jueves, 13 de noviembre de 2014

El arte de la esteganografía

Muchos autores han definido a la esteganografía como el arte de ocultar información [1], con el cual se tiene como propósito intercambiar información por un medio sin que se revele la existencia de dicha información. Es diferente de la criptografía, ya que en dicha área lo que se busca es hacer ilegible un mensaje, aunque no le es posible ocultar información.

La esteganografía moderna se inspira en archivos binarios [2], cada archivo de una computadora es una secuencia de bytes que a su vez es una secuencia de bits. Pero antes de empezar a hablar de la esteganografía, me gustaría explicar que són los bytes y los bits.

Me gusta imaginar a los bytes como "las envolturas" de una caja (el archivo binario), y cada envoltura puede tener ocho bits "o dulces", en el que cada dulce puede ser un 0 ó un 1. Varios ejemplo de bytes se encuentran a continuación:

$11001100$, $00110011$, $11111111$, $00000000$, $10111101$

En cada byte existe un bit que es llamado el bit menos significativo (LSB en sus siglas en inglés) que es el que se encuentra más a la derecha en la cadena binaria. En los ejemplos anteriores el LSB para cada byte serían los siguientes:
  • LSB de $11001100 = 0$
  • LSB de $00110011 = 1$
  • LSB de $11111111 = 1$
  • LSB de $00000000 = 0$
  • LSB de $10111101 = 1$
Se le llama bit menos significativo porque es el que tiene el "menor peso" en el byte, es decir, sólo puede representar un $0$ ó un $1$ cuando se convierte a un número decimal. Por ejemplo, el byte $11001100$ en décimal es el número $204$, mientras que el byte $11001101$ (nótese que se cambió el LSB de 0 a 1) es el número decimal $205$. Es evidente que el cambio en un byte no es muy drástico si se modifica este bit en particular.

La importancia del LSB radica en que si se modifica este bit es posible introducir nueva información en una secuencia de bytes, por ejemplo, un caracter de $n$ bits puede ser ocultado en $n$ bytes. Siguiendo esa lógica, se puede deducir que en un archivo binario hay muchísimos bytes "disponibles" para modificar su bit menos significativo y así guardar un mensaje.

Dependiendo del tipo de archivo binario y si el contenido se puede distinguir de alguna manera por  humanos, que por lo general es por medio del sentido del oído y de la vista, es posible encontrar "ruido" con el que se podría sospechar que el archivo ha sido modificado de alguna manera. No obstante, es mucho más evidente  [3] cuando el tamaño del mensaje es comparable al tamaño de un sample [7] de audio.
Si el archivo de audio tiene calidad comparable a la de un CD [5] entonces se dice que tiene un sample rate de 44100 Hz, es decir, cada 44100 samples equivale un segundo, aunque también es muy común encontrar archivos de audio que tengan sample rate de 48000 Hz. 
Además del LSB existen otras técnicas para ocultar información [4] en un archivo binario, aunque si no se tiene otra opción se puede mejorar los resultados de LSB si se elige el conjunto correcto de bytes a modificar.

Como última tarea para la clase de Seguridad de la Información y Criptografía se pidió implementar una aplicación de esteganografía que oculte un mensaje en un archivo de audio. Por su sencillez y la documentación disponible [5] se eligió el formato de audio WAVE como archivo contenedor de un mensaje oculto, aunque mi programa no discrimina el tipo de archivo ya que lo lee por igual, aunque lo más probable es que borre información de cabecera. Es algo que necesito corregir en un futuro.

La estructura de un archivo WAVE es simple: los primeros 44 bytes guardan información de cabecera y de allí en adelante se guarda información de audio que están disponibles para aplicarles un poco de esteganografía "casera". (Actualización pequeña después de releer el párrafo: si, perdón por la tonta rima improvisada)
Depende mucho de como se grabó el audio para determinar el tamaño de un sample en WAVE en términos de bytes [9], para sonido modo son de 1 y 2 bytes (8 y 16 bits), mientras que para sonido estéreo son de 4 bytes (32 bits). En el caso de sonido estéreo cada par de bytes representan un canal, y estos pares de bytes se leen con el sistema little-endian.
En esta última actualización (20 de noviembre 2014) me di cuenta que interpreté mal esta información del sistema little-endian [10]. Confieso que lo ignoré hasta este momento porque creí que, comparado con los resultados de las primeras pruebas que realicé, ya no escuchaba tanto ruido en los audios modificados con la última versión de mi programa, por lo que me gustaría consultar esto con la profesora para resolver mis dudas y así mejorar mi aplicación.
Estructura del formato WAVE [6]

