def CarreVigenere () : """creation du carre de Vigenere""" al = "abcdefghijklmnopqrstuvwxyz" al = al.upper () carre = [] for i in range (0,26) : carre.append (al) al = al [1:26] + al [0] return carre def CodeVigenere (message, cle, carre) : """code un message selon le code de Vigenere, message est le message a coder cle est la cle carre est le carre de Vigenere""" alphabet = carre [0] # contient l'alphabet (premiere ligne du carre) resultat = "" # contiendra le message code # on parcourt le message for i in range (0, len (message)) : # j est la position de la lettre dans le cle # associee a la lettre i dans le message # % retourne le reste d'une division entiere j = i % len (cle) a = alphabet.find (message [i]) # numero de la lettre message [i] b = alphabet.find (cle [j]) # numero de la lettre cle [j] c = carre [b][a] resultat += c return resultat def DecodeVigenere (message, cle, carre) : """decode un message selon le code de Vigenere, message est le message a decoder cle est la cle carre est le carre de Vigenere""" alphabet = carre [0] # contient l'alphabet (premiere ligne du carre) resultat = "" # contiendra le message code # on parcourt le message for i in range (0, len (message)) : # j est la position de la lettre dans le cle # associee a la lettre i dans le message # % retourne le reste d'une division entiere j = i % len (cle) b = alphabet.find (cle [j]) # numero de la lettre cle [j] a = carre [b].find (message [i]) # numero de la lettre message [i] # dans la ligne du carre correspondant # au decalage introduit par cle [j] c = carre [0][a] resultat += c return resultat message = "ceci est le message non code sans signe de ponctuation" message = message.replace (" ", "") message = message.upper () cle = "VIGENERES" carre = CarreVigenere () code = CodeVigenere (message, cle, carre) decode = DecodeVigenere (code, cle, carre) print "------------------ cle" print cle print "------------------ message" print message print "------------------ message code" print code print "------------------ message decode" print decode print "------------------" if decode == message : print "message bien retranscrit" else : print "message mal retranscrit" ############################################################################# ############################################################################# ############################################################################# print "" print "####################################################################" print "seconde partie : decoder sans la cle" print "cette methode ne marche que sur un message plus long ou de nombreux" print "message mis bout a bout, on essaye la methode sur le fichier :" print "hugo_dernier_jour_condamne.txt" print "####################################################################" def PGCD (m,n) : """determine le PGCD""" if m == 1 or n == 1 : return 1 if m == n : return m if m < n : return PGCD (m, n-m) return PGCD (n, m-n) def DecodeVigenereLongueurCle (message, mot = 3) : """cette fonction determine la longueur de la cle, elle repere les groupes de trois lettres qui se repete dans le message code et suppose qu'il y une tres forte probabilite qu'un meme groupe de trois soit code avec les memes trois lettres du message et les memes trois lettres de la cle message : .....DES...........DES...........DES.........DES....DES cle : ABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCD code : .....EGV.........................EGV.........EGV.......... distance : <----------24--------------><----8-----> la longueur de la cle divise le PGCD de 24 et 8 """ al = "abcdefghijklmnopqrstuvwxyz" al = al.upper () # parcours du message pour recenser toutes les positions dico = {} for i in xrange (0, len (message)-2) : t = message [i:i+mot] if dico.has_key (t) : dico [t].append (i) else : dico [t] = [i] # on va garder toutes les distances entre # entre deux occurrences du meme mot de n lettres dis = [] for d in dico : p = dico [d] if len (p) > 1 : for i in range (0, len (p)-1) : #print d, p [i+1] - p [i], " --- ", float (p [i+1] - p [i]) / 8 dis.append ( p [i+1] - p [i] ) # on extrait le PGCD if len (dis) == 0 : print "impossible de determiner la cle" return 0 if len (dis) == 1 : return dis [0] longueur = PGCD (dis [0], dis [1]) for d in dis : longueur = PGCD (longueur, d) if longueur > 5 : # si la longueur est suffisante, le resultat a des chances d'etre bon return longueur else : # sinon, on relance l'algorithme avec des mots plus grand return DecodeVigenereLongueurCle (message, mot+1) def DecodeVigenereCle (code, l) : """determine la cle du message code, connaissant sa longueur, on suppose que la lettre E est la lettre la plus frequente """ al = "abcdefghijklmnopqrstuvwxyz" al = al.upper () cle = "" for i in xrange (0, l) : nombre = [ 0 for a in al] sous = code [i:len (code):l] # on extrait toutes les lettres # i, i+l, i+2l; i+3l, ... # on compte les lettres for k in sous : nombre [ al.find (k) ] += 1 # on cherche le maximum p = 0 for k in range (0, len (nombre)) : if nombre [k] > nombre [p] : p = k # on suppose que al [p] est la lettre E code, # il ne reste plus qu'a trouver la lettre de la cle # qui a permis de coder E en al [p] cle += al [ (p + 26 - al.find ("E")) % 26 ] return cle # on lit Victor Hugo f = open ("hugo_dernier_jour_condamne.txt") message = f.read () # lit tout d'une seule traite f.close () # on limite la taille du fichier message = message [5000:7000] # on enleve les signes de ponctuation et on met en majuscule message = message.replace ("\n", "") message = message.replace ("\r", "") message = message.replace ("\t", "") message = message.replace (" ", "") message = message.replace (",", "") message = message.replace (";", "") message = message.replace (":", "") message = message.replace (".", "") message = message.replace ("'", "") message = message.replace ("\"", "") message = message.replace ("-", "") message = message.replace ("!", "") message = message.replace ("?", "") message = message.replace ("(", "") message = message.replace (")", "") message = message.upper () # on code print "on code, longueur du message ", len (message) code = CodeVigenere (message, cle, carre) memoire = cle cle = None # on oublie la cle # on determine la longueur de la cle l = DecodeVigenereLongueurCle (code) # on determine la cle en suppose que la lettre E est la plus frequente # ne marche pas pour les textes anglais cle_code = DecodeVigenereCle (code, l) # decode le texte decode = DecodeVigenere (code, cle_code, carre) print "------------------ vraie" print memoire print "------------------ cle trouve par Babbage" print "longueur ", l, " cle : ", cle_code if memoire == cle_code : print "bonne cle" else : print "mauvaise cle" print "------------------ message" print message [:200] print "------------------ message code" print code [:200] print "------------------ message decode" print decode [:200] print "------------------" if decode == message : print "message bien retranscrit" else : for i in xrange (0, len (decode)) : if message[i] != decode [i] : print i, message[i], decode[i] print "message mal retranscrit"