miércoles, junio 08, 2016

¿Tienes un oído fino? Cifrado y esteganografía de datos en ficheros de audio y un test de estegonanálisis con tu oreja

Tras ver la invitación de Chema Alonso para escribir algún artículo en El lado del mal me decidí a enviar un resumen de lo que fue mi proyecto final de carrera de ingeniería informática, en el que tocaba el tema de esteganografía y cifrado de datos en ficheros de audio. Hace poco se habló de una técnica parecida en el artículo "Esteganografía con ficheros de audio: enviar tus documentos ocultos en canciones", pero en este trabajo se añade la capa de cifrado y el trabajo se hace con MatLab, así que espero que os sea de utilidad y complemente un poco más el conocimiento de las técnicas de esteganografía y estegoanálisis.

Figura 1: ¿Tienes un oído fino? Cifrado y esteganografía de datos en
ficheros de audio y un test de estgonanálisis con tu oreja

Considero que todo documento científico debe contar con una breve introducción de los conceptos que se tratarán, así que, para empezar a tener claras las ideas, me gusta empezar siempre con definiciones y, si es posible, dar algunas pinceladas de etimología a los términos sobre los que escribo. Y aquí van:
Definición 1: esteganografía es la ciencia que trata el estudio y la aplicación de un conjunto de técnicas que permiten ocultar o esconder información, de modo que no se perciba su existencia. 
Etimología 1: Estegano-, del griego tégos-/steganos, que significa disimular, disfrazar o cubrir. 
Definición 2: criptografía es el arte de escribir con clave secreta o de un modo enigmático. 
Etimología 2: Cripto-, del griego kryptós, que significa recubierto.
Etimología 3: -grafía, de la raíz del griego grafein, que significa escritura o representación gráfica.
Con todo esto presente, mi objetivo fue construir un criptosistema que fuera capaz de cifrar información y para posteriormente esconderla dentro de un fichero de audio en formato WAV, maximizando la cantidad de mensaje a ocultar y minimizando todo lo posible el ruido introducido. Para la parte del cifrado me decanté por usar cifrado asimétrico RSA y para la de esteganografía, utilicé 2 métodos, uno bastante empleado, como es el LSB y otro no tanto, conocido como Phase Coding.

Explicación del funcionamiento del criptosistema

El sistema consta de dos capas de seguridad, la primera será criptográfica, ya que a toda la información que se pretenda transmitir, le aplicaremos un cifrado asimétrico. Una vez tenemos la información cifrada, realizaremos el proceso de esteganografía, escogiendo para ello un fichero de audio WAV como portador y ocultando en él los datos cifrados en el paso anterior.

Figura 2: Diagrama global del criptosistema

En la Figura 2 vemos cómo encajan todos los subsistemas entre sí, donde las cajas rojas conforman el subsistema criptográfico, que se corresponden con los procesos de cifrado y descifrado. Aquí es importante destacar que el emisor cifra la clave secreta (o clave de sesión) con la clave pública del receptor y que el mensaje se cifra usando la clave secreta, generada automática y aleatoriamente por GPG4WIN.

Las cajas azules conforman el subsistema esteganográfico, que se corresponden con los procesos de ocultación y extracción. El resto de elemento son las entradas y salidas del sistema, y un medio de transmisión.

Explicación general de cada subsistema

Teniendo una visión global del sistema, veamos el comportamiento de cada uno de sus elementos de procesamiento de la información.

