Chiffrement RSA

Fermé
Cthiry Messages postés 2 Date d'inscription mardi 31 mai 2022 Statut Membre Dernière intervention 31 mai 2022 - 31 mai 2022 à 09:27
yg_be Messages postés 22710 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 avril 2024 - 31 mai 2022 à 17:09
Bonjour,
je suis actuellement sur un projet de minitchat "sécurisé" et donc bien sûr j'ai besoin de la cryptographie RSA. J'ai donc réussi à générer des clés me semblant cohérentes sauf que le chiffrage ou le déchiffrage ne fonctionne pas certaines fois.
Par exemple, avec la clé publique (17,1333) et la clé privée (593,1333) c'est bon puisque le message déchiffré (à droite) est le même que le message d'origine (à gauche)

et d'autres fois, par exemple avec la clé publique (7,143) et la clé privée (103,143), le message décodé ne correspond pas au message d'origine


Voici mon code folklorique puisqu'il est en POO (ça me fait rire moi-même, à voir plus tard si je change ce délire occulte)
et aussi, j'ai recodé moi même les algorithmes l'aide du document https://jpq.pagesperso-orange.fr/divers/rsa/rsa.pdf
#chiffrement assymétrique
#si cela apparaît encore c'est que l'algorithme n'est pas fiable à 100% : certaines fois le cryptage décryptage fonctionne parfaitement et d'autres fois des erreurs se glissent... Peut-être des nombres trop gros ?
from random import randint
class Assymetrique:
    """classe représentant un système de chiffrement ASsymétrique
    ATTRIBUTS :
     - p : premier nombre premier à choisir (soi-m^me ou aléatoirement)
     - q : deuxième nombre premier à choisir (soi-m^me ou aléatoirement)
     - n : p*q
     - M : (p-1)*(q-1)
     - publique : clé publique (à faire passer au serveur pour qu'il chiffre la clé symétrique
     -privee : clé privée (pour déchiffrer l'information venue du serveur)
     +++++++++++++++
     MÉTHODES :
     - genere_cle_publique() : cherche 4 nombres e premiers et en séletionne un au hasard avec M et renvoie le tuple (e,n)
     - genere_cle_privee() : cherche le premier entier d tel que d*e congru à 1 [M]
     - chiffre(message) : chiffre le message passé en paramètre
     - dechiffre(message) : déchiffre le message passé en paramètre
     SOURCES pour la generation des clés :
     https://jpq.pagesperso-orange.fr/divers/rsa/rsa.pdf
     """

    def __init__(self,p=None,q=None):
        """constructeur de la classe Assymetrique,
        prend en paramètre deux nombres premiers et génère les clés publique et privée asociée
        ou si les entiers ne sont pas renseignés ou pas premiers, ils sont générés aléatoirement"""
        if p==None or q==None or not(est_premier(p)) or not(est_premier(q)):
            liste_premiers=nbr_premiers()
            #print("les indices de la liste vont de 0 à ",len(liste_premiers)-1)
            if p==None:
                ind_p=randint(0,len(liste_premiers)-1)#on choisit aléatoirement l'indice du nombre p parmi les indices de la liste de nombre premiers
                #print("indice de p= ",ind_p)
                p=liste_premiers[ind_p]
                liste_premiers.remove(p)#on enlève p pour éviter de le rechoisir
            if q==None:
                if p in liste_premiers:
                    liste_premiers.remove(p)#on enlève p de la liste mais on verifie qu'il y est sinon erreur
                ind_q=randint(0,len(liste_premiers)-1)#on choisit aléatoirement l'indice du nombre q parmi les indices de la liste de nombre premiers
                #print("indice de q= ",ind_q)
                q=liste_premiers[ind_q]
        #on affecte les valeurs dont on a besoin pour calculer les clés aux attributs p, q, n, M
        self.p=p
        self.q=q
        #print(f"p={p} et q ={q}")
        self.n=self.p*self.q
        self.M=(self.p-1)*(self.q-1)
        #on genere les clés
        self.publique=self.genere_cle_publique()
        #print("cle_publique ok")
        self.privee=self.genere_cle_privee()
        #print("cle privee ok")



    def genere_cle_publique(self):
        e=1#e ne peut être qu'impair
        j=e+2#on essaie donc tous les nombres impairs de 3 à M exclu
        b=True # et on s'arrête au 3ème e trouvé mais on pourrait continuer
        i=0
        e_possibles=[]
        while b and j<self.M:
            #print("j= ",j)
            i1=self.M#on applique l'algorithme d'euclide à (p-1)(q-1) et j
            j1=j
            k=i1%j1
            while k>1:
                k=i1%j1
                i1=j1
                j1=k
                #print("k= ",k)
            if k==0:
                j+=2#k=0 ça ne va pas
            else:
                i+=1
                e_possibles.append(j)
                j=j+2
                #print(e_possibles)
                if i==4:
                    b=False
        if b:
            print("pas de e dans l'intervalle [3;M[")
        else:
            #print(e_possibles)
            e=e_possibles[randint(0,len(e_possibles)-1)]
        return (int(e),self.n)

    def genere_cle_privee(self):
        """recherche le premier entier d =k*M+1 divisible par e"""
        i=1
        e=self.publique[0]
        while i%e!=0:
            i=i+self.M
        d=i/e
        return (int(d),self.n)

    def chiffre(self,message):
        """prend un message en paramètre et le retourne chiffré"""
        #print("+++++on chiffre+++++")
        e=self.publique[0]
        n=self.n
        message_code=""
        for lettre in message:
            code_lettre=(ord(lettre)**e)%n
            #print(f"{ord(lettre)}->{code_lettre}")
            message_code+=chr(int(code_lettre))
        return message_code

    def dechiffre(self,message_code):
        """prend un message chiffré en paramètre et le retorne déchiffré"""
        #print("+++++on déchiffre+++++")
        d=self.privee[0]
        n=self.n
        message_en_clair=""
        for lettre in message_code:
            decode_lettre=(ord(lettre)**d)%n
            #print(f"{ord(lettre)}->{decode_lettre}")
            message_en_clair+=chr(decode_lettre)
        return message_en_clair







