Outils pour utilisateurs

Outils du site


nsi:terminales:securite:rsa

Ceci est une ancienne révision du document !



Warning: Undefined array key 1 in /home/goupillf/wiki.goupill.fr/lib/plugins/codeprettify/syntax/code.php on line 172

Warning: Undefined array key 1 in /home/goupillf/wiki.goupill.fr/lib/plugins/codeprettify/syntax/code.php on line 172

Warning: Undefined array key 1 in /home/goupillf/wiki.goupill.fr/lib/plugins/codeprettify/syntax/code.php on line 172

Warning: Undefined array key 2 in /home/goupillf/wiki.goupill.fr/lib/plugins/codeprettify/syntax/code.php on line 214

Warning: Undefined array key 2 in /home/goupillf/wiki.goupill.fr/lib/plugins/codeprettify/syntax/code.php on line 214

Warning: Undefined array key 2 in /home/goupillf/wiki.goupill.fr/lib/plugins/codeprettify/syntax/code.php on line 214

Warning: Undefined array key 2 in /home/goupillf/wiki.goupill.fr/lib/plugins/codeprettify/syntax/code.php on line 214

Warning: Undefined array key 2 in /home/goupillf/wiki.goupill.fr/lib/plugins/codeprettify/syntax/code.php on line 214

Warning: Undefined array key 2 in /home/goupillf/wiki.goupill.fr/lib/plugins/codeprettify/syntax/code.php on line 214

Chiffrement RSA

Nommé selon les initiales de ses inventeurs, en 1977 : Ronald Rivest, Adi Shamir et Leonard Adleman. Il s'agit d'un chiffre asymétrique, c'est à dire que la clé pour chiffrer est différente de la clé pour chiffrer.

Comme pour le chiffre de ElGamal, RSA exploite des propriétés arithmétiques des nombres premiers.

Cette technique avait déjà été découverte à Bletchley Park lors de la seconde guerre mondiale. Il s'agit du centre de renseignement où a été créé le fameux Colossus, calculateur destiné à casser le code Enigma utilisé par l'armée allemande. Mais cette invention, couverte par le secret défense, n'a pu être revendiquée par les Britanniques.

Création des clés publique et privée

Nombres premiers

Nous allons utiliser des nombres premiers. Pour les démonstrations, des nombres premiers peuvent suffire. Vous en trouverez une liste ici.

Mais la solidité de RSA est garantie par l'utilisation de nombres premiers très grands : de l'ordre de 500 à 1000 bits. $2^{1000} \approx 1000^{100} = 1\overbrace{000\cdots0}^{300\times}$.

À cette échelle, les nombres premiers sont trop nombreux pour être catalogués ou même recherchés de faaçon systématique. On se contente d'en choisir au hasard – voir cet exercice.

L'idée est de choisir aléatoirement un nombre de 512 bits et de faire une série de tests pour savoir s'il est premier. La série de tests pour chaque essai est suffisamment rapide et on sait qu'on a aux alentours de $\frac{1}{300}$ chance de trouver un premier dans cet zone. On trouve donc un premier assez vite au hasard.

Ces premiers étant très nombreux, la probabilité que deux personnes trouvent une même paire de premiers est négligeable.

Méthode

  • Choisir $p$ et $q$ deux premiers.
    Il existe quelques conditions pour que le chiffrement reste solide et évite certaines techniques de déchiffrement. Nous n'entrerons pas dans ces détails mais si vous êtes curieux, voir sur Wikipedia.
  • Calculer $n = p\times q$.
  • Calculer $\varphi = (p-1)\times(q-1)$.
  • Choisir $e$ premier avec $\varphi$ et inférieur.
    On peut choisir $e$ premier, ce qui garantit que $e$ sera premier avec $\varphi$.
    Pour faciliter les calculs, on préfère un $e$ dont l'écriture binaire n'ait pas trop de 1. On peut choisir 3, 17 – pour les expérimentations – ou encore 65537.
  • Calculer $d$, inverse modulaire de $e \mod \varphi$.

Clé publique

La paire $(n,e)$ constitue la clé publique.

Clé privée

La paire $(n,d)$ constitue la clé privée.

À faire

Quelques questions

  1. Si je vous donne $(n, e) = (143, 17)$,
    • trouvez $p$ et $q$,
    • déduisez-en $\varphi$,
    • déduisez-en $d$.
  2. Si je vous donne $(n,e) = (261\,589, 17)$, même question.

Vous voyez que c'est beaucoup plus long dans le second cas. Ce serait infaisable avec un $n$ de grande taille comme ce qu'on utilise avec RSA.

Implémentation

Écrivez une fonction Python make_keys(p, q) qui reçoit les premiers p et q et renvoie Kpu = (n,e) et Kpr = (n,d).