Subsistema criptográfico: es el componente que aplica un algoritmo de cifrado o descifrado, en función de la etapa en la que se encuentre la información que procesemos dentro del sistema global. Recurrimos a RSA 2048 bits, mediante la herramienta GPG4WIN. En la Figura 1 se ve el flujo de la información y cuándo entra en juego cada componente. Para gestionar nuestro criptosistema de la forma que queremos, debemos configurar adecuadamente GPG4WIN. Los pasos a seguir son:
1. Crear un certificado de tipo ‘OpenPGP key pair’
2. Introducir algunos datos personales: Dentro de las opciones avanzadas, elegimos el uso que le vamos a dar. En nuestro caso solo queremos cifrar, así que elegimos el método RSA con 2048 bits y marcamos la casilla de ‘Encryption’.
3. Crear una ‘passphrase’ para cifrar la clave privada (este cifrado es tipo simétrico)
Si todo el proceso se ha llevado a cabo correctamente, obtendremos una ventana de confirmación que nos mostrará el ‘fingerprint’ de nuestro certificado. Con este certificado será con el que podamos cifrar/descifrar ficheros. Para cifrar en GPG4WIN lo podemos hacer con el propio gestor de certificados que incluye, llamado Kleopatra. Simplemente lo abrimos y seguimos estos pasos:
1. Elegimos ‘Sign/Encrypt Files’, y marcamos la opción de Encrypt. Seleccionamos el fichero a cifrar.
2. Seleccionamos el certificado que queramos usar para cifrar. En este caso, como ya lo tenemos creado, seleccionamos y añadimos el que hemos hecho anteriormente.
3. Pulsamos en ‘Encrypt’ y esperamos a que el proceso finalice. El programa nos avisará.
Para descifrar en GPG4WIN lo haremos también con Kleopatra:
1. Elegimos ‘Decrypt/Verify Files’, y seleccionamos el fichero a descifrar. También podemos elegir dónde se guardará la información descifrada.2. Introducimos la ‘passphrase’ para nuestro certificado, que se nos indica en pantalla. Cada certificado que creemos tiene su propia ‘passphrase’, de modo que hay que recordarla para poder realizar el proceso de descifrado.3. Pulsamos en ‘OK’ y esperamos a que el proceso finalice.
Subsistema esteganográfico: es el componente que aplica un algoritmo de ocultación o extracción. Depende también de la etapa, y en la misma Figura 2 vemos las interacciones de este componente con el sistema.

1. LSB (Least Significant Bit): es un método de ocultación que se basa en esconder la información en los bits menos significativos del fichero de audio original. El proceso consiste en realizar una sustitución de los bits menos significativos de las muestras del audio original por todos los bits del mensaje. En la Figura 2 vemos un ejemplo de ocultación, donde:
• Audio: muestras de sonido del fichero WAV original. El subíndice indica el número de muestra y el superíndice indica el peso del bit de la muestra.
• Datos: cadena de bits del mensaje original.
• Portador: muestras de sonido del fichero WAV con el mensaje ‘Datos’ incluido.
Figura 3: Ejemplo de ocultación LSB. Sustitución de los bits menos significativos
de las muestras de audio original por los bits del mensaje

2. Phase Coding: Es un método de ocultación que se basa en esconder la información en la fase de las componentes espectrales de la onda de sonido que se obtiene a partir del audio original. El proceso de ocultación es como sigue:
a. Dividimos la señal acústica en varias ventanas de tamaño fijo.
b. Calculamos la DFT (transformada discreta de Fourier) de cada ventana, obteniendo la fase y la magnitud.
c. Elección de puntos de cada ventana candidatos para esconder la información.

i. Todos los puntos que cumplan Thmin < magnitud < Th albergarán el mensaje a ocultar.
• Umbral, Th, es un porcentaje del valor máximo de la señal.
• Umbral mínimo, Thmin, es un valor fijo obtenido de forma empírica, 10^-4 genera 0 errores.
ii. Para cada punto, dejaremos el valor de la fase original, con el siguiente criterio:
• Si bit a ocultar 0, entonces: (-1) x fase
• Si bit a ocultar 1, entonces: (1) x fase
Figura 4: Pasos para aplicar el método de esteganografía de Phase Coding

Implementación de esteganografía con Matlab

Entrando un poco más en materia, paso a explicar cómo implementé ambos algoritmos esteganográficos en Matlab.

