Cryptographie
´
Elements de correction
TP1 d’informatique deuxi`eme ann´ee
Vu que vous avez tous r´eussi les questions, les principaux enseignements que vous trouverez dans ce
document sont une fa¸con propre de faire le chiffrement de C´esar et des informations sur les diff´erentes fa¸cons
de parcourir et de construire des s´equences (listes, chaˆınes, ...). Le fait qu’une boucle for puisse parcourir
toute sorte de s´equence ordonn´ee (les types it´erables), et la construction d’une liste par compr´ehension, qui
est plus rapide `a ´ecrire, quand on comprend bien ce qu’elle fait.
Lisez bien la partie sur la fonction sans combi, et surtout la diff´erence entre liste.append(element)
et liste=liste+[element] ! Faites VRAIMENT l’exp´erience de comparer les deux versions sur un texte
un peu long comme votre oeuvre compl`ete !
Pr´eliminaire : pour le faire soi-mˆeme on utilise une boucle for. En python cette boucle peut it´erer sur
tout ce qui repr´esente une s´equence : un range, une liste, une chaˆıne... On a donc ici deux possibilit´es
naturelles : it´erer sur le range des indices, ou sur la liste elle-mˆeme.
def rassembler(liste):
s=’’
for iin range(len(liste)): #iteration sur les indices
s=s+liste[i]
return s
def rassembler(liste):
s=’’
for chaine in liste: #iteration sur la liste
s=s+chaine
return s
Sinon, voir help(str.join), et essayer s="xxx".join(["nous","sommes","r´eunies"]),
puis s="".join(["nous","sommes","r´eunies"]).
Unicode
10FFFF16 = 1 ×165+ 0 ×164+ 15 ×163+ 15 ×162+ 15 ×161+ 15 ×160. Pour donner `a python un
nombre repr´esent´e en base 2 (binaire), 8 (octale), ou 16 (h´exad´ecimale), on le pr´efixe d’un z´ero et de
la lettre b,o, ou x. Donc python donne la r´eponse `a la premi`ere question si on lui demande de calculer
0x10FFFF+1. Un peu plus d’un million de codepoints : de quoi encoder l’ensemble des caract`eres de
toutes les langues, chinois compris.
Fabriquer la liste des majuscules ["A","B",...,"Z"].
eponse : Ce sont les codepoints 65 `a 90, donc :
alpha=[]
for iin range(65,91):
alpha.append(chr(i))
1
ou encore, en d´efinissant cette liste par compr´ehension :
alpha=[chr(i) for iin range(65,91)]
´
Ecrire une fonction qui prend un texte en argument et retourne le mˆeme texte o`u tous les caract`eres
de combinaison ont disparu :
On ne peut pas modifier une chaˆıne de caract`eres, c’est pourquoi on doit construire une nouvelle chaˆıne.
On d´ecompose notre texte pour s´eparer les lettres de leurs accents, et on copie tous ses caract`eres qui
ne sont pas des caract`eres de combinaison.
On utilise une boucle for, et on peut soit it´erer sur la chaˆıne de caract`eres elle-mˆeme, soit it´erer sur
un ensemble d’indices (entiers). Voir les deux versions ci-dessous :
def sans_combi(texte):
s=unicodedata.normalize("NFD",texte)
nouveau_texte=""
for caractere in s: # iteration sur la chaine
if unicodedata.combining(caractere)==0:
nouveau_texte=nouveau_texte+caractere
return nouveau_texte
def sans_combi(texte):
s=unicodedata.normalize("NFD",texte)
nouveau_texte=""
for iin range(len(s)): #iteration sur les indices
if unicodedata.combining(s[i])==0:
nouveau_texte=nouveau_texte+s[i]
return nouveau_texte
Certains ont pr´ef´er´e construire une liste au lieu de construire une chaˆıne de caract`eres, puis `a la fin
rassembler la liste en une seule chaˆıne. Mais attention ! Pour construire une liste ´el´ement par ´el´ement
on utilise liste.append(element) qui modifie l’objet liste, et surtout pas liste=liste+[element],
qui cr´ee une toute nouvelle liste puis la remplit avec le contenu de l’ancienne et le nouvel ´el´ement !
def sans_combi(texte):
s=unicodedata.normalize("NFD",texte)
nouvelle_liste=[]
for iin range(len(s)):
if unicodedata.combining(s[i])==0:
nouvelle_liste.append(s[i])
# remplacez la ligne ci-dessus par : nouvelle_liste=nouvelle_liste+[s[i]]
# et comparez le temps d’execution sur une chaine de 10^5 ou 10^6 caracteres.
return rassembler(nouvelle_liste)
On peut aussi construire cette liste “par compr´ehension” :
def sans_combi(texte):
s=unicodedata.normalize("NFD",texte)
nouvelle_liste=[c for cin sif unicodedata.combining(c)==0]
return rassembler(nouvelle_liste)
Toutes ces solutions sont correctes et se valent `a peu pr`es du point de vue du temps de calcul.
Fonction clean :
2
def clean(texte):
return sans_combi( texte.upper() )
# ou bien :
return sans_combi(texte).upper()
Chiffrement de C´esar
Il en existe 25 versions si on ne compte pas la fonction identit´e comme un chiffrement.
´
Ecrire une fonction cesar caractere(c,k) qui retourne le caract`ere cecal´e de krangs dans l’alphabet
si c’est une lettre majuscule, et retourne cinchang´e sinon :
Pour tester si on a affaire `a une lettre majuscule, il suffit de v´erifier si son codepoint est entre 65
et 90. Ce test est plus rapide que de parcourir la liste des lettres majuscules pour v´erifier si cs’y
trouve. Concernant le d´ecalage de krangs, vous avez presque tous pu vous rendre compte qu’une
solution pas assez rigoureuse `a ce genre de question m`ene `a une longue s´eance de d´ebuggage. Donc
proc´edons m´ethodiquement : prenons notre lettre, et consid´erons son codepoint. Changeons-le en
un nombre entre 0 et 25 en retranchant 65. Ajoutons ket ramenons-nous dans l’intervalle [[0,25]] `a
l’aide de l’op´erateur modulo : %. Ajoutons 65 pour obtenir le codepoint de la lettre correspondante, et
appliquons chr pour avoir cette lettre :
def cesar_caractere(c,k):
codepoint=ord(c)
if codepoint <65or codepoint > 90:
return c
else :
numero=codepoint-65
numero_decale=(numero+65)%26
codepoint_decale=65+numero_decale
return chr(codepoint_decale)
Cette fonction fonctionne avec n’importe quel kZ.
´
Ecrire une fonction cesar(s,k) qui chiffre un texte avec le code de C´esar avec le d´ecalage fourni.
Comme pour retirer les caract`eres de combinaison, on avait le choix entre plein de variantes tr`es proches
les unes des autres. On pouvait it´erer sur la chaˆıne, ou sur ses indices, ou sur la liste de ses caract`eres,
et on pouvait construire directement une chaˆıne ou contruire une liste pour la rassembler ensuite. Par
exemple, en it´erant sur la chaˆıne et en construisant directement une chaˆıne :
def cesar(texte,k):
resultat=""
for cin texte:
resultat=resultat+cesar_caractere(c,k)
return resultat
ou bien en construisant une liste par compr´ehension pour ensuite la rassembler :
def cesar(texte,k):
liste_resultat=[cesar_caractere(c,k) for cin texte]
return rassembler(liste_resultat)
Pour d´ecoder un texte coe par un d´ecalage de k, on effectue un d´ecalage de k.
Pour d´echiffrer le texte “V’XLM NG IXN VHNKM, CXNGX AHFFX”, on pouvait essayer les 26
d´ecalages possibles et trouver celui qui retournait un texte lisible.
3
Analyse fr´equentielle
´
Echantillon de texte : attention `a le sauver sous la forme d’un fichier texte “brut”, pas un document
word ou autre. Pour cela, utiliser le logiciel “bloc-notes”, et si il n’est pas dans votre menu D´emarrer,
alors dans le menu D´emarrer, cliquer sur “´
Ex´ecuter...” et taper “notepad”.
Pour lire son contenu depuis python, ne pas oublier l’extension .txt du fichier, et si le chemin contient
des backslash, mieux vaut les doubler. Python interpr´etera toujours un double backslash comme le
caract`ere ‘\’. En revanche, un simple backslash suivi de certaines lettres comme ‘a’, ‘t’, ‘r’ ou ‘n’ sera
compris comme un caract`ere sp´ecial (tabulation, saut de ligne...)
f=open("chemin_vers_le_fichier.txt")
texte=f.read()
Compter le nombre d’occurrences de chaque lettre dans l’´echantillon, et en d´eduire la fr´equence de
chaque lettre :
occurrences=[0]*26
for cin texte :
codepoint=ord(c)
if codepoint>=65 and codepoint <=90 :
occurrences[codepoint-65]=occurrences[codepoint-65]+1
total=sum(occurrences) # merci la fonction ’sum’ de python
frequences=[]
for nin occurrences:
frequences.append(n/total)
Histogramme des fr´equences : les abscisses des bˆatons seront 1, 2, 3, ..., 26 : pour les obtenir, on
convertit le range(1,27) en une liste. Leurs hauteurs seront les fr´equences. Leurs noms seront les
lettres de l’alphabet, dont on a fabriqu´e la liste alpha pr´ec´edemment.
import matplotlib.pyplot as plt
abscisses=list(range(1,27))
plt.bar(abscisses, frequences)
plt.xticks(abscisses, alpha)
plt.show()
Codage par substitution
Pas de corrig´e sur cette partie.
4
1 / 4 100%
La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans linterface ou les textes ? Ou savez-vous comment améliorer linterface utilisateur de StudyLib ? Nhésitez pas à envoyer vos suggestions. Cest très important pour nous !