Matrix
comme dans le TP 2from sympy import *
import sympy as sy
x= sy.symbols('x')
y= sy.symbols('y')
add=sy.Lambda([x,y], (x+y)%5)
sy.Matrix(5,5,add) # pour l'addition
mult=sy.Lambda([x,y], (x*y)%5)
sy.Matrix(5,5,mult) # pour la multiplication
CoprimeQ
qui prend en entrée deux entiers et qui renvoie True
si les entiers sont premiers entre euxdef CoprimeQ(n,m):
return gcd(n,m)==1
CoprimeQ(3,11)
Sympy
. La fonction floor
se trouve dans la librairie math
mais corresond aussi à la division entière //
. Les variables Q
et R
ne peuvent pas être des tuples (il n'y a pas d'arithmétique des tuples).def euclideEtendu(q,r):
if q>=r: raise Exception("q >= r")
Q=sy.Matrix([1, 0])
R=sy.Matrix([0, 1])
while r !=0:
t=q%r
T=Q-(q//r)*R
print(q,r,t,Q,(q//r),R,T)
q,r = r,t
Q,R=R,T
return (Q,q)
euclideEtendu(11,26)
gcdex(11,26)
Pour comprendre le fonctionnement, remplissez le tableau qui trace les valeurs de q,r,t,Q,floor(q/r),R,T
.
modinv
qui prend en entrée a
et m
et qui renvoie l'inverse de a
modulo m
s'il existe et retourne une erreur sinondef modinv(a,m):
d=gcd(a,m)
if d==1:
return gcdex(a,m)[0]
else:
if d%b!=0: raise Exception("Pas d'inverse")
else:
return d*modinv(a/d, m/d)
modinv(3,26)
def exponentMod(a,b,p):
res=1
loop=0
for i in bin(b)[2:]:
res=(res*res)%p
if i=='1':
res=(res*a)%p
print(loop,i,res**2, res)
loop+=1
return(res)
exponentMod(17,73,100)
genCle
qui prend en entrée une taille (celle de la clé) exprimée en octets (1 octet = 8 bits) et qui retourne le tuple composé de l'entier $p$ et de l'entier $q$.def genCle(o):
o=o*4
p=randprime(2**(o-1), 2**o)
q=randprime(2**(o-1), 2**o)
cle=(p,q)
return(cle)
genCle(4)
clePub
et clePriv
qui ont un fonctionnement analogue à rsa_public_key
et rsa_private_key
. N'oubliez pas de fournir la valeur de e
.def clePub(p,q,e):
return (p*q,e)
def clePriv(p,q,e):
n=p*q
phi=(p-1)*(q-1)
d= modinv(e,phi)
cle=(n,d)
return cle
RSA
en Python
qui prend en entrée :def rsa(m,cle):
return pow(m,cle[1],cle[0])
rsa(3,(509,11))
RSA
pour construire RSAEnc
et RDADec
dont le comportement est analogue à encipher_rsa(m,pk)
et decipher_rsa(c,dk)
de l'implémentation RSA de Sympy
.def RSAEnc(m,pub):
return rsa(m,pub)
RSAEnc(3,(509*521,11))
def RSADec(c,priv):
return rsa(c,priv)
RSADec(177147,(509*521,216131))
RSAEnc
et RSADec
pour qu'elles pemettent de chiffrer et de déchiffer des chaines de caractères.DEFAULT_BLOCK_SIZE = 128 # taille bloc doit être inférieure à la taille de la clé et elle est en octets
BYTE_SIZE=256 # un octet a 2**8=256 valeurs possibles
def Text2Ints(message,blockSize=DEFAULT_BLOCK_SIZE):
# convertit une chaine en une liste de blocs d'entiers.
# chaque entier représente 'blockSize' caractères de la chaîne
messageBytes=message.encode('ascii')
# convertit la chaine en octets
blockInts=[]
# initialise la liste de s entiers
for blockStart in range(0,len(messageBytes),blockSize):
# calculer l'entier correspondant au bloc de texte
blockInt=0
for i in range(blockStart,min(blockStart+blockSize,len(messageBytes))):
blockInt += int(messageBytes[i])*(BYTE_SIZE ** (i%blockSize))
blockInts.append(blockInt)
return blockInts
def Ints2Text(blockInts,messageLength,blockSize=DEFAULT_BLOCK_SIZE) :
# convertit une liste de blocs d'entiers et retourne la chaine correspondante.
# on a besoin de la longueur du message passée dans messageLeng th pour convertir
# le dernier bloc d'entier
message=[]
for blockInt in blockInts:
blockMessage=[]
# initialise la liste qui contiendr a les caractères
for i in range(blockSize-1,-1,-1):
if len(message)+i < messageLength:
# décode la chaine des 'blockSize' caractères depui s ce bloc d'entier
charNumber=blockInt//(BYTE_SIZE**i)
# on passe au bloc suivant
blockInt=blockInt%(BYTE_SIZE**i)
blockMessage.insert(0,bytes([charNumber]).decode('a scii'))
message.extend(blockMessage)
return ''.join(message)
def RSAEncMessage(message,pub):
m=Text2Ints(message)
crypt=""
for block in m:
crypt=crypt+Ints2Text(RSAEnc(block,pub))
return crypt
def RSADecMessage(crypt,priv):
crypt=Text2Ints(message)
message=""
for block in crypt:
message=message+Ints2Text(RSAEnc(block,priv))
return message