• LSB, ocultación:
1. Leer fichero con los datos a esconder
[Datos, count] = fread(fopen('C:\ruta\mensaje.txt'));
Datos = matriz de ‘count’ filas (cada caracter) y 1 columna.
count = cantidad de caracteres leídos.
2. Leer fichero de audio, que hará de portador
[x,fs] = audioread(ruta);
x = muestras de audio
fs = frecuencia de muestreo
3. Sustituir los bits menos significativos de ‘x’ por todos los bits que haya en ‘Datos’
% La parte del mensaje que cabe justa
coded(1:F_smr,(end-LSB+1):end) = stego_mensaje;
% La parte del mensaje que sobra
coded(F_smr+1,end-sobran+1:end)=Datos(L_esconder-sobran+1:end);
Básicamente estos son los pasos, pero se ve mucho mejor en la Figura 3. Hay que tener en cuenta que hay que moldear bastante las matrices y jugar con los tipos de datos en Matlab, para poder ajustar todos los cálculos, ya que el algoritmo lo hice para poder escoger una cantidad variable de bits menos significativos.
4. Crear un nuevo vector de muestras, que contenga el mensaje sustituido y el resto de muestras originales, es decir, las muestras del fichero portador, incluyendo el mensaje a esconder.
y = coded;
audiowrite(‘C:\ruta\LSB-codedAudio.wav’, y, fs);
• LSB, extracción:
1. Leer fichero de audio, que es el portador del mensaje oculto
[x_ext,fs_ext] = audioread(‘C:\ruta\LSB-codedAudio.wav’);
2. Extraer los bits menos significativos de ‘x_ext’
% Recupero el mensaje, por partes: la divisible, y el resto
% 1º Recupero la parte divisible del mensaje
recup1 = x_ext(1:F_smr,end-LSB+1:end);
% 2º Recupero la parte que falta del mensaje
recup2 = x_ext(F_smr+1,end-sobran+1:end);
% Juntamos todo
recup = vertcat(recup1,recup2);
3. Crear un nuevo fichero que será el mensaje extraído.
fwrite(fopen('C:\ruta\mensaje_extraido.txt','w'), recup);  
%Recordad que este mensaje extraído está cifrado.
• Phase Coding, ocultación:
1. Leer fichero de audio y dividir la señal en ventanas
[x,fs] = audioread(ruta);
% Longitud archivo portador en muestras
T = length(x);
% Longitud de cada segmento
L = 1024;% Numero de segmentos
N = floor(T/L);
% División en segmentos de la señal (cada columna un segmento)
for n=1:N
xf(:,n) = x((n-1)*L + 1:n*L);
end
2. Calcular DFT y obtener fase y magnitud
% DFT de cada segmento (fft lo hace de golpe)
Xf = fft(xf);
% Matriz de magnitud original
M_ori = abs(Xf);
% Matriz de fases original
P_ori = angle(Xf);
3. Calcular umbrales y obtener los puntos candidatos
Th = porcentaje*max(M_ori(:)); Th_min = 0.0001; indhide = find(M_ori<Th & M_ori>Th_min);
4. Calcular umbrales y obtener los puntos candidatos
for k=1:L_esconder % desde 1 hasta el tamaño del mensaje que quiero esconder
if Datos(k)==0
P_hide(indhide(k)) = abs(P_ori(indhide(k)))*(-1);
else
P_hide(indhide(k)) = abs(P_ori(indhide(k)))*(+1);
end
end
5. Crear el audio portador con el mensaje a esconder.
% Mensaje portador con datos ocultos
Xhide = M_ori.*exp(1i*P_ori);
xm = real(ifft(Xhide));
audiowrite(‘C:\ruta\PC-codedAudio.wav’,xm,fs);
• Phase Coding, extracción:
1. Los pasos para extraer son los mismos que para ocultar, desde el 1 al 3 
2. Extraemos la información del vector con los puntos candidatos
% Extraer índices de los puntos con bits ocultos
indhide = find(M_decod<Th & M_decod>Th_min);
indhide = indhide(1:L_esconder);
Decp = P_ decod(indhide);
Recordad que ‘L_esconder’ es el tamaño del mensaje que voy a extraer. En principio lo sabemos de antemano, pero se podría crear un espacio dentro del mensaje a ocultar para indicar cuál es su tamaño, y transmitirlo también una vez cifrado y ocultado. 
3. Extraemos el mensaje oculto
% Mensaje extraído en Datadec
Datadec = (Decp<=0)*0 + (Decp>0)*1;
Guión final y resultados

Bien, ahora que hemos visto cómo funciona cada parte por separado, vamos a hacer un pequeño guión de cómo hacer funcionar todo el sistema.

CIFRADO Y OCULTACIÓN
1. Elegimos un fichero cualquiera que será nuestro mensaje a ocultar.
2. Elegimos un fichero de audio, en formato WAV, que será nuestro portador.
3. Ciframos el fichero con GPG4WIN.
4. Ocultamos el mensaje obtenido en el paso 3 mediante una técnica esteganográfica: LSB o Phase Coding.
5. Obtenemos un fichero WAV con el mensaje incluido. Este fichero lo podemos transmitir o almacenar teniendo 2 ventajas principalmente:
a. Tenemos la información escondida, luego será más difícil encontrarla para cualquiera que no sepa dónde/cómo buscar.
b. Tenemos la información cifrada, de modo que, incluso aunque se llegue a descubrir que tenemos información oculta, sería casi imposible descifrar sin tener la llave.
EXTRACCIÓN Y DESCIFRADO
1. Elegimos un fichero de audio que sea portador.
2. Extraemos el mensaje mediante una técnica esteganográfica: LSB o Phase Coding.
3. Desciframos el fichero obtenido en el paso 2 con GPG4WIN.
Para comprobar que todo este proceso de cifrado y ocultación funciona bien, quise realizar una serie de pruebas a personas de mi entorno. Recurrí para ello al test ABX, que es un tipo de prueba auditiva que se realiza a ciegas, lo que se conoce también como ‘blind test’, es decir, que el sujeto desconoce el origen del audio que escucha. Para hacer las pruebas más sencillas, recurrí a la herramienta llamada Lacinato ABX/Shootouter, que permite cargar ficheros de audio, y realizar la prueba de forma automática, mostrando los resultados obtenidos por cada sujeto. Sin entrar en mucho detalle matemático, necesariamente derivado de este tipo de pruebas, os explico en qué consiste el test ABX.