Función para ocultar y recuperar información

Estas son las principales funciones del programa, dependiendo del tipo del mensaje (texto o archivo binario) sigue una secuencia de flujo. La función ocultar proporciona mecanismos de seguridad para encriptar la información (de la que se describirá en breve) y para generar información que será utilizado por la función recuperar.

Se define un alfabeto de $n$ bits que incluye todas las letras del idioma inglés, los dígitos del 0 al 9 y otros caracteres de uso común. Por tanto, antes de ocultar el texto primero preparo el mensaje, porque en caso de que el mensaje contenga caracteres que no aparezcan en el abecedario, esos caracteres serán eliminados y reemplazados con un amistoso caracter de "?".

Casos de uso #1 - Ejecución típica del programa



Funciones para generar el conjunto de bytes

Estas funciones auxilian a las funciones de ocultar y recuperar generando una secuencia determinista de bytes a modificar. En mi programa utilizo el último byte como indicador para la función recuperar de cuándo debe dejar de buscar nuevos bits, pero también lo utilizo en la función ocultar para hacer cifrados XOR del mensaje de texto. En caso de que el mensaje es un archivo binario no se cifra el "mensaje".



Función de cifrado

Como ya se había comentado, el mensaje de texto se cifra con un número especial (el último byte que se modifica). El mensaje de texto está conformado de caracteres del abecedario ya definido anteriormente, por lo que se puede decir que un caracter puede ser identificado como un número entero decimal y también como una cadena binaria. Teniendo en cuenta esto, el mensaje de texto se puede ver como una concatenación binaria a la cual se le puede aplicar una operación XOR con la representación numérica binaria del último byte. El resultado de esta operación es una concatenación de caracteres que será ocultado en el archivo de audio.

El número especial, el último byte, de alguna manera debe ser conocido por el usuario para recuperar los mensajes, pero es un poco peligroso conocerlo porque da pistas de la generación del conjunto de bytes a modificar. ¿Entonces qué se puede hacer para evitar esta paradoja? Cifrar una representación binaria de dicho número con un número pseudoaleatorio binario.

Recalco aquí que en vez de convertir el último byte a número binario lo que hago es hacer una concatenación binaria de los dígitos del último byte, lo que me permite utilizar información del abecedario, esto con el fin de confundir un poco al usuario y evitar que se pierdan "los dígitos". Al final lo único importante es que el usuario introduzca las claves cuando desea recuperar un mensaje en un archivo de audio.

Con las operaciones comentadas garantizo que, en teoría, sea virtualmente imposible recuperar un mensaje sin conocer las claves. Así ocurre porque sin la clave pseudoaleatoria no es posible recuperar el último byte, y en caso de que se quiere recuperar un mensaje de texto, no sería posible descifrarlo sin la información del último byte. En caso de querer hackear esto se tiene que realizar muchas operaciones por fuerza bruta para siquiera intentar romper esta barrera.

En el caso de que se oculte un archivo binario, las cosas cambian un poquito. El último byte sigue representado como una cadena de bits asociada al abecedario y también se cifra, pero en vez de recuperar los caracteres del resultado de la operación, recupero la posición de cada caracter en el abecedario.

Decidí hacerlo así porque cuando se oculta un archivo binario tengo que definir un abecedario de acuerdo a Unicode, es decir, tengo 256 "caracteres" que van desde la posición 0 hasta 255 en el abecedario. Como en este abecedario de 8 bits existen caracteres especiales de control, prefiero conocer la posición (expresada en tres dígitos) del caracter cifrado y concatenar las posiciones de dichos caracteres. Al final de cuentas, como la posición del último caracter en el abecedario es de 255, que es un número de tres dígitos, implica que en esta concatenación cada tres dígitos me identifica el caracter cifrado.



Longitud del mensaje y del archivo contenedor

Dependiendo de si el mensaje es un mensaje de texto o es un archivo binario es entonces que se determina la secuencia de bytes a generar. Por cuestiones de seguridad me reservo a revelar cómo genero la secuencia de bytes.

Al final de cuentas los experimentos que realicé fue más que nada para demostrar que se puede ocultar mensajes de los dos tipos y darme una idea del conjunto ideal de los bytes que serán utilizados para ocultar mensajes de texto.


Casos de uso #2 - El programa reconoce que no es posible guardar todo el mensaje en el archivo



Ocultar archivos binarios

Cuando oculto archivos binarios no busco garantizar la integridad del archivo contenedor, sino que sea posible ocultar y recuperar ese archivo binario. Los resultados son tal como sigue (con algunos errores que no comprometieron el programa).


