Files
TermNSI/Sécurité/exemples/chiffrement_ECB.py

209 lines
8.1 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Jan 8 15:27:05 2021
@author: pjoulaud
"""
from numpy.random import permutation
# Pour créer des permutations aléatoirement
class ECB:
"""
Classe dont les instances sont des cryptosystèmes dépendant de la donnée de leur clé
sous la forme d'une permutation
"""
def __init__(self, taille = None, images = None):
"""
Un cryptosystème ECB est défini par la donnée d'une permutation
Une permutation a pour attributs sa taille et la liste de ses images.
Un des deux doit être donné au moment de l'instanciation.
Une Permutation est si besoin créée aléatoirement en utilisant la fonction permutation
du module numpy.random
>>> ECB(images = [1,0,2]).images
[1, 0, 2]
"""
# si les images ne sont pas données, on les tire aléatoirement
if images :
liste_reference = [i for i in range(len(images))]
images_ordonnees = images[:]
images_ordonnees.sort()
#print(f"liste_reference {liste_reference}-images_ordonnees {images_ordonnees}")
if images_ordonnees==liste_reference:
self.images = images
else :
self.images = list(permutation(range(taille)))
def __repr__(self):
"""
On représente les images de la permutation :
>>> ECB(images=[0, 3, 2, 4, 1])
0 3 2 4 1
"""
return " ".join([str(image) for image in self.images])
def __invert__(self) :
"""
Permet d'obtenir la permutation réciproque de self avec ~
>>> mon_ecb = ECB(images = [1,3,0,2])
>>> mon_ecb
1 3 0 2
>>> ~mon_ecb
2 0 3 1
"""
ma_liste = []
for i in range(len(self.images)):
ma_liste.append(self.images.index(i))
mon_ecb = ECB(images=ma_liste)
return mon_ecb
@property
def taille(self):
"""
>>> ECB(6).taille
6
"""
# si la taille n'est pas donnée, c'est la longueur de la liste des images
return len(self.images)
def permute(self, une_liste):
"""
Permute les éléments d'une liste donnée en argument
Si xs = [xs[0], xs[1], xs[2],...] et si p est une permutation alors
mon_ecb.permute(xs) = [xs[p(0)], xs[p(1)], xs[p(2)],...]
>>> mon_ecb = ECB(images=[0, 3, 2, 4, 1])
>>> ma_liste = ['a', 'b', 'c', 'd', 'e']
>>> mon_ecb.permute(ma_liste)
['a', 'd', 'c', 'e', 'b']
"""
if len(une_liste)>=self.taille:
return [une_liste[i] for i in self.images]
def chaine2texte(self, une_chaine):
"""
Prend une chaine de caractères uniquement composée de 0 et de 1
Les cryptosystèmes manipulent des chaines de bits mais les humains veulent du texte
Cette méthode permet de transformer une trame de caractères codés sur un octet
en la chaîne de caractères correspondante.
>>> mon_ecb = ECB(images=[0, 3, 2, 4, 1])
>>> mon_ecb.chaine2texte('11101001')
'é'
>>> mon_ecb.chaine2texte('111010011110100111101001')
'ééé'
À comparer avec :
>>> chr(0b11101001)
'é'
"""
ma_chaine = ''
#car_a_completer = len(une_chaine)%8
#if car_a_completer!=0:
# une_chaine = '0'*(8-car_a_completer)+une_chaine
for i in range(len(une_chaine)//8):
ma_chaine += chr(int(une_chaine[8*i:8*(i+1)],2))
return ma_chaine
def texte2chaine(self, une_chaine):
"""
On transforme une instance de Texte en la chaîne caractères uniquement composée de 0 et de 1.
>>> mon_ecb = ECB(images=[0, 3, 2, 4, 1])
>>> mon_ecb.texte2chaine('ab')
'0110000101100010'
>>> mon_ecb.chaine2texte(mon_ecb.texte2chaine('azerty'))
'azerty'
"""
while len(une_chaine)%len(self.images) != 0:
une_chaine += ' '
ma_chaine = ''
for i in une_chaine :
for j in "{:08b}".format(ord(i)):
ma_chaine += j
return ma_chaine
def decoupe_en_blocs(self, les_caracteres):
"""
Prend une chaîne de caractères et la transforme en chaînes de caractères de
longueur celle de la permutation en complétant éventuellement par des '0'.
Méthode à usage interne facilitant l'écriture de la fonction chiffre
>>> mon_ecb = ECB(images=[1,0,3,2])
>>> mon_ecb.decoupe_en_blocs('123456789123456789')
['12345', '67891', '23456', '78900']
"""
ma_liste = []
car_a_completer = len(les_caracteres)%self.taille
if car_a_completer!=0:
les_caracteres = '0'*(self.taille-car_a_completer) + les_caracteres
car_a_completer = len(les_caracteres)%8
if car_a_completer!=0:
les_caracteres = '0'*(8-car_a_completer) + les_caracteres
nb_car_par_elem = len(les_caracteres)//self.taille
for i in range(self.taille):
ma_liste.append(les_caracteres[i*nb_car_par_elem:(i+1)*nb_car_par_elem])
return ma_liste
def permute(self, les_caracteres):
"""
Renvoie la liste des permutations des blocs de longueur celle de la permutation
construits à partir d'une chaîne de caracteres.
>>> mon_ecb = ECB(images=[1,0,3,2])
>>> mon_ecb.permute('123456789123456789')
'67891123457890023456'
"""
ma_liste_de_chaine = self.decoupe_en_blocs(les_caracteres)
#print(f"{ma_liste_de_chaine} toto")
ma_liste_de_chaine2 = []
for indice in self.images :
#print(f"{une_chaine}")
#ma_chaine = Chaine(self.cle.permute(une_chaine.entiers))
#print(f"{ma_chaine}")
ma_liste_de_chaine2.append(ma_liste_de_chaine[indice])
#print(f"{ma_liste_de_chaine} - {ma_liste_de_chaine2}")
return "".join(ma_liste_de_chaine2)
def chiffre(self, message):
"""
Retourne le message chiffré sous forme de chaîne de caracères.
Utilise les sous-méthodes précédentes.
>>> mon_ecb = ECB(images=[0, 1, 3, 4, 2])
>>> chaine_0_1 = mon_ecb.texte2chaine('hello world')
>>> chaine_0_1_code = mon_ecb.permute(chaine_0_1)
>>> message_code = mon_ecb.chaine2texte(chaine_0_1_code)
"""
chaine_0_1 = mon_ecb.texte2chaine(message)
#print(f"{chaine_0_1}")
chaine_0_1_code = mon_ecb.permute(chaine_0_1)
#print(f"{chaine_0_1_code}")
return mon_ecb.chaine2texte(chaine_0_1_code)
def dechiffre(self, message_code):
ecb_inverse = ~self
chaine_0_1 = ecb_inverse.texte2chaine(message_code)
print(f"0 : {chaine_0_1}")
chaine_0_1_code = ecb_inverse.permute(chaine_0_1)
print(f"1 : {chaine_0_1_code}")
return ecb_inverse.chaine2texte(chaine_0_1_code)
#mon_ecb = ECB(6)
#print(mon_ecb)
#print(mon_ecb.taille)
import doctest
doctest.testmod()
mon_ecb = ECB(25)
toto = mon_ecb.chiffre("Et si quelquefois, sur les marches d'un palais, sur l'herbe verte d'un fossé, vous vous réveillez, l'ivresse déjà diminuée ou disparue, demandez au vent, à la vague, à l'étoile, à l'oiseau, à l'horloge; à tout ce qui fuit, à tout ce qui gémit, à tout ce qui roule, à tout ce qui chante, à tout ce qui parle, demandez quelle heure il est. Et le vent, la vague, l'étoile, l'oiseau, l'horloge, vous répondront, il est l'heure de s'enivrer ; pour ne pas être les esclaves martyrisés du temps, enivrez-vous, enivrez-vous sans cesse de vin, de poésie, de vertu, à votre guise")
print(toto)
titi = mon_ecb.dechiffre(toto)
print(titi)