Le cryptage des données est très à la mode : il s'agit d'un enjeu aujourd'hui majeur du fait de la connexion quasi permanente des terminaux à internet, de la multiplication des points d'accès à internet, du stockage des données dans le cloud, de l'augmentation incessante des performances des ordinateurs et de l'apparition de nouveaux algorithmes de décryptage. Nous voilà donc lancé dans la fameuse course technologique entre les armes et les armures...
Cryptage simple
Une méthode simple de cryptage peut être de changer tout simplement la palette de couleurs de l'image : si elle à l'avantage d'être assez simple à programmer et à comprendre, elle ne permet toutefois pas de masquer complètement le sujet présenté et n'est donc pas à utiliser pour cacher totalement le sujet de l'image !
La code présentée ici est basé sur un algorithme de type César fonctionnant sur les 3 canaux RVB de l'image.
import pygame
from pygame.locals import *
# Entrée des 3 clés de César pour les 3 canaux RVB
r=int(input("Entrer la clé de César pour le canal Rouge :"))
v=int(input("Entrer la clé de César pour le canal Vert :"))
b=int(input("Entrer la clé de César pour le canal Bleu :"))
cesar=[r,v,b]
# Initialisation de la fenêtre d'affichage
pygame.init()
fenetre = pygame.display.set_mode((870,522))
pygame.display.set_caption("La Vie Cryptée de Marc Chagall")
# Traitement de l'image
fond = pygame.image.load("lavie.jpg").convert()
blank_surface = pygame.Surface((870,522))
# Affichage de l'image départ
fenetre.blit(fond,(0,0))
pygame.display.flip()
pygame.time.wait(1000)
# Lecture et remplacement de la couleur de chaque pixel
for i in range(870):
for j in range(522):
color=list(fond.get_at((i,j)))
for k in range(3):
color[k]=color[k]+cesar[k]
if color[k]>255:
color[k]=color[k]-255
color=tuple(color)
blank_surface.set_at((i,j),color)
#collage du fond
fenetre.blit(blank_surface,(0,0))
pygame.display.flip()
# Sauvegarde de l'image dans un fichier
pygame.image.save(blank_surface,"laviecrypteedemarcchagall.jpg")
# Boucle principale
continuer = 1
while continuer:
for event in pygame.event.get():
# Quitter
if event.type == QUIT:
continuer = 0
pygame.quit()
A noter ici :
pygame.time.wait(1000)
, ce qui permet de voir un instant l'image de départcesar=[r,v,b]
, on aurait cependant pu choisir un stockage externe dans un fichiercolor[k]=color[k]+cesar[k]
if color[k]>255: color[k]=color[k]-255
pygame.image.save(blank_surface,"laviecrypteedemarcchagall.jpg")
Exemple d'exercice d'appropriation : créer un deuxième script permettant cette fois-ci de décrypter l'image, en lisant l'image cryptée stockée précédemment et en saisissant les 3 clés de César.
La correction du script est ici.
Voici le résultat du cryptage et du décryptage de César pour les clés de César [100,100,100] (on peut remarquer la surexposition de certains pixels lors du décryptage due à un bug de la version de SDL utilisée) :
Cryptage avancé
il existe et on peut imaginer quantité de méthode de cryptage plus ou moins compliquée. Nous allons ici améliorer notre cryptage tout en conservant le même algorithme : pour cela nous allons crypter chacun des canaux RVB de chacune des lignes avec une clé de César différente déterminée aléatoirement. Ces clés vont être stockées dans un fichier externe qui sera utilisé pour le décryptage de l'image, ainsi il sera impossible de connaître le contenu de l'image sans avoir accès au fichier contenant l'ensemble des clés et au programme de décryptage.
Voici le code complet :
import pygame
import random
from pygame.locals import *
# Initialisation de la fenêtre d'affichage
pygame.init()
fenetre = pygame.display.set_mode((870,522))
pygame.display.set_caption("La Vie Très Cryptée de Marc Chagall")
# Traitement de l'image
fond = pygame.image.load("lavie.jpg").convert()
blank_surface = pygame.Surface((870,522))
# Affichage de l'image départ
fenetre.blit(fond,(0,0))
pygame.display.flip()
pygame.time.wait(1000)
# Création de la liste contenant les clés de César
cesar=[]
for j in range(522):
cesar=cesar +[[random.randint(0,255),random.randint(0,255),random.randint(0,255)]]
# Création du fichier contenant les clés de César
trousseau = open("topsecret.txt", "w")
trousseau.close()
trousseau = open("topsecret.txt", "a")
for j in range(522):
for k in range(3):
trousseau.write(str(cesar[j][k])+" ")
trousseau.close()
# Lecture et remplacement de la couleur de chaque pixel
for i in range(870):
for j in range(522):
color=list(fond.get_at((i,j)))
for k in range(3):
color[k]=color[k]+cesar[j][k]
if color[k]>255:
color[k]=color[k]-255
color=tuple(color)
blank_surface.set_at((i,j),color)
# Collage du fond
fenetre.blit(blank_surface,(0,0))
pygame.display.flip()
# Sauvegarde de l'image dans un fichier
pygame.image.save(blank_surface,"lavietrescrypteedemarcchagall.jpg")
# Boucle principale
continuer = 1
while continuer:
for event in pygame.event.get():
# Quitter
if event.type == QUIT:
continuer = 0
pygame.quit()
Détaillons maintenant un peu ce code:
import random
random.randint(0,255)
open("topsecret.txt", "w")
sert normalement à accéder au fichier topsecret.txt en écriture, elle est utilisée ici pour simplement effacer le contenu du fichier précédent. Ne pas oublier de fermer le plus tôt possible le fichier ouvert à l'aide de l'instruction close()
pour éviter de générer une erreur d'accès. open("topsecret.txt", "a")
et les deux boucles for imbriquées servent à parcourir la liste cesar. Son contenu est ensuite écrit dans le fichier texte ouvert précédemment grâce à l'instruction write(str(cesar[j][k])+" ")
. A noter la conversion de chaque donnée en chaîne de caractères et l'insertion d'un espace pour préparer le split de la chaîne lors du décodage... color[k]=color[k]+cesar[j][k]
Exemple d'exercice d'appropriation : créer un deuxième script permettant cette fois-ci de décrypter l'image, en lisant l'image cryptée stockée précédemment et en utilisant le fichier topsecret.txt.
La correction du script est ici.
Voici le résultat du cryptage avancé et du décryptage avancé de César (même cause et mêmes effet, les altérations sur l'image décryptée sont dues à un bug de la SDL mais on reconnaît bien le sujet de l'image):