209 lines
8.1 KiB
Python
209 lines
8.1 KiB
Python
|
|
#!/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)
|