Skip to content

Instantly share code, notes, and snippets.

@lefuturiste
Created December 20, 2020 14:31
Show Gist options
  • Save lefuturiste/8a1b91c4365c888be8cc9911f0de35e5 to your computer and use it in GitHub Desktop.
Save lefuturiste/8a1b91c4365c888be8cc9911f0de35e5 to your computer and use it in GitHub Desktop.
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