El regalo que le hice a Elena

El regalo que le hice a Elena

En efecto, este es el regalo que le hice a Elena, imprimí la foto (realmente era otra versión de mayor resolución) en papel fotográfico y se la regalé con un marco.

¿Qué es lo que tiene de especial esta imagen? Pues que no es una imagen normal y corriente aunque pueda parecer que si, es una imagen con un texto oculto.

Hace 4 años si no recuerdo mal desarrollé un pequeño programa para codificar textos dentro de imagenes (bmp's), se me ocurrió como se me solián ocurrir los proyectos en aquella época, por la noche y en época de exámenes, esa misma noche dejé todo lo que estaba estudiando y me pasé la mayor parte de la noche desarrollando el sistema.

¿Qué es una imagen?

Una imagen es una matriz de píxeles de dimensiones alto*ancho, un pixel es un conjunto de bytes que especifican las canales rojo, verde y azul de cada pixel, a partir de ahora denotado por la sintaxis [rojo, verde, azul], cada uno de los canales puede ir desde 0 hasta 255, de tal manera que un pixel de rojo puro es [255,0,0] y el blanco podría representarse por [255,255,255], es decir, el blanco es la presencia de los 3 colores primarios, esto es lo que se conoce como el modelo RGB bastante usando en representación de colores en un modelo de luz (como pueden ser las pantallas de los ordenadores) en contra posición con el modelo CMYK que se suele usar en impresión (para representación de colores en luz hay más modelos a parte del RGB, una variante bastante usada por ejemplo es el RGBA o ARGB que a parte de los colores primarios también incorpora un componente alpha que otorga transparencia al pixel).

De todas maneras centrémonos en el modelo de esta imagen de cabecera, es una imagen RGB con 8 bits para cada canal, es decir, 1 byte para cada canal (de 0 a 255), como he dicho antes, el color rojo sería representado por [255,0,0] en notación decimal.

¿Como podemos entonces ocultar texto en una imagen?

Pues la solución obviamente pasa por esconder el texto en los pixeles de la imagen, pero para hacer esto nos tenemos hacer otra pregunta.

¿Qué es un texto?

Un texto, al igual que una imagen o cualquier otro elemento digital, no es más que una secuencia de 1's y 0's. Un texto está formado por letras y cada letra está formada 8 bits, es decir, 1 byte, al menos en el sistema ASCII. Por ejemplo, para escribir mi nombre, Ángel Luis, lo que entiende el ordenador es:

181 110 103 101 108 32 76 117 105 115

Eso pasado a sistema binario es lo que realmente entiende el ordenador, por ejemplo, la Á (181) sería 10110101. Mi nombre completo en binario sería

10110101 01101110 01100111 01100101 01101100 00100000 01001100 01110101 01101001 01110011

¿Como podemos entonces ocultar texto en una imagen? (De nuevo)

Visto lo anterior lo que tenemos que hacer es intentar ocultar las letras de un texto en cada uno de los píxeles, pero tenemos una limitación, un pixel en este caso son 8 bytes, al igual que una letra, si introducimos una letra por cada pixel la imagen se distorsionaria porque eliminamos por completo un canal del pixel, por tanto, lo más sencillo una vez llegado aquí es que en vez de codificar una letra por cada pixel se va a codificar 3 bits de una letra por cada pixel, esto es, para codificar una letra necesitaremos 3 píxeles, y se va a modificar el bit menos significativo para que afecte lo mínimo posible a la imagen.

Por ejemplo, si queremos codificar la letra Á (181, 10110101) dentro de una imagen totalmente roja de tamaño 3x3.

Aquí tenemos la imagen original en rojo puro

\begin{pmatrix} [255, 0, 0] &[255, 0, 0] & [255, 0, 0] \\ [255, 0, 0] &[255, 0, 0] & [255, 0, 0] \\ [255, 0, 0] &[255, 0, 0] & [255, 0, 0] \end{pmatrix}

Si lo pasamos a binario que se verá mejor, tenemos

\begin{pmatrix} [1111111\textbf{1}, 0\textbf{0}, 0\textbf{0}] &[1111111\textbf{1}, 0\textbf{0}, 0\textbf{0}] & [1111111\textbf{1}, 0\textbf{0}, 0\textbf{0}] \\ [1111111\textbf{1}, 0\textbf{0}, 0\textbf{0}] &[1111111\textbf{1}, 0\textbf{0}, 0\textbf{0}] & [1111111\textbf{1}, 0\textbf{0}, 0\textbf{0}] \\ [1111111\textbf{1}, 0\textbf{0}, 0\textbf{0}] &[1111111\textbf{1}, 0\textbf{0}, 0\textbf{0}] & [1111111\textbf{1}, 0\textbf{0}, 0\textbf{0}] \end{pmatrix}

Nota: Por simplicidad cuando es todo 0 se omite 00000000 y se pone solo 00

Nota: En negrita están los bits que van a ser sustituidos por cada uno de los bits de la letra Á (10110101)

\begin{pmatrix} [1111111\textbf{1}, 0\textbf{0}, 0\textbf{1}] &[1111111\textbf{1}, 0\textbf{0}, 0\textbf{1}] & [1111111\textbf{0}, 0\textbf{1}, 00] \\ [11111111, 00, 00] &[11111111, 00, 00] & [11111111, 00, 00] \\ [11111111, 00, 00] &[11111111, 00, 00] & [11111111, 00, 00] \end{pmatrix}

En negrita ahora se aprecian aquellos bits a los que ha afectado la codificación.

En decimal esto se traduce a

\begin{pmatrix} [255, 0, 1] &[255, 0, 1] & [254, 1, 0] \\ [255, 0, 0] &[255, 0, 0] & [255, 0, 0] \\ [255, 0, 0] &[255, 0, 0] & [255, 0, 0] \end{pmatrix}

Como se puede observar, al modificar el bit menos significativo obtenemos un error de \pm 1 en cada uno de los canales con respecto a la imagen original.

Esta es nuestra imagen con el texto códificado. Ahora solo queda automatizar el proceso mediante un programa informático, teniendo en cuenta una cosa, el texto tiene que estar delimitado entre una marca de inicio y marca de fin para saber donde empieza el texto y donde acaba.

Proceso de codificación del texto

Proceso de codificación del texto

En la imagen anterior se lista el directorio actual donde existen 4 ficheros, 2 programas, 1 texto y 1 imagen. A continuación se imprime el texto de text_hide por pantalla (Esto es una prueba de texto oculto en una imagen). Luego se ejecuta el programa codificador, se elige la imagen donde se va a codificar el texto (image1.bmp), el texto a ocultar (text_hide) y la nueva imagen que se generará (image1.bmp). Por último, mediante el comando diff nos dice que las 2 imágenes son distintas a nivel binario, es decir, algunos bytes son distintos en ambas imagenes, aunque a efectos prácticos para el ojo humano las 2 imágenes son idénticas.

Proceso de decodificación del texto

Proceso de decodificación del texto

En la imagen anterior se muestra el proceso de decodificación, primero pruebo a decodificar image.bmp y me dice que no tiene ningún texto oculto, a continuación pruebo a decodificar el fichero imagen1.bmp y en efecto me dice que hay un texto oculto en ella.

Este método tiene una desventaja. Si tenemos un texto de 100 letras en total necesitariamos una imagen de

\dfrac{100*8}{3} = 266,666 \approx 267 pixeles

No son especialmente muchos píxeles si los comparamos con una foto en alta definicion (1920 x 1080 píxeles), pero si que puede llegar a ser un factor a tener en cuenta en imágenes más pequeñas.

Conclusión

Así es como le regalé una foto especial a Elena que actualmente se encuentra en su mesita.photo

Esta técnica se llama Esteganografía, y consiste en ocultar mensajes dentro de otros objetos, en este caso una imagen. Esta técnica se lleva usando desde hace muchos siglos.

Recuerdo que el programa lo hice hace unos 4 años y en cuanto a prestaciones deja mucho que desear debido a la falta de tiempo que tenía. Este programa solo acepta imágenes bmp de 24 bytes por pixel (8 por cada canal). Si tuviese que reformar hoy en día este programa haría las siguientes mejoras

  • Aceptar más formátos de imágenes (jpg, png) esto se conseguiría facilmente con alguna librería de tratamiento de imágenes o framework, por ejemplo imagemagick, la clase Pixmap del framework Qt o la función PixBuf del framework GTK+. Una vez decodificada la imagen, el tratamiento sería el mismo que el mostrado aquí, las librerías anteriores solamente decodifican la imagen y la convierten en un mapa de bits (como un bmp nativo).
  • Ocultar el texto en una posición aleatoria de la imagen, actualmente se empieza a ocultar a partir de la posicion 54.
  • Comprimir el texto con algún algoritmo conocido, por ejemplo Base64.
  • Permitir encriptar el texto con algún algoritmo de encriptación, tanto de clave simetrica como de clave asimétrica.
  • Introducir un hash del texto en una parte aleatoria de la imagen que no coincida con la posición del texto, con esto podriamos comprobar que el texto no ha sido modificado.

Hide Grub completely on boot

Months ago I had to setup an industrial PC with linux and I needed optimize system boot in order to work as a real time system.

In this PC, lubuntu was instaled and Grub was active. On the boot, when grub passed, the system boot in a reduced time. So, I need hide grub in order to it doesn't show at boot the system in order to reduce boot time. This task is very simple, we can do that with config file or with an application specialized in it.

The problems appeared when in some performance test GRUB continued to appear and this time Grub didn't have a timer to disappear with no human interactions.

This used to occur when current was interrupt just after that BIOS appears but before the Operating System was loaded.

The explain is when the system is shutdown incorrectly GRUB enable a bit called recordfail. If this bit is enable GRUB won't show the timer and will need the human interaction.

I was seaching program that can modify this bit but I don't find anything. Finally I modify GRUB script my self in order to remove any occurence of recordfail variable. Then I found the solution by modification of config file. The file that we need to modify is /etc/default/grub and the first part of this fill must match with:

The options in order to disable recodfail is GRUB_RECORDFAIL_TIMEOUT="0"

After modify that file we must run the following command:

update-grub

Ocultar totalmente Grub al arrancar en sistemas Linux

Hace poco he tenido que poner en marcha un PC industrial con un linux y necesitamos optimizar el arranque lo máximo posible puesto que va a ser un sistema de tiempo real.

Este PC llevaba instalado lubuntu con GRUB activado y una vez pasado GRUB el PC iniciaba en un tiempo bastante reducido (menos de 10 segundos) así que lo que había que hacer era ocultar GRUB al arranque para poder conseguir menor tiempo de arranque, quitarlo es realmente sencillo, ya sea mediante fichero de configuración o mediante algún programa especializado en ello.

El problema apareció cuando en determinadas pruebas de rendimiento (en donde cortabamos la corriente varias veces) GRUB seguía apareciendo y no solo eso, sino que esta vez no había un temporizador de modo que si pasan X segundos GRUB elige la entrada por defecto, es decir, GRUB no desaparecia si no era por la acción humana en estas determinadas ocasiones.

Esto solía ocurrir cuando se cortaba la corriente justo después de que apareciese la BIOS pero antes de que cargase el Sistema Operativo.

La explicación a esto es que cuando el sistema se apaga incorrectamente se activa un bit en GRUb llamado recordfail que hace que si el sistema se apaga incorrectamente se muestre GRUB y sea necesaria la acción humana para pasar de GRUB (esto lo descubrí ojeando los script de GRUB).

Estuve buscando programas que modificasen ese bit pero creo que no hubo ninguno que sirviese para tal fin. Así que lo que hice inicialmente fue modificar los script de inicio de GRUB para borrar cualquier mención a ese bit. Pero posteriormente encontré las opciones especificas para poder modificarlo desde un fichero de configuración. Para ello hay que modificar el fichero /etc/default/grub y que la primera parte coincida con:

La opción para deshabilitar el recordfail es GRUB_RECORDFAIL_TIMEOUT="0"

Después de modificar este fichero hay que ejecutar el comando:

update-grub