def nbr_premiers(n=50):
    """prend en paramètre un nombre entier n et retourne la liste des nombres_premiers infèrieurs à n
    ici n est utilisé avec la valeur 50 car sur l'ordinateur de test, une liste avec plus d'entiers premiers ammène à des valeurs trop autes dans les calculs ce qui renvoie une erreur"""
    l=[2,3,5,7,11]
    for i in range(13,n,2):#2on avance de 2 en 2 car les nombres premiers sont tous impairs
        if est_premier(i):
            l.append(i)
    return l

def est_premier(n):
    """vérifie si le nombre entier passé en paramètre est premier, True si oui False sinon"""
    for i in range(2,n):
        if n%i==0:
            return False
    return True

if __name__=='__main__':
    chiffrement=Assymetrique()
    print(chiffrement.publique)
    print(chiffrement.privee)
    messages=["bonjour le monde","moi je vais très bien","EEEEETTTTT toi ?","ééééé"]
    for message in messages:
        code=chiffrement.chiffre(message)
        decode=chiffrement.dechiffre(code)
        assert(len(message)==len(code)and len(message)==len(decode))
        print(message,decode)
    #assert message==decode



Configuration: Windows / Chrome 102.0.5005.61

2 réponses

yg_be Messages postés 22710 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 avril 2024 1 474
31 mai 2022 à 12:07
bonjour,
je pense que tu as un souci quand tu utilises des nombres premiers trop petits.
0
Cthiry Messages postés 2 Date d'inscription mardi 31 mai 2022 Statut Membre Dernière intervention 31 mai 2022
31 mai 2022 à 16:02
Merci pour la réponse, en orientant mes recherches vers cette idée, j'ai vu que si p et q sont choisis tels que n=p*q <255 alors le chiffrement n'est pas bijectif.
0
yg_be Messages postés 22710 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 avril 2024 1 474 > Cthiry Messages postés 2 Date d'inscription mardi 31 mai 2022 Statut Membre Dernière intervention 31 mai 2022
31 mai 2022 à 16:16
Ce qui explique que je n'avais plus de soucis en prenant des nombres premiers >=17.
0
yg_be Messages postés 22710 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 avril 2024 1 474
31 mai 2022 à 17:09
Il n'est pas du tout normal que tu puisses facilement calculer la clé privée à partir de la clé publique. Cela va à l'encontre du bon sens.

En fait, tu as inversé le sens de public et de privé.
0