Created
December 20, 2020 14:31
-
-
Save lefuturiste/8a1b91c4365c888be8cc9911f0de35e5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
abc = 'abcdefghijklmnopqrstuvwxyz' | |
stat = [[7.62, 'a'], [1.03, 'b'], [3.04, 'c'], [3.24, 'd'], [17.07, 'e'], [0.88, 'f'], [0.83, 'g'], [0.83, 'h'], [8.29, 'i'], [1.15, 'j'], [0.0, 'k'], [5.57, 'l'], [3.08, 'm'], [6.96, 'n'], [5.38, 'o'], [3.32, 'p'], [1.1, 'q'], [6.46, 'r'], [8.2, 's'], [7.51, 't'], [6.38, 'u'], [1.41, 'v'], [0.0, 'w'], [0.38, 'x'], [0.19, 'y'], [0.1, 'z']] | |
def decrypt(cipher, stat): | |
""" Décrypter un texte grâce à une attaque par statistique | |
Parameters | |
---------- | |
cipher : str | |
La chaine de caractère à décrypter | |
stat : str | |
Les statistiques de référence à utiliser pour ce texte | |
Returns | |
------- | |
Un couple contenant la clé de chiffrement utilisé et le texte décrypté | |
""" | |
# on trie la liste statistique par ordre décroissant | |
# avec une lambda, on spécifie un critère de tri (ici la première valeur de chaque élément) | |
stat.sort(reverse=True, key=lambda e: e[0]) | |
# on filtre le cipher pour ne garder que les lettres de l'alphabet | |
cipherFiltered = list(filter(lambda x: x in abc, cipher)) | |
# on va créer une liste de même dimension que 'stat' qui contient l'occurence de chaque lettre dans le cipher | |
cipherStat = [[0, e] for e in abc] | |
for char in cipherFiltered: | |
cipherStat[abc.index(char)][0] += 1 | |
# on trie cette nouvelle liste de la même manière que la liste 'stat' | |
cipherStat.sort(reverse=True, key=lambda e: e[0]) | |
# ensuite on cherche la liste nous donnant les permutation à effectuer pour | |
# passer du texte de base au cipher appellé 'encryptionMap' (il s'agit donc de la clé de chiffrement) | |
decryptionMap = [0]*len(abc) | |
encryptionMap = [0]*len(abc) | |
for i in range(len(cipherStat)): | |
cipherLetter = cipherStat[i][1] | |
originalLetter = stat[i][1] | |
encryptionMap[abc.index(originalLetter)] = cipherLetter | |
# donc la lettre la plus récurrence correspond à la lettre la plus récurrente de la statistique donné | |
# enfin, on va reconsituer la chaine de caractère de base. | |
# pour chaque caractère du cipher: | |
# - si c'est un caractère spécial, on ne fait rien, on l'ajoute tel quel | |
# - sinon on regarde grâce à 'encryptionMap' le caractère par lequel il faut remplacer | |
decoded = '' | |
for char in cipher: | |
decoded += abc[encryptionMap.index(char)] if char in abc else char | |
return encryptionMap, decoded | |
# Utilisation de la fonction 'decrypt': | |
# on ouvre le texte chiffré : c'est le cipher | |
file = open('chiffre.txt', 'rt') | |
cipher = file.read() | |
file.close() | |
encryptionMap, decoded = decrypt(cipher, stat) | |
# hack pas propre: on sait que en fait les g deviennet des h | |
# problème à cause que g et h on la même statistique (0.83) du coup c'est triste | |
new = '' | |
for c in decoded: | |
if c == 'g': | |
new += 'h' | |
elif c == 'h': | |
new += 'g' | |
else: | |
new += c | |
print(new) | |
print(encryptionMap) | |
# on sauvegarde le texte décrypté sur le disque | |
output = open('output.txt', 'wt') | |
output.write(new) | |
output.close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment