
Steganografia in Python | Nascondi file o dati in file immagine
Questo script nasconde file all'interno di immagini e salva l'immagine modificata su disco.
La dimensione massima del file che può essere nascosto all'interno di un'immagine dipende dalle dimensioni dell'immagine.
max_file_size = ( height_of_image * width_of_image * 6 / 8 ) bytes
'100k words.txt' è nascosto in 'original_image.png' chiamato 'image_with_100k words.png'. Vai a verificare se riesci a notare la differenza tra queste due immagini. Puoi usare questo Modulo per estrarre '100k words.txt' da 'image_with_100k words.png'
Immagine Originale

Immagine Modificata

Questa immagine ha 100k parole (un file di testo) nascoste al suo interno!
Si basa su un semplice principio: se modifichiamo gli LSB (Least Significant Bits, bit meno significativi) di ogni pixel, il cambiamento non sarà significativo e non verrà notato dall'occhio umano.
Quindi, questo Modulo prende 2 bit di dati dal file da nascondere e sostituisce gli ultimi 2 bit di un pixel con quei 2 bit, poi passa al pixel successivo. La variazione massima in un pixel può essere di 4 unità, e l'intervallo dei valori in un'immagine PNG è (0,255), quindi questo cambiamento non sarà significativo.
In un'immagine PNG, ogni pixel ha 3 canali: Rosso, Verde e Blu. (Alcune immagini PNG hanno 1 o 4 canali, ma questo Programma li converte in 3 canali). Un pixel tipico in un'immagine PNG appare così:
a_pixel = (17,32,11) # (RED, GREEN, BLUE)
Quindi, possiamo salvare 3 volte 2 bit in un pixel, ovvero 6 bit per pixel. Questo ci porta al limite superiore della dimensione del file che può essere nascosto in un'immagine:
max_file_size = ( height_of_image * width_of_image * 6 / 8 ) bytes
Capiamolo con un esempio. I dati da nascondere sono:
binary_data = 0b100111
Prendiamo i primi due bit e sostituiamoli con il Canale ROSSO del nostro 'a_pixel'.
a_pixel = (0b10001, 0b100000, 0b1011) # binary representation of a_pixel values
# Modifichiamo il Canale ROSSO di a_pixel
# 0b10001 -> 0b10010 (I primi 2 bit sono 10)
a_pixel = (0b10010, 0b100000, 0b1011) # modified pixel
Prendiamo di nuovo 2 bit da binary_data e sostituiamo gli ultimi 2 bit del Canale VERDE con essi.
a_pixel = (0b10010, 0b100000, 0b1011)
# Modifichiamo il Canale VERDE di a_pixel
# 0b100000 -> 0b100001 (I 2 bit sono 01)
a_pixel = (0b10010, 0b100001, 0b1011) # modified pixel
Facciamolo un'ultima volta con il Canale BLU e avremo finito.
a_pixel = (0b10010, 0b100001, 0b1011)
# Modifichiamo il Canale BLU di a_pixel
# 0b1011 -> 0b1011 (I 2 bit sono 11); Nota che il valore non è cambiato questa volta
a_pixel = (0b10010, 0b100001, 0b1011) # pixel wasn't modified this time
Quindi, abbiamo nascosto il nostro messaggio di 6 bit in un pixel, vediamo i cambiamenti nel pixel
a_pixel = (0b10001, 0b100000, 0b1011) = (17, 32, 11)
a_pixel_with_data = (0b10010, 0b100001, 0b1011) = (18, 33, 11)
Come possiamo vedere, il cambiamento non è nemmeno percettibile a livello di pixel. Il Modulo ripete questo processo fino a quando tutti i dati sono salvati nell'immagine.

NOTA: Il rumore nella foto aumenta e se usiamo un software di fotoritocco e lo confrontiamo con l'immagine originale, questa immagine avrà molto più rumore dell'immagine originale.
Soluzione per questo problema: non caricare/condividere mai l'immagine originale su internet
MIT
Software libero, sì!