Je vous présente ici une méthode de chiffrement personnel d’images avec Python. Pour se faire, nous allons prendre une image quelconque, par exemple celle-ci:

chiffrement images python

Un chiffrement personnel d’images avec python: préliminaires

Une image est une matrice de triplets ou quadruplets (selon les formats). Pour notre exemple, l’image est au format JPG, donc chaque pixel qui la compose est un triplet (R,B,V).

Il faut donc avant tout récupérer ces triplets à l’aide de Python. Pour cela, nous allons avoir besoin des modules pillow et numpy.

Installation des modules

Si vous avez une distribution standard de Python, vous pouvez les installer à l’aide de “pip”.

pip install pillow numpy

Si vous êtes sous Anaconda, ce sera:

conda install pillow numpy

Récupérations des données de l’images

from PIL import Image
import numpy as np

# Charger l'image
image_path = 'ruban.jpg'
image = Image.open(image_path)

# Convertir l'image en matrice numpy
image_matrix = np.array(image)

# Afficher la matrice
print(image_matrix)

np.array(image) va nous donner une matrice. La matrice commence par:

[[[10 16 28]
  [ 3  9 21]
  [ 6 13 23]
  ...
  [ 6  9 16]
  [ 9  9 17]
  [ 9  9 17]]

Cela signifie que:

  • Le premier pixel en haut à gauche est codé par le RVB : (10,16,28) ➙ 10% de Rouge, 16% de Vert et 28% de Bleu;
  • Le pixel qui est juste à droite du premier est codé par le RVB : (3,9,21);
  • Le pixel qui est juste en-dessous du premier est codé par (6,9,16);
  • etc.

Mieux comprendre la matrice de l’image

Pour simplifier, si notre image faisait 3 pixels sur 3, la matrice pourrait être par exemple:

image_matrix = np.array([
    [[255, 0, 0], [0, 255, 0], [0, 0, 255]],  # Première ligne de pixels
    [[255, 255, 0], [0, 255, 255], [255, 0, 255]],  # Deuxième ligne de pixels
    [[128, 128, 128], [255, 255, 255], [0, 0, 0]]  # Troisième ligne de pixels
])

Le chiffrement de l’image avec python

Maintenant, il est temps de chiffrer chaque nombre qui compose cette matrice. Là, nous avons le choix:

Je vais utiliser un chiffrement par permutation. Pour des raisons de sécurité, il est nécessaire d’ajouter une clé, afin que le déchiffrement ne soit pas possible sans.

from PIL import Image
import numpy as np

# Charger l'image
image_path = 'ruban.jpg'
image = Image.open(image_path)

# Convertir l'image en matrice numpy
image_matrix = np.array(image)

# Fonction pour générer une permutation déterministe à partir d'une clé
def generate_permutation(size, key):
    np.random.seed(key)
    return np.random.permutation(size)

# Appliquer la permutation
def apply_permutation(image_matrix, permutation):
    flat_matrix = image_matrix.flatten()
    permuted_matrix = flat_matrix[permutation]
    return permuted_matrix.reshape(image_matrix.shape)

# Inverser la permutation
def inverse_permutation(permutation):
    inverse = np.zeros_like(permutation)
    inverse[permutation] = np.arange(len(permutation))
    return inverse

# Clé de chiffrement
key = 12345  # Vous pouvez utiliser n'importe quelle valeur comme clé

# Générer une permutation pour l'image à partir de la clé
permutation = generate_permutation(image_matrix.size, key)

# Appliquer la permutation pour chiffrer l'image
encrypted_matrix = apply_permutation(image_matrix, permutation)

# Convertir la matrice chiffrée en image
encrypted_image = Image.fromarray(encrypted_matrix.astype('uint8'), 'RGB')

# Sauvegarder l'image chiffrée
encrypted_image.save('ruban_chiffre_permutation.jpg')

# Inverser la permutation pour déchiffrer l'image
inverse_permutation = inverse_permutation(permutation)
decrypted_matrix = apply_permutation(encrypted_matrix, inverse_permutation)

# Convertir la matrice déchiffrée en image
decrypted_image = Image.fromarray(decrypted_matrix.astype('uint8'), 'RGB')

# Sauvegarder l'image déchiffrée
decrypted_image.save('ruban_dechiffre_permutation.jpg')

L’image ainsi chiffrée est:

On peut maintenant se servir de ce code pour créer une interface graphique qui demande à l’utilisateur une image, puis une clé, puis un répertoire de sauvegarde.

Là, il a fallu adapter le code précédent car la méthode de chiffrement n’était pas compatible. Je change aussi quelques petits trucs concernant la clé de chiffrement qui, sur les codes précédents, ne peuvent être que des chaînes numériques. J’aimerais que la clé puisse être alphanumérique.

import tkinter as tk
from tkinter import filedialog, messagebox
from PIL import Image
import numpy as np
import hashlib

# Convertir une chaine de caractères en entier
def key_from_string(key_string):
    # Convertir la chaîne en une valeur de hachage (MD5)
    hashed_key = hashlib.md5(key_string.encode()).hexdigest()
    # Convertir la valeur hexadécimale en entier
    key_int = int(hashed_key, 16)
    # Réduire la valeur pour qu'elle soit compatible avec np.random.seed
    return key_int % (2**32)  # Limiter à 32 bits


# Fonction pour générer une permutation déterministe à partir d'une clé
def generate_permutation(size, key):
    np.random.seed(key)
    return np.random.permutation(size)

# Fonction pour appliquer la permutation
def apply_permutation(image_matrix, permutation):
    # Si l'image est en 3D (RGB), appliquer la permutation sur chaque canal
    if len(image_matrix.shape) == 3:
        permuted_matrix = np.zeros_like(image_matrix)
        for channel in range(image_matrix.shape[2]):  # Parcourir R, G, B
            flat_channel = image_matrix[:, :, channel].flatten()
            permuted_channel = flat_channel[permutation]
            permuted_matrix[:, :, channel] = permuted_channel.reshape(image_matrix.shape[:2])
        return permuted_matrix
    else:  # Si l'image est en niveaux de gris (2D)
        flat_matrix = image_matrix.flatten()
        permuted_matrix = flat_matrix[permutation]
        return permuted_matrix.reshape(image_matrix.shape)


# Fonction pour inverser la permutation
def inverse_permutation(permutation):
    inverse = np.zeros_like(permutation)
    inverse[permutation] = np.arange(len(permutation))
    return inverse

# Fonction pour chiffrer l'image
def encrypt_image(image_path, key, save_path):
    image = Image.open(image_path)
    image_matrix = np.array(image)

    # Si la clé est une chaîne, la convertir en entier
    if isinstance(key, str):
        key = key_from_string(key)

    # Générer une permutation
    permutation = generate_permutation(image_matrix.shape[0] * image_matrix.shape[1], key)

    # Appliquer la permutation
    encrypted_matrix = apply_permutation(image_matrix, permutation)

    # Sauvegarder l'image chiffrée
    encrypted_image = Image.fromarray(encrypted_matrix.astype('uint8'))
    encrypted_image.save(save_path)
    messagebox.showinfo("Succès", "L'image a été chiffrée et sauvegardée avec succès.")

# Fonction pour déchiffrer l'image
def decrypt_image(image_path, key, save_path):
    image = Image.open(image_path)
    image_matrix = np.array(image)

    # Si la clé est une chaîne, la convertir en entier
    if isinstance(key, str):
        key = key_from_string(key)

    # Générer la permutation et son inverse
    permutation = generate_permutation(image_matrix.shape[0] * image_matrix.shape[1], key)
    inverse_perm = inverse_permutation(permutation)

    # Appliquer l'inverse de la permutation
    decrypted_matrix = apply_permutation(image_matrix, inverse_perm)

    # Sauvegarder l'image déchiffrée
    decrypted_image = Image.fromarray(decrypted_matrix.astype('uint8'))
    decrypted_image.save(save_path)
    messagebox.showinfo("Succès", "L'image a été déchiffrée et sauvegardée avec succès.")


# Fonction pour sélectionner une image
def select_image():
    file_path = filedialog.askopenfilename(title="Sélectionner une image", filetypes=[("Image files", "*.jpg *.jpeg *.png *.bmp *.gif")])
    if file_path:
        image_path_entry.delete(0, tk.END)
        image_path_entry.insert(0, file_path)

# Fonction pour sélectionner un répertoire de sauvegarde
def select_save_directory():
    dir_path = filedialog.askdirectory(title="Sélectionner un répertoire de sauvegarde")
    if dir_path:
        save_dir_entry.delete(0, tk.END)
        save_dir_entry.insert(0, dir_path)

# Fonction pour chiffrer l'image
def encrypt():
    image_path = image_path_entry.get()
    key = key_entry.get() 
    save_dir = save_dir_entry.get()
    save_path = f"{save_dir}/encrypted_image.jpg"
    encrypt_image(image_path, key, save_path)

def decrypt():
    image_path = image_path_entry.get()
    key = key_entry.get() 
    save_dir = save_dir_entry.get()
    save_path = f"{save_dir}/decrypted_image.jpg"
    decrypt_image(image_path, key, save_path)


# Créer la fenêtre principale
root = tk.Tk()
root.title("Chiffrement et Déchiffrement d'Image")

# Créer les widgets
image_path_label = tk.Label(root, text="Chemin de l'image:")
image_path_label.grid(row=0, column=0, padx=10, pady=10)

image_path_entry = tk.Entry(root, width=50)
image_path_entry.grid(row=0, column=1, padx=10, pady=10)

image_path_button = tk.Button(root, text="Sélectionner une image", command=select_image)
image_path_button.grid(row=0, column=2, padx=10, pady=10)

key_label = tk.Label(root, text="Clé de chiffrement:")
key_label.grid(row=1, column=0, padx=10, pady=10)

key_entry = tk.Entry(root, width=50)
key_entry.grid(row=1, column=1, padx=10, pady=10)

save_dir_label = tk.Label(root, text="Répertoire de sauvegarde:")
save_dir_label.grid(row=2, column=0, padx=10, pady=10)

save_dir_entry = tk.Entry(root, width=50)
save_dir_entry.grid(row=2, column=1, padx=10, pady=10)

save_dir_button = tk.Button(root, text="Sélectionner un répertoire", command=select_save_directory)
save_dir_button.grid(row=2, column=2, padx=10, pady=10)

encrypt_button = tk.Button(root, text="Chiffrer l'image", command=encrypt)
encrypt_button.grid(row=3, column=1, padx=10, pady=10)

decrypt_button = tk.Button(root, text="Déchiffrer l'image", command=decrypt)
decrypt_button.grid(row=3, column=2, padx=10, pady=10)

# Lancer la boucle principale
root.mainloop()

Et voilà! ça fonctionne nickel!

Catégories : InformatiquePython

0 0 votes
Évaluation de l'article
S’abonner
Notification pour
guest
0 Commentaires
Le plus ancien
Le plus récent Le plus populaire
Commentaires en ligne
Afficher tous les commentaires
0
Nous aimerions avoir votre avis, veuillez laisser un commentaire.x
0
    0
    Votre panier
    Votre panier est vide