Introducción a la esteganografía con imágenes en LSB

Introducción

La esteganografía es una técnica para ocultar mensajes en un canal encubierto. Hay muchas formas de hacerlo, y hoy veremos cómo es que se hace en imágenes. Sólo explicaremos la teoría, no haremos nada práctico por el momento.

Actualización: aquí un ejemplo.

Recordando cómo se compone una imagen

Una imagen tiene pixeles. Y cada pixel tiene un nivel de rojo, verde y azul. Dichos niveles van desde 0 hasta 255, y se les conoce como colores RGB.

  • El color blanco es 255, 255, 255
  • El negro es 0, 0, 0

Podemos combinar de cualquier forma estos colores

Bits y bytes

Por lo tanto, cada pixel puede alojar 3 bytes de información, uno por cada nivel de color. Recordemos que un byte son ocho bits, o sea, 8 ceros o unos.

Y el mayor número decimal que podemos representar con 8 bits (un byte) es 255, que en binario es 11111111.

Así que los niveles de los colores ocupan un byte. Si su valor es 0, el byte es 00000000. Si es 1, 00000001, y así.

LSB o bit menos significativo

Ya dijimos que 11111111 es 255, y 00000001 es 1. Ahora vamos a ver el bit más y menos significativo. El menos significativo (LSB) es el que, al cambiar su valor, no afecta mucho. Es el último bit de izquierda a derecha.

Pongamos el ejemplo de 255, que es 11111111:

Si cambio su último bit por un 0, entonces será 11111110. Al convertirlo a decimal, será 254, no es una gran diferencia.

MSB o bit más significativo

El MSB es el primer bit si ordenamos de izquierda a derecha. Siguiendo el ejemplo de 255, que es 11111111 vamos a cambiarlo.

Cambiamos 11111111 por 01111111. Al convertirlo en decimal, tenemos el número 127; es decir, de 255 pasó a 127. Eso sí fue un gran cambio.

Escondiendo un bit de información en el LSB

Ya vimos que no afecta mucho si cambiamos el LSB, pues sólo aumentará o disminuirá 1. Entonces descomponemos una cadena, la convertimos en bits y escondemos un bit por cada nivel de color.

Ejemplo

Escondamos la palabra “Ho”. El número o código ascii que le corresponde a cada letra es como se ve abajo:

  • H: 72
  • o: 111

Ahora vamos a convertir esos números a binario:

  • 72: 01001000
  • 111: 01101111

Supongamos que tenemos algunos pixeles de una imagen así como se ve abajo. El orden es R, G, B o Rojo, Verde, Azul. Sin alterar, se ven así:

  1. (80, 20, 55)
  2. (12, 20, 55)
  3. (80, 55, 55)
  4. (32, 20, 55)
  5. (80, 2, 200)
  6. (20, 152, 96)

Su representación binaria es esta:

  1. (01010000, 00010100, 00110111)
  2. (00001100, 00010100, 00110111)
  3. (01010000, 00110111, 00110111)
  4. (00100000, 00010100, 00110111)
  5. (01010000, 00000010, 11001000)
  6. (00010100, 10011000, 01100000)

Alterar bytes por cada bit

Ahora, por cada bit de la palabra “Ho” vamos a alterar un byte de un nivel de color los pixeles.

“Ho” en bits, es esto (el 72 y el 111 en binario):

01001000 01101111

Comenzamos con el primer bit (0), lo acomodamos en el valor R del primer pixel. El segundo bit (1) en el valor G del primer pixel, el tercero (0) en el valor B del primer pixel. Luego, el cuarto bit (0) en el valor R del segundo pixel y así sucesivamente.

Los pixeles, ya modificados y en binario, lucen así  como se ve abajo. Notar por favor que en el nivel B del tercer pixel comenzamos a escribir el primer bit de la letra “o”.

  1. (01010000, 00010101, 00110110)
  2. (00001100, 00010101, 00110110)
  3. (01010000, 00110110, 00110110)
  4. (00100001, 00010101, 00110110)
  5. (01010001, 00000011, 11001001)
  6. (00010101, 10011000, 01100000)

Los últimos dos niveles del sexto pixel los dejamos intactos, pues ya escondimos lo que era necesario. Ahora vamos a ver lo más interesante de esto.

Convertir de nuevo a decimal

Ya tenemos nuestros pixeles modificados, vamos a convertirlos a decimal. Se ven así:

  1. (80, 21, 55)
  2. (12, 21, 55)
  3. (80, 55, 55)
  4. (33, 21, 55)
  5. (81, 3, 201)
  6. (21, 152, 96)

Y los originales eran estos:

  1. (80, 20, 55)
  2. (12, 20, 55)
  3. (80, 55, 55)
  4. (32, 20, 55)
  5. (80, 2, 200)
  6. (20, 152, 96)

Viéndolo como números, claro que se ve la diferencia. Veamos ahora cómo se ven en colores.

Diferencia no notable al ojo humano

Tomemos el primer pixel. El original era 80, 20, 55. El modificado es 80, 21, 55. Aquí los colores:

Izquierda color original. Derecha color modificado (lo saqué de aquí). Al menos yo no veo alguna diferencia, y de hecho esta es una imagen grande. Recordemos que un pixel es mucho mucho más pequeño, así que… ¿quién notaría la diferencia?

Así podemos esconder información en cada pixel. Para recuperarla, hay que hacer el proceso inverso, con la diferencia de que cada que llevemos ocho bits tenemos que calcular su valor en decimal, y luego convertir ese decimal al carácter que le corresponde.

¿Es esto seguro?

Claro que lo es, pero no de este modo. Tenemos que aprender a no ser tan predecibles. Por ejemplo, modificar pixeles pero no en un orden, sino aleatoriamente. Rotar el texto antes de escribirlo, cosas de esas.

Es importante notar que también podemos (y lo recomiendo ampliamente) encriptar el texto antes de esconderlo. Así, aunque alguien descubra que hay texto ahí, no sabrá cuál es el mensaje original.

Encantado de ayudarte


Estoy disponible para trabajar en tu proyecto, modificar el programa del post o realizar tu tarea pendiente, no dudes en ponerte en contacto conmigo.

No te pierdas ninguno de mis posts

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.

1 comentario en “Introducción a la esteganografía con imágenes en LSB”

  1. Pingback: Ejemplo de esteganografía en imágenes con Python - Parzibyte's blog - El blog de Luis Cabrera

Dejar un comentario