Casos de uso #3 - Guardar un archivo binario (una imagen) en el archivo WAVE contenedor







Casos de uso #4 - Pedir ayuda




Propiedades estadísticas de los archivos de audio

Se utilizó el programa Audacity para comprobar el waveform y el análisis de frecuencia para un archivo original y su correspondiente modificado. Como guía en la imagen del waveform el diagrama superior representa al canal izquierdo del audio, mientras que el diagrama inferior representa al canal derecho del audio.

En particular no encuentro diferencias a simple vista, aunque cuando escuché ese audio encontré un poco de ruido en el archivo modificado.

Waveform del archivo original


Análisis de frecuencias del archivo original de audio


Waveform del archivo modificado con un archivo de texto


Análisis de frecuencias del archivo  modificado que oculta un archivo de texto
Estudio de desempeño
Caracteres/Bytes Tiempo para ocultar
82 caracteres 7.36 segundos
511595 caracteres 61.54 segundos
15625 bytes 3 minutos, 0.368265 segundos
Estudio de desempeño
Caracteres/Bytes Tiempo para recuperar
82 caracteres 0.036 segundos
15625 caracteres 0.55 segundos
511595 bytes 17.11 segundos



Resultados y conclusiones

Esta fue una actividad muy interesante de realizar porque nunca había trabajado directamente con archivos binarios y descubrí que no es nada difícil hacerlo, lo único que es importante es conocer la estructura del tipo de archivo. En mi caso admito que sigo escuchando un poco de ruido en mis archivos modificados, y creo que ocurre porque elegí una mala configuración para elegir los bytes a modificar (no lo voy a revelar por el momento) y quizás también por otras cuestiones relacionadas con el LSB de cada sample, por lo que quizás mis modificaciones inducen a que se escuche ruido audible por un ser humano.

En futuras mejoras del programa se piensa trabajar con más información de los samples y también proporcionar al usuario la oportunidad de decidir el formato de archivo a utilizar. Algunos ejemplos de formatos de audio [8] son: el formato WAVE (que es muy popular en la industria, pero en Internet no es fácil conseguir archivos), que es un archivo de audio sin comprimir y que en teoría no tiene pérdidas, el formato FLAC (que es muy popular en Internet por los audiófilos), que es un archivo de audio con compresión sin pérdidas y el formato MP3 (también muy popular), que es un archivo de audio con compresión con pérdidas.

Deduzco que realizar esteganografía en un archivo MP3 y similares no es una idea muy buena, pero creo que el usuario debe tener la opción de elegir el tipo de archivo de audio que contendrá el mensaje oculto.

Para el reto ideado por la doctora Elisa dejaré en los comentarios un enlace a Dropbox con los archivos que elegí para la competición :)

Referencias

[1] GC Kessler (2004), "An Overview of Steganography for the Computer Forensics Examiner"
[2] M.I.Khalil (2011) "Image steganography: hiding short audio messages withidin digital images"
[3] Zamani et al. (2009), "A Secure Audio Steganography Approach "
[4] B.B.Zaidan et al. (2010) "Overview: Main Fundamentals for Steganography"
[5] Estructura del formato de audio WAVE (documentación)
[6] Estructura del formato de audio WAVE (imágenes)
[7] Entrada de sampling en la Wikipedia en inglés
[8] Entrada de archivos de audio en la Wikipedia en inglés
[9] Estructura del formato de audio WAVE [samples]
[10] Entrada de endianness en la Wikipedia en inglés

Páginas de consulta

4 comentarios:

  1. Como expliqué en la entrada voy a subir los archivos originales y los modificados, además de un zip con el código fuente y las claves de los archivos modificados :)

    ResponderEliminar
  2. Mejoré un poco el código fuente, así que compartiré el enlace a Dropbox para las nuevas muestras. Me gustaría que estos nuevos archivos sean los que compitan en el reto, pero la decisión final recae en la profesora (el password del archivo comprimido es el mismo) y aceptaré lo que ella diga.

    https://www.dropbox.com/sh/9qcf0rrjpdlfa7w/AABzw8rR931-jMuFeTC1dRtCa?dl=0

    ResponderEliminar
  3. Muy bien, 10 pts. Usen los archivos del comentario justo encima de éste para el reto.

    + example runs on relevant use cases
    + ocultación exitosa de mensajes recuperables
    + explicación de cómo funciona todo
    + eval. de desempeño
    + security measures
    + a reasonably clever method of hiding messages
    + multiple media types (input and/or output)
    + manejo automatizado de la longitud de mensajes
    + método eficiente de procesamiento
    + study of statistical properties of the files
    + files provided for the detection challenge

    ResponderEliminar