Python et stéganographie

Il n'y a pas si longtemps, un Hackathon pilote pour étudiants a eu lieu dans mon école . Le sujet des tâches était lié à la sécurité de l'information, y compris le chiffrement des données.



L'une des tâches les plus colorées était TASK-10: la stéganographie .
Nous donnons une définition.
La stéganographie est un moyen de transmission ou de stockage d'informations, en tenant compte de la confidentialité du fait même d'un tel transfert (stockage).
En d'autres termes, si la cryptographie masque les informations elles-mêmes, la stéganographie masque le fait de leur transmission.



Malheureusement, l'équipe et moi n'avons pas eu le temps de terminer cette tâche à temps, et j'ai décidé de la terminer après l'événement.

La solution la plus évidente à l'époque semblait être:

  1. Convertissez le texte chiffré en ensembles de bits.
  2. Faites de même avec l'image.
  3. Placez le texte à un endroit aléatoire sur l'image et enregistrez-le en tant qu'image.

Voici un petit code pour convertir du texte en ensembles de bits et vice versa.

def text_to_binary(event): return [int(format(ord(elem),'b')) for elem in event] def binary_to_text(event): return [chr(int(str(elem),2)) for elem in event] 

Cependant, après avoir fait part de mes pensées à mes collègues plus expérimentés, j'ai été envoyée pour enseigner le matériel.
Vous devez commencer par le fait que les octets du fichier image ne peuvent pas être modifiés directement s'il ne s'agit pas de bmp.

{% - encodeur aléatoire%}
Après avoir lu un peu les modèles de couleurs, j'ai décidé d'abandonner la décomposition de l'image à 1 et 0 au profit de modifications des pixels eux-mêmes dans la palette RVB. Pour ces manipulations, j'ai choisi la bibliothèque Pillow, voici un bon article à ce sujet.

Nous avons donc une image. L'image a des pixels. Les pixels sont formés à partir de couleurs primaires - rouge, vert et bleu.

Chacune des couleurs est codée avec un nombre compris entre 0 et 255.



Et nous avons également des caractères ASCII qui sont également encodés.

Essayons de crypter du texte dans cette image.

Image:




Un peu de texte:
C, il est facile de se tirer une balle dans le pied; Le C ++ rend les choses plus difficiles, mais quand vous le faites, il vous emporte toute la jambe
Connectez les bibliothèques nécessaires.

 from PIL import Image, ImageDraw from random import randint 

Ensuite, nous déclarons la fonction et y mettons tous les objets qui nous sont utiles.

 def stega_encrypt(): keys = [] img = Image.open(input("path to image: ")) draw = ImageDraw.Draw(img) width = img.size[0] height = img.size[1] pix = img.load() f = open('keys.txt','w') 

Plus intéressant. La tâche la plus importante consiste à trouver un moyen de crypter les messages. J'ai proposé cette méthode :

  1. Prenez un caractère, traduisez-le en un nombre ASCII
  2. Créer un tuple avec des coordonnées aléatoires
  3. Nous collectons les nuances vertes et bleues d'un pixel aux coordonnées
  4. Remplacez la teinte rouge par le numéro de caractère ASCII

 for elem in ([ord(elem) for elem in input("text here: ")]): key = (randint(1,width-10),randint(1,height-10)) g, b = pix[key][1:3] draw.point(key, (elem,g , b)) f.write(str(key)+'\n') 

Nous sauvegardons les clés et l'image.

 print('keys were written to the keys.txt file') img.save("newimage.png", "PNG") f.close() 

code

Nous essayons d'exécuter le script.

En conséquence, nous avons obtenu la même image, mais au format png et avec quelques pixels modifiés.



Il reste maintenant à déchiffrer le tout.

Nous écrivons un script de décryptage!

Nous connectons tout ce qui est nécessaire.

 from PIL import Image from re import findall 

Nous déclarons une fonction de décryptage, ainsi que plusieurs objets.

 def stega_decrypt(): a = [] keys = [] img = Image.open(input("path to image: ")) pix = img.load() f = open(input('path to keys: '),'r') y = str([line.strip() for line in f]) 

Algorithme de décryptage de base:

 for i in range(len(findall(r'\((\d+)\,',y))): keys.append((int(findall(r'\((\d+)\,',y)[i]),int(findall(r'\,\s(\d+)\)',y)[i]))) for key in keys: a.append(pix[tuple(key)][0]) return ''.join([chr(elem) for elem in a]) 

Ces expressions régulières sont nécessaires pour lire les tuples d'un fichier texte.

La dernière action consiste à afficher un message crypté à l'écran.

 print("you message: ", stega_decrypt()) 

code

Essayez maintenant de faire passer notre message.



Comme requis pour prouver, tout fonctionne!

Le principal inconvénient: la visibilité des pixels morts dans l'image dans le cas du cryptage d'un grand nombre de caractères. Cependant, cette faille est parfaitement corrigée par la haute résolution.

Références:

Source: https://habr.com/ru/post/fr413803/


All Articles