1.10.12

Jugando a romper claves con tarjetas gráficas

Publicado en las jornadas de Avances de Seguridad en Internet, ASI10, en Marzo de 2012, de Ángel Rodríguez Monterrubio.

 

1 ASI 10 (2012) GPU CRACKING

A lo largo de la historia, se pueden encontrar multitud de ejemplos donde una parte esta interesada en ocultar información, y otra parte está interesada en revelar esa información oculta. Criptografía y Criptoanálisis son las áreas del conocimiento humano que respectivamente intentan ocultar y revelar. Ver por ejemplo La Criptografía de Julio César y el Kamasutra.

Podemos definir un criptosistema como el sistema formado por un conjunto de mensajes sin cifrar, unos mensajes cifrados y unas claves; estos elementos se relacionarán entre sí por la manera de cifrar y por la manera de descifrar. Criptoanálisis se puede considerar por tanto como los mecanismos que permite romper un criptosistema. Sin entrar en detalles, todas las técnicas de criptoanálisis, en mayor o menor medida, comparten la repetición de la misma operación sobre, idealmente, grandes conjuntos de datos.

Es en este aspecto, en el de la ejecución de la misma tarea sobre una gran cantidad de datos donde la relación entre GPU y Criptoanálisis es más estrecha.

Las tarjetas gráficas no solo sirven para jugar a juegos increíbles, es su principal función sí, pero están a su vez dotadas de un interesante efecto colateral: Una brutal capacidad de cálculo en paralelo. Esta capacidad de cálculo ha evolucionado espectacularmente a lo largo de los últimos años, sobrepasando incluso la ley de Moore en lo que a Operaciones Por Segundo se refiere. La GPU  geForce GTX 480, por ejemplo, alcanza las 1400 GFLOPS (Giga Floatingpoint OPS), muy por encima de un Westmere (i7) que no alcanza las 250 GFLOPS. Los mismos datos se pueden aportar respecto del ancho de banda para procesado de datos, cerca de 180 GB/s frente a los cerca de 40 GB para el i7. Y continúa creciendo, incluso mientras lees este artículo.



Esto hace que se disponga a nivel doméstico y por poco más de 400 € de una capacidad de cálculo imposible de concebir hace unos años. En consecuencia, criptosistemas robustos o considerados robustos pueden verse comprometidos, ya no solo por los grandes centros de investigación, si no a nivel "ambulatorio" por cualquier individuo interesado, en su propio domicilio.

Una GPUs es un procesador de propósito específico. Su objetivo es la renderización de entornos 3D en tiempo real, ejecutando la misma operación sobre grandes conjuntos de datos. Es ordinario que estos dispositivos tengan varios GB solo para el procesado de datos, del orden de 1 GB, aunque versiones profesionales pueden llegar a los 4GB. Esta memoria suele ser de alta velocidad de acceso y transferencia.

En la layout del los componentes de la GPU, se ha sacrificado espacio de control sofisticado y de caché, para aumentar la superficie dedicada a cómputo. Esto desemboca en una arquitectura de propósito específico con caches reducidas, elevado número de elementos de proceso y una optimización para acceso secuencial a los datos.



Existen tecnologías que nos permiten acceder a toda esta potencia de cálculo y realizar operaciones en paralelo sobre el dispositivo, abriendo así unas increíbles posibilidades para el GPU cracking o criptoanálisis sobre GPUs. Estas tecnologías se basan en la ejecución de programas de manera bivalente, entre el CPU o HOST y la GPU. Prepararemos los datos en el HOST y desde allí los cargaremos en la GPU, ésta realizará los cálculos y recibiremos los datos de nuevo en el HOST para explotarlos como consideremos necesarios. Será la GPU la encargada de ejecutar en paralelo y sobre los conjuntos de datos extensos operaciones en unos tiempos varios ordenes de magnitud inferiores a una ejecución en el HOST. Incluso es posible convertir en tratable un problema que computacionalmente se ha considerado como intratable de manera general.

Para trabajar sobre la GPU podemos contar con la tecnología Compute Unified Device Architecture (CUDA), de nVdia, aunque existe también una tecnología equivalente para las GPUs AMD.

La arquitectura CUDA arranca en los motores de computación paralela dentro de las GPUs, el autentico horsepower de computación de una GPU.  A través del Driver del dispositivo y el soporte del núcleo del sistema operativo, es posible cargar  el código nativo que será ejecutado por la GPU.  El código nativo que ejecuta la GPU no es más que una versión de C con extensiones para CUDA, compilado para poder ser ejecutada en ésta.

Internamente la arquitectura de la GPU esta dividida en varios Stream Multiprocessors o SM. En un SM puede haber hasta 32 Streaming Processors para la ejecución de operaciones simples en paralelo y hasta 4 para la ejecución de funciones más complicadas. Además cada SM cuenta con circuitería para controlar la ejecución en paralelo, un banco de registros para los Stream Processors y un banco de memoria compartida. Cada SM podrá acceder a los datos almacenados en la memoria global del dispositivo,  que es algo mas lenta que la memoria compartida.

El modelo de memoria sigue una escala progresiva de manera que los registros de cada Streaming Processor son los más rápidos pero de tamaño mas reducido, la memoria compartida la siguiente en cuanto a velocidad, con algo más de tamaño, pero no demasiado (varios KB) y por último con gran capacidad y más lenta la memoria global del dispositivo.

Todo lo que hemos visto hasta aquí, puede resultar bastante familiar, sin embargo, donde cambia el paradigma es en el modelo de programación.  La pieza de código que será ejecutada en paralelo por los SM es conocida como kernel. Un kernel es una pieza de código que será ejecutada en paralelo por la GPU en un hilo de ejecución. El número de hilos o veces que se ejecutará nuestro kernel, en paralelo, depende de la extensión de nuestros datos.  Los hilos pueden agruparse, de tal manera que los hilos pertenecientes a un grupo acceden a la misma memoria compartida, y todos los hilos pueden acceder a la memoria global. Podemos decir por tanto que un Kernel es ejecutado N veces por N hilos que se agrupan en bloques. Dentro de cada bloque un hilo tiene unos índices que lo diferencian del resto. Es a través de esos índices en los que cada kernel accede a diferentes datos para su ejecución en paralelo.

El criptoanálisis, en cualquiera de sus formatos comparte gran cantidad de paralelismos con la computación en GPU. Los algoritmos de criptoanálisis ejecutan las misma operaciones de compromiso sobre grandes bloques de datos para poder intentar romper el criptosistema, precisamente el paradigma de ejecución en una GPU. A su vez la paralelización y ejecución en una GPU permite una reducción de tiempos considerables, en ocasiones de varios ordenes de magnitud, e incluso de hacer tratable un problema que no lo es.

El acceso a grandes capacidades de cómputo por el gran público, con la democratización de la capacidad de cálculo y las similitudes entre las herramientas de criptoanálisis y  el GPGPU Computing hace que estemos cerca de que los tiempos de rotura de los criptosistemas considerados seguros, estén en cierta medida comprometidos.

Existen multitud de herramientas que hacen uso de GPGPU para acelerar los cálculos necesarios para, por ejemplo, recuperar una contraseña. Éste es el caso de oclHashcat-plus (http://hashcat.net/oclhashcat-plus/) o de ighashgpu (http://www.golubev.com/hashgpu.htm) estas herramientas de password recovery (ó GPU cracking) hacen uso de la GPU ofreciendo recortes de tiempo espectaculares.

Mientras que sólo CPU tarda 4 días



Si utilizamos un software que utilice la aceleración en la GPU como ighashgpu (y tanto aceleración) para romper el password...,



en minutos...

No hay comentarios:

Publicar un comentario

Nota: solo los miembros de este blog pueden publicar comentarios.