#!/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)