Figura 5: Herramienta Lacinato ABS/SHootouter

Durante la prueba, una de las muestras recibe el nombre de A y la otra muestra recibe el nombre de B. El programa elige una muestra X, que puede ser cualquiera de las muestras A o B, que el usuario ha indicado como banco de muestras, pero el sujeto no sabe cuál es. La tarea del sujeto es escuchar atentamente todas las muestras, tanto A y B como X, y entonces decidir si X se corresponde con la muestra A o con la muestra B. Por cada vez que el sujeto se vea sometido a esta elección, lo llamaremos intento. Al final de la prueba, se analizan el número de pruebas realizadas, el número de aciertos y fallos.

Las señales acústicas que hemos elegido para el test se pueden agrupar en cuatro tipos diferentes de audio:
Música clásica: Sinfonía nº 6 en Fa mayor, op. 68, “Pastoral”, Ludwig Van Beethoven.
Música comercial: Diamonds, Season One, Emancipator.
Música pop-rock: Cuando los ´árboles se sequen, Casa Grande, Marco Boz y Pablo Páez.
Voz hablada: Blue Sky Bridge, narración en inglés, Fergus Sound Enterprises.
Estos cuatro tipos de audio son muy comunes a día de hoy, por lo tanto, son un adecuado objeto de estudio para nuestro proyecto. Cabe destacar que los formatos de los audio obtenidos son del tipo sin pérdida, concretamente en formato WAV. Esto es así para poder trabajar a partir de un material que ofrezca el menor error posible. Destacar que, para homogeneizar las muestras, todos los audio han sido normalizados y convertidos a monocanal con 16 bits de profundidad. Los resultados que obtuve para cada algoritmo esteganográfico fueron los siguientes:
Resultados para LSB: Para evitar detección auditiva, recomiendo utilizar como máximo los 4 bits menos significativos. Capacidad de ocultación del LSB es el producto del número de muestras del audio original y el valor de LSB elegido en cada caso: numero_muestras x N lsb 
Resultados para Phase Coding: Para evitar detección auditiva, recomiendo utilizar un valor Th ≤ 10-4.
Es importante tener en cuenta que lo que más pesa a la hora de realizar un buen proceso de ocultación es el fichero portador. En nuestro caso, cuanto más intenso sea el nivel de sonido de nuestra onda portadora, más disimulará el contenido oculto. Por eso he especificado qué tipo de fragmentos musicales he utilizado, y también porque necesitaba una base sobre la que partir. Es por ello que se hace complicado dar un valor preciso que indique cuánta cantidad de información puedo introducir por muestra mediante esta técnica.

Para terminar, ahora que os he soltado toda esta marea de ideas y conceptos, aquí podéis escuchar los ficheros de audio y realizar vosotros mismos vuestras comparativas. Os los dejos organizados por carpetas y por estilos musicales [Audios CodificadosAudios Originales] ¿Hasta dónde sois capaces de detectar el ruido en cada técnica? Empieza el reto ;)

Autor: Jorge Peris (Universidad de Valencia)

9 comentarios:

  1. Excelente trabajo, aunque estaría bien conocer si se puede hacer sobre ficheros mp3, ya que son más comunes que los wav.

    ResponderEliminar
  2. Hola +Ernesto Sanchez, muchas gracias. Sí que puede hacerse con MP3, de hecho tienes una herramienta bastante conocida (y funcional) que ya lo hace, se llama MP3stego y fue desarrollada por Fabien Petitcolas. En este caso, este autor aplica el cifrado después de comprimir. Yo quise evitar formatos con compresión, principalmente porque planifiqué los test auditivos, y quería eliminar todos aquellos ruidos que pudiesen interferir en el propio ruido del experimento (el ruido que inherentemente introducen los algoritmos de ocultación).

    Un saludo.

    ResponderEliminar
  3. Buenísimo, felicitaciones por tu trabajo, muy interesante.

    ResponderEliminar
  4. Muchas gracias +Nicolás Bruna ;)

    ResponderEliminar
  5. Muy buen trabajo y muy interesante! ;)

    ResponderEliminar
  6. necesito ayuda en 00webhost , no me hace la conexion

    ResponderEliminar
  7. Excelente trabajo!!muy interesante!

    ResponderEliminar