Optionnel : Pour aller plus loin, vous pouvez utiliser cet exercice pour produire des premiers de taille voulue et écrire make_keys(nbits)nbits est un entier pair, par exemple 100. Dans cette version, on génère 2 premiers de nbits//2 bits puis on produit les paires Kpu et Kpr. Vous pouvez toujours choisir e parmi 3, 17, 65537 selon la taille des premiers considérés.

Taille de la clé

Si je transmet le message m, un entier, il doit être inférieur à n. Le message chiffré mc sera lui aussi inférieur à n.

Comme m et mc seront à un moment écrits sous forme d'octets bytes, il pourra être utile de connaître la taille de n quand il est écrit sous la forme bytes.

On écrit donc une fonction pour trouver la taille de n.

def octets_size(n):
    """
    n: entier positif
    renvoie le nombre d'octets nécessaires pour écrire n.
    """
    s = 0
    while n > 0:
        n = n //256
        s += 1
    return s

Ajoutez la fonction à votre programme.

Chiffrer

Soit un message mb de type bytes et la clé publique Kpu = (n, e).

Il faut transformer mb dans le nombre entier m correspondant :

>>> m = int.from_bytes(mb, 'big')

L'argument 'big' indique dans quel ordre est écrit le nombre. Mais cela n'a pas d'importance tant qu'on utilise le même ordre au chiffrement et au déchiffrement.

condition : Il faut m < n.

Le calcul du message chiffré est tout simplement $m' \overset{n}{=}m^e$.

Pour le calcul $mc \overset{n}{=}m^e$ on utilisera l'exponentielle modulaire définie dans exponentiation_modulaire.

Il faut enfin transformé le message chiffré mc dans le type bytes. On peut écrire :

>>> s = octets_size(n)
>>> mcb = mc.to_bytes(s, 'big')

À faire

Écrivez une fonction chiffrer_RSA(mb, Kpu)mb est le message de type bytes, Kpu est la clé publique, et qui renvoie le message chiffré sous la forme bytes.

Déchiffrer

C'est exactement la même chose mais en utilisant $Kpr$ au lieu de $Kpu$.

À faire

Écrivez une fonction dechiffrer_RSA(mcb, Kpr)mcb est le message chiffré de type bytes, Kpr est la clé privée, et qui renvoie le message déchiffré sous la forme bytes.

À faire

  • Écrire une fonction dechiffrer_RSA(Kc, Kpr)
  • Placer un texte quelconque dans un fichier cle.txt
  • K est obtenu en lisant le contenu de cle.txt en mode binaire.
  • Choisissez Kpu et Kpr de sorte que 255 < n < 65536
    Vous pourrez faire plus grand si cela fonctionne.
  • Calculez Kc = chiffrer_RSA(K, Kpu)
  • Vérifiez : assert dechiffrer_RSA(Kc, Kpr) == K.

Justification

D'après le petit théorème de Fermat, on sait que si $q$ premier, pour $a$ non divisible par $q$, alors $a^{q-1} \overset{q}{\equiv} 1$.

Donc, prenons $B$ un élément de $K$.

  • $C \overset{n}{\equiv} B^e$
  • donc $C^d \overset{n}{\equiv} \left(B^e\right)^d = B^{e\cdot d}$
  • on sait que $e\cdot d \overset{(p-1)(q-1)}{\equiv} 1$ donc $e\cdot d = 1 + k\cdot(p-1)(q-1)$ pour un certain $k$ (dont la valeur n'a pas d'importance)
  • donc $C^d \overset{n}{\equiv} B^{1 + k\cdot(p-1)(q-1)}$
  • Supposons que $B$ n'est pas divisible par $q$, on aura
    $B^{q-1} \overset{q}{\equiv} 1$ et donc $B^{1 + k\cdot(p-1)(q-1)} = B\cdot \left(B^{q-1}\right)^{k\cdot (p-1)} \overset{q}{\equiv} B \cdot 1 = B$
  • De même si $B$ n'est pas divisible par $p$, $B^{1 + k\cdot(p-1)(q-1)} \overset{p}{\equiv} B \cdot B$
  • On peut raisonner dans le cas où $B$ serait multiple de $p$ ou $q$, je ne le fais pas ici.
  • On déduit que $C^d \overset{q}{\equiv} B$ et $C^d \overset{p}{\equiv} B$, ce qui signifie que $C^d - B$ est multiple de $p$ et $q$, donc de $n = pq$ et donc $C^d - B \overset{n}{\equiv} 0$
  • On conclut que $C^d \overset{n}{\equiv} = B$.
nsi/terminales/securite/rsa.1680208566.txt.gz · Dernière modification : de goupillwiki