TP1-PROG-11 : Introduction à la cryptographie
Contents
TP1-PROG-11 : Introduction à la cryptographie#
Objectifs#
Modéliser une scytale
comprendre et modéliser un chiffrement par décalage
intégrer une attaque en force brute
Implémenter le fonctionnement de la scytale:
chiffrer un texte clair avec connaissance de la clef
déchiffrer un texte crypté avec connaissance de la clef
Pour aller plus loin : Déchiffrer un texte crypté sans connaissance de la clef
attaque par force brute
reconnaissance de la langue
élagage des solutions peu probables
Modélisation d’une scytale#
La scytale est l’un des premiers dispositifs permettant de chiffrer ou déchiffrer un message. La méthode de chiffrement se fait par transposition.
Concrètement, le message à crypter est écrit sur un rouleau de papier ou de cuir enroulé sur la scytale (ou Bâton de Plutarque) :
| u | n | e | s | c | y |
| t | a | l | e | . | . |
| c | e | c | i | e | s |
| t | u | n | m | e | s |
| s | a | g | e | e | c |
| r | i | t | s | u | r |
Une fois déroulé, le message devient :
c t s r u t e u a i n a c n g t e l i m e s s e e e e u c . s s c r y .
Le clé de codage, c’est à dire le décalage sur la scytale vaut : clef = 6
. Cette clef permet de chiffrer et déchiffrer le message clair et codé.
Décalage#
Le décalage (lié à la clef de codage/décodage) est lié au nombre de lettres que l’on peut inscrire sur le périmètre de la scytale. Par conséquent, la clef est directement liée au rayon de la scytale.
Attaque en force brute#
Si on ne connaît pas la clef de codage/décodage, le seul moyen de décoder le message est de tester toutes les possibilités de décalage des lettres et de reconnaître un éventuel message clair.
C’est la technique de la force brute.
Exercice 1 : déclarer les phrases claires#
Ouvrez l’IDE Python et créez un nouveau fichier
crypto.py
.choisissez une phrase en clair (un
texte_clair
) en anglais ou en français
phrase_a_1 = "Arise, you have nothing to lose but your barbed wire fences!"
phrase_a_2 = "If privacy is outlawed, only outlaws will have privacy"
phrase_a_3 = "Show me a person who has nothing to hide, and I’ll show you a person who is either exceedingly dull or an exhibitionist"
phrase_a_4 = "One of the best ways to achieve justice is to expose injustice"
phrase_a_5 = "I am a future-hacker ; I am trying to get root access to the future. I want to ride its system of thought"
phrase_a_6 = "Girls need modems"
phrase_f_1 = "La valeur d’un trésor réside dans son secret"
phrase_f_2 = "La cryptographie est la forme la plus aboutie de l’action directe non-violente"
phrase_f_3 = "L’argent c’est du temps, sauf si vous n’avez pas l’un ou l’autre"
phrase_f_4 = "Un téléphone portable émet des signaux de localisation. Lorsqu’on a un téléphone portable, le réseau sait toujours où l’on se trouve"
phrase_f_5 = "Si vous possédez une bibliothèque et un jardin, vous avez tout ce qu’il vous faut"
phrase_f_6 = "Combien de vous n’ont pas violé de loi ce mois-ci ?"
phrase_f_7 = "Si vous surveillez tout le monde, vous ne surveillez personne"
Boucles : formalisme des algorigrammes - programme Python#
Une boucle for
est une construction où un test conditionnel est fait de manière implicite. En effet, en Python on écrit une boucle de la façon suivante :
for var in range(longueur):
instruction 1
instruction 2
etc..
Signifie que la variable var
va successivement prendre les valeur décrites dans la liste retournée par la fonction range(borneSup)
(où borneSup
n’est pas compris). Par exemple :
for var in range(5):
la fonction range(5)
va retourner la liste [0,1,2,3,4]
. La variable var
va donc successivement prendre ces valeurs. Lorsqu’elle atteindra la valeur 5
, le test conditionnel sera faux et le programme va sortir de la boucle.
On peut décrire une boucle for
avec l’algorigramme suivant :
Exercice 2 : Construction de la fonction de chiffrement#
La signature de la fonction de chiffrement est la suivante :
# Fonction permettant de chiffrer un texte en clair
# Argument 1 : le texte clair
# Argument 2 : la clef de chiffrage
# Retour : le texte chiffré
def chiffre(texte_clair,saut):
Elle prend en paramètre le texte clair à chiffrer ainsi que le clef de chiffrement. Et le retourne la phrase chiffrée. L’algorithme est donc :
POUR toute lettre du
texte_clair
fairecalculer la position chiffrée
pos_c
:pos_c = pos_c + clef
SI on a atteint la fin du texte_clair
l
, alors incrémenter :if (pos_c > l-1)
dec = dec + 1
la position dans le texte chiffré devient la valeur de l’incrément :
pos_c = dec
Ajouter la lettre chiffrée à la position
pos_c
dans letexte_chiffre
:texte_chiffre = texte_chiffre + texte_clair[pos_c]
retourner
texte_chiffre
:return texte_chiffre
Nous avons donc une boucle for
qu’il s’agit de reconnaître dans algorigramme suivant:
Afin de tester votre algorigramme avec une feuille de papier, et avant de vous lancer dans l’implémentation :
prenez une feuille de papier
codez le mot
BONJOUR
avecclef = 2
analysez chacune des étapes dans un tableau qui contient :
Valeur de pos |
Valeur de pos_c |
Valeur de dec |
---|---|---|
0 |
0 |
0 |
1 |
2 |
0 |
2 |
4 |
0 |
etc… |
le mot
BONJOUR
chiffré avecclef = 2
vautBNOROJU
# Fonction permettant de chiffrer un texte en clair
# Argument 1 : le texte clair
# Argument 2 : la clef de chiffrage
# Retour : le texte chiffré
def chiffre(texte_clair,clef):
texte_chiffre = ''
# la variable pos contient l'index (la position) dans le texte clair
pos = 0
# la variable dec contient l'incrément négatif lorsque la longueur du texte clair est atteinte
dec = 0
# la variable pos_c contient l'index (la position) dans le texte chiffré
pos_c = 0
# la variable l contient la longueur du texte clair
l = len(texte_clair)
# A REMPLIR ICI
return texte_chiffre
Exercice 3 : Test de la fonction#
Pour tester votre fonction, appelez-la sur la phrase que vous avez choisie à l’exercice 1.
Testez plusieurs valeurs de
clef
Exercice 4 : Construction de la fonction de déchiffrement#
La fonction de déchiffrement est parfaitement équivalente à la fonction de chiffrement. La seule différence est qu’elle prend en paramètre le texte_chiffre
et que la position chiffrée pos_c
devient la position dans le texte clair.
Attention : on travaille ici avec une liste ret
pour recréer le texte clair et initialisée à la longueur du texte chiffré, puisqu’il n’est pas possible de changer un caractère dans une chaîne. Le retour s’effectue avec la fonction ''.join(ret)
qui transforme une liste en chaîne de caractères.
# Fonction permettant de déchiffrer un texte crypté
# Argument 1 : le texte crypté
# Argument 2 : la clef de chiffrage
# Retour : le texte déchiffré
def dechiffre(texte_chiffre,clef):
# la variable l contient la longueur du texte chiffré
l = len(texte_chiffre)
# la variable pos continent l'index (la position) dans le texte chiffré
pos = 0
# la varibale pos_c contient l'index (la position) dans le texte clair
pos_c = 0
# la variable dec contient la valeur de l'incrément positif
dec = 0
# la variable ret est une liste de longueur l qui est vide et que l'on va remplir avec les lettre du texte chiffré
ret = ['' for _ in range(l)]
## A REMPLIR ICI
# on retourne une chaîne de caractères (''.join(ret) retourne la transformation de la liste en chaîne de caractères)
return ''.join(ret)
Exercice 5 : Chiffrer et déchiffrer#
testez vos deux fonctions
chiffrer(texte_clair,clef)
etdechiffre(texte_chiffre, clef)
sur la phrase choisirvous devriez obtenir la phrase clair
Exercice 6 : Force brute#
Choisissez une valeur pour la variable
clef
chiffrez une phrase de votre crû à l’aide de votre fonction de chiffrement et cette clef
Testez l’ensemble des possibilités par la force brute pour retrouver la phrase en clair.
Répondez aux questions suivantes :
Combien de clef maximum devez-vous tester ?
Quelles sont les difficultés que vous rencontrez ?
Pour aller plus loin#
Une fois que vous avez les deux fonctions de chiffrement et déchiffrement, il vous manque un élément pour être capable de casser une phrase chiffrée sans connaissance préalable de la clef de chiffrement.
Analyse de la langue utilisée#
Pour pimenter la difficulté, les messages sont écrit dans des langues différentes. Dans ce TP, nous utiliserons le français et l’anglais. La question devient donc : si l’on ne connaît pas la clef, comment faire comprendre à l’ordinateur qu’une phrase décryptée est peut-être la solution de décodage ?
Deux possibilités existent pour ce faire :
Une analyse fréquentielle : on compare la fréquence de chaque lettre du message codé avec la fréquence d’utilisation des lettres de chacune des langues. On prend la plus proche.
Une analyse par apparition des mots les plus courants des deux langues.
Créer des sets de données dans différentes langues#
Afin de tester l’analyse de la langue, il s’agit d’avoir deux datasets (l’un en anglais et l’autre en français). Ces sets de données comprennent l’entier des phrases déclarées à l’exercice 1
Exercice 7 : Créez les datasets#
Ces ensembles de données permettront de tester les différentes fonctions de chiffrement et de déchiffrement
déclarez l’ensemble des phrases en français et en anglais
crééez les deux sets de données tel que ci-dessous
dataset_a = [phrase_a_1,phrase_a_2,phrase_a_3,phrase_a_4,phrase_a_5,phrase_a_6]
dataset_f = [phrase_f_1,phrase_f_2,phrase_f_3,phrase_f_4,phrase_f_5,phrase_f_6,phrase_f_7]
Exercice 8 : Analyse linguistique du texte déchiffré#
Lorsqu’on a un très grand texte chiffré, la difficulté humaine lorsqu’on utilise la méthode de la force brute, est de devoir lire tous les résultats. Il peut y en avoir énormément et cela prend du temps. On peut demander à l’ordinateur de le faire à notre place.
Analyser chaque sous-chaîne de caractère du texte décrypté
Comparer avec un ensemble de mot très couramment utilisé dans les langues cibles.
Si “peu” de mots apparaissent, la clef n’est probablement pas la bonne, sinon, on conserve la solution possible
La fonction analyse_langue(texte)
a la signature suivante :
# Fonction permettant de retourner la langue d'un texte donné en paramètre
# sur la base d'une analyse de certains mots clefs
# La liste des mots clefs est basée sur les classements internationaux (comme COCA)
# Argument 1 : le texte clair
# Retour : une liste qui contient : [la langue possible, le nombre d'occurences des mots-clefs]
def analyse_langue(texte):
elle doit permettre de trouver si le texte est en français ou en anglais, sans garantie d’exactitude. Il s’agit d’abord de définir une suite des mots les plus utilisés en français et en anglais. Une recherche internet devrait vous y aider.
mots_clefs_f = ['le','la','les','un','une','de','des','il','elle','et','non','est','on','vous','nous','se','pas','leur']
mots_clefs_a = ['the','be','to','of','and','in','that','have','it','for','not','is','if']
L’idée ensuite est d’analyser l’ensemble de la chaîne de caractère passée en paramètre texte
et de compter les occurences de chacun des mots-clefs en français nbr_f
, puis en anglais nbr_a
. La méthode texte.startwith(sousChaine,i)
permet de retourner True
si la sous-chaîne de caractères sousChaine
à rechercher dans la chaîne texte
à l’index i
:
if texte.startwith(mot_clefs_f[i],position) :
# on incrémente le nombre d'occurences françaises de 1
nbr_f = nbr_f + 1
On compare ensuite les deux valeurs :
if (nbf_f == nbr_a):
# on ne peut pas discriminer les deux langues, on retourne NULL:
langue = 'NULL'
retour = [langue,nbr_a]
elif (nbr_f > nbr_a):
# le texte est en français
langue = 'FRA'
retour = [langue,nbr_f]
else:
# le texte est en anglais
langue = 'ENG'
retour = [langue,nbr_a]
on retourne finalement la valeur de la liste avec le nombre d’occurences:
return retour
# Fonction permettant de retourner la langue d'un texte donné en paramètre
# sur la base d'une analyse de certains mots clefs
# La liste des mots clefs est basée sur les classements internationaux (comme COCA)
# Argument 1 : le texte clair
# Retour : une liste qui contient : [la langue possible, le nombre d'occurences des mots-clefs]
def analyse_langue(texte):
mots_clefs_f = ['le','la','les','un','une','de','des','il','elle','et','non','est','on','vous','nous','se','pas','leur']
mots_clefs_a = ['the','be','to','of','and','in','that','have','it','for','not','is','if']
retour = ['',0]
l = len(texte)
nbr_f = 0
nbr_a = 0
for mot_clef in mots_clefs_f:
## A REMPLIR ICI
for mot_clef in mots_clefs_a:
## A REMPLIR ICI
if nbr_f == 0 and nbr_a == 0:
## A REMPLIR ICI
return retour
Input In [6]
for mot_clef in mots_clefs_a:
^
IndentationError: expected an indented block
Exercice 9 : Chiffrement et déchiffrement des datasets français et anglais#
Pour chiffrer et déchiffrer, nous choisissons des clefs de codage aléatoirement avec le module Python random
. Il s’agit d’importer ce module en tout début de programme :
import random
Pour tirer un entier au hasard, on utilise la fonction
random.randint(debut, fin)
où debut
est la borne inférieure, fin
la borne supérieure (non comprise). Ainsi :
random.randint(3,100)
va tirer un entier au hasard compris entre 3
et 100
import random
random.randint(3,100)
5
# Création des phrases chiffrées aléatoirement
# Et déchiffrement SANS élagage
for phrase in dataset_a:
longueur = len(phrase)
clef = random.randint(3,int(longueur/2))
texte_chiffre = chiffre(phrase,clef)
print('[Cyphered] '+str(clef)+" : "+texte_chiffre)
texte_dechiffre = dechiffre(texte_chiffre,clef)
print(' [ANALYSED '+str(clef)+'] : '+texte_dechiffre)
[Cyphered] 24 : Atwroii rsleeo ,sf eey nobcuue tsh !ayvoeu rn obtahribnegd
[ANALYSED 24] : Arise, you have nothing to lose but your barbed wire fences!
[Cyphered] 12 : Iso rf nwi olivpuylart lcilo yvauhawtacelvydae ,w i sp
[ANALYSED 12] : If privacy is outlawed, only outlaws will have privacy
[Cyphered] 31 : Sgpyh e otrdwosu olmhnlei dwoaehr ,o p aeainrns sd eo exnIih ’tiwlhbhleio rt s ihheoaoxnswci esnyetoodtuih niagn l
[ANALYSED 31] : Show me a person who has nothing to hide, and I’ll show you a person who is either exceedingly dull or an exhibitionist
[Cyphered] 27 : Oinnejevu eso tfji uctsehtei cbee sits wtaoy se xtpoo saec hi
[ANALYSED 27] : One of the best ways to achieve justice is to expose injustice
[Cyphered] 21 : I;rti outaIorsm te a .sama y cIsftc turewetysamuisn rn toegt f- ot ht otaot hc hrokgeiuee dgrtfeh u t
[ANALYSED 21] : I am a future-hacker ; I am trying to get root access to the future. I want to ride its system of thought
[Cyphered] 8 : Gesidr lmso dneem
[ANALYSED 8] : Girls need modems
Exercice 10: Application de la force brute#
A partir de la boucle précédente, calculer toutes les possibilités et clefs associées, c’est-à-dire sans connaître la clef a priori
Exercice 11 : Décrypter un très long texte chiffré#
A l’aide des trois fonctions chiffre(texte_clair,clef)
, dechiffre(texte_chiffre,clef)
et analyse_langue(texte)
, déchiffrez la phrase suivante :
phrase_chiffree = "Lemasp lccerr yycppottnoonggurr aadppehh iiceqr,uy eplsta o pgsrrciaimpeihnticieev eudste i ellxi iséséctera iipteounurtre dpdareno stc éolgd eeArsn tdeietqs u diietn éfc oheritmf,af tràie omunensn tccseo rnptfoaiuidrne nudtneiege rlcélo,em sml uadn aiptcleau tpdiaeor nt3 sd5ée0cs0u rcaiinsvséi ele,in sveaistrtio onln. s u Unan n dcseicser niénbleeés m mesénestmosbp lopetrnaitmn icaeivnpo airurex c eoauuy raraneitct o ruàer nsld auà cplroays psctirobyglpreta oplgh’riiaenp vhpeioneut.ri oLdnei sdrseeismm pucllraeycrpe tmuoen-nemt o fndonera misueylsme b eodtle e d,ge lsla açb ulfrooecr kmdceeh alpiaon tspe lrmuiosed ,eé rlunétemisel.ni tsLaéeiesr est uedrce h dnceirsqy uptetasob glcreratyptphetisoe g,dr aaapprhpgiaiqrluaeeî.st uàt illai sféoeiss aduajnosu rlde sh uéic rsiotnst écgeyppetnideannst alnet ifqruueist edt umnées olpoontgaumei ehniss.t oLier ep ldues daénvceileonp peexmeemnptl.e Dceopnunius dle Acnet itqyupiet éd,e lcar ycprtyopgtroagprhaipeh iae épteér mterto udveé tdraannss mleat ttroem bdee sd iunnf onrombaltei oéngsy pdtei emna nnioèmrmeé sKéhcnuurmihsoétee.p VIoIi,c iq uli’ hviisvtaoiitr ei lf ays cai neannvtier odne 3l a9 0c0r yapntso.g r aLpeh iree mqpulia cae mceonntd udiet sayumxb omléetsh oddaenss alv’ainncsécersi petti osno pdhei sKtnihquuméheost eupt inl’ias épeass ppoouurr loeb jcercytpitfa gdee nduimsésriimquulee rm oddeesr nien.f o r mLaetsi ornasc,i nmeasi sa ndcei ernennefso rdcee rl al ecurry pattotgrraaipth ilei n gOuni sstaiiqtu eq.u eL el epsr etmeicehrn ieqxue"
phrase_chiffree = "Lemasp lccerr yycppottnoonggurr aadppehh iiceqr,uy eplsta o pgsrrciaimpeihnticieev eudste i ellxi iséséctera iipteounurtre dpdareno stc éolgd eeArsn tdeietqs u diietn éfc oheritmf,af tràie omunensn tccseo rnptfoaiuidrne nudtneiege rlcélo,em sml uadn aiptcleau tpdiaeor nt3 sd5ée0cs0u rcaiinsvséi ele,in sveaistrtio onln. s u Unan n dcseicser niénbleeés m mesénestmosbp lopetrnaitmn icaeivnpo airurex c eoauuy raraneitct o ruàer nsld auà cplroays psctirobyglpreta oplgh’riiaenp vhpeioneut.ri oLdnei sdrseeismm pucllraeycrpe tmuoen-nemt o fndonera misueylsme b eodtle e d,ge lsla açb ulfrooecr kmdceeh alpiaon tspe lrmuiosed ,eé rlunétemisel.ni tsLaéeiesr est uedrce h dnceirsqy uptetasob glcreratyptphetisoe g,dr aaapprhpgiaiqrluaeeî.st uàt illai sféoeiss aduajnosu rlde sh uéic rsiotnst écgeyppetnideannst alnet ifqruueist edt umnées olpoontgaumei ehniss.t oLier ep ldues daénvceileonp peexmeemnptl.e Dceopnunius dle Acnet itqyupiet éd,e lcar ycprtyopgtroagprhaipeh iae épteér mterto udveé tdraannss mleat ttroem bdee sd iunnf onrombaltei oéngsy pdtei emna nnioèmrmeé sKéhcnuurmihsoétee.p VIoIi,c iq uli’ hviisvtaoiitr ei lf ays cai neannvtier odne 3l a9 0c0r yapntso.g r aLpeh iree mqpulia cae mceonntd udiet sayumxb omléetsh oddaenss alv’ainncsécersi petti osno pdhei sKtnihquuméheost eupt inl’ias épeass ppoouurr loeb jcercytpitfa gdee nduimsésriimquulee rm oddeesr nien.f o r mLaetsi ornasc,i nmeasi sa ndcei ernennefso rdcee rl al ecurry pattotgrraaipth ilei n gOuni sstaiiqtu eq.u eL el epsr etmeicehrn ieqxue"
Exercice 12 : Envoyer un message crypté#
Envoyez un email contenant un message chiffré à un ou une camarade de classe présent dans la salle sans lui dévoiler la clef et demandez-lui de le déchiffrer.