29
Sep
2012

Computer Architecture y Cryptography en Coursera

Coursera es un proyecto libre, abierto y gratuito de enseñanza online, soportado por varias de las universidades más prestigiosas del mundo -principalmente universidades estadounidenses-.

A través de una moderna plataforma web, se brindan cursos no-presenciales de diversas áreas de las ciencias. Cada curso es guiado por un docente de la universidad que lo patrocina e incluye textos, materiales, slides, videos de las clases, ámbitos de intercambio con otros alumnos (con revisión periódica de los docentes) y evaluaciones. Algunos cursos, incluso, brindan un certificado de asistencia o realización de las tareas prácticas. Todo el material puede ser descargado para su visualización offline.

Los cursos duran entre 6 y 10 semanas en general. Sin embargo, al enrolarse en casi todos los casos es posible acceder completamente al material teórico y a los videos -especialmente cuando se trata de cursos dictados en una base regular-. Se recomienda hacer el seguimiento del curso en las fechas pautadas para poder acompasar su desarrollo con los aspectos prácticos y las evaluaciones.

Si no conocen, entren y vean: http://www.coursera.org.

Luego de esta introducción, quiero comentarles que estoy enrolado en dos cursos muy interesantes: Computer Architecture y Cryptography.

Computer Architecture

princeton university coursera

  • Comienzo: 30 de setiembre 2012
  • Duración: 10 semanas
  • Carga de trabajo: 5-8 horas por semana
  • Profesor: David Wentzlaff
  • Keywords: Computer Science: Systems, Security, Networking, Electrical and Materials Engineering

Enrolarse: https://www.coursera.org/course/crypto

Cryptography I

stanford university coursera

  • Comienzo: 5 de noviembre 2012
  • Duración: 6 semanas
  • Carga de trabajo: 5-7 horas por semana
  • Profesor: Dan Boneh
  • Keywords: Computer Science: Theory Computer Science: Systems, Security, Networking

Enrolarse: https://www.coursera.org/course/comparch

Quiero agradecer a mi amigo Mariano, que gracias a él conocí Coursera hace ya varios meses.

24
Mar
2012

Crypto++: cifrar bloque binario con AES + ECB

Crypto++ es una de las bibliotecas más importantes y recomendables para implementar funciones criptográficas en C++. Es de uso libre (open source) y funciona en múltiples plataformas (Windows, Linux, OS X). Si en algún momento deciden usarla, tomenlo con paciencia porque es un poco árida al principio.

En el día de hoy comencé a implementar una demo de CTR (streamcipher) en Qt/C++. Para esta implementación -que no es tan compleja-, necesité aplicar un blockcipher a bloques binarios de largo fijo. Elegí como blockcipher al algoritmo Rijndael. Como no era el objetivo implementar un Rijndael desde cero, decidí utilizar la funcionalidad que brinda Crypto++ (cryptopp).

Para facilitar el asunto, voy a estar trabajando con bloques y claves de 128 bits (16 bytes).

Al cifrar un único bloque de largo fijo e igual a 128 bits, no necesito padding ni técnicas de block-chaining (ej. CBC). Por lo tanto, el modo en el que necesitaba usar AES es ECB sin padding. Recordemos que ECB no encadena bloques realmente y en caso de que el texto plano se repita, se repetirá también el cifrado leakeando información. Por favor nunca utilizar ECB para cifrar mensajes de más de un bloque.

Hechas estas consideraciones, este es el código:


Leer el resto del artículo »

19
Mar
2012

Autenticación de mensajes: HMAC

Otro mecanismo para autenticar mensajes es utilizar una función de hash y una PSK (pre-shared key). Llamemos h a la función de hash.

¿Cómo se calcula el MAC?

h ( K XOR a || h ( K XOR b || m))

K es la clave compartida.
a y b son constantes pre-definidas. Según el NIST en su documento FIPS198a, a (outerpad) es el byte x’5c’ repetido la cantidad de veces que entra un byte como input de la función de hash. b (innerpad) se forma igual que a pero con el byte x’36’.
m es el mensaje a autenticar.

Según el NIST, en su documento FIPS198a:

The size of the key, K, shall be equal to or greater than L/2, where L is the size of the hash function output.

Calcular el HMAC de las siguientes formas está mal:

h ( K || m), h ( m || K), h (K || m || K), etc.

B. Schneier, en su libro Cryptography Engineering, considera que utilizar SHA-1 como función de hash es riesgoso. En su lugar -y para lograr una seguridad de 128 bits- recomienda SHA-256.

Leer el resto del artículo »

17
Mar
2012

Autenticación de mensajes: CBC-MAC II

Retomando el artículo anterior (Autenticación de mensajes: CBC-MAC), voy a comentarles aquí otros dos posible ataques a CBC-MAC.

Este ataque puede aplicarse también algunas funciones de hash. Supongamos que “c” tiene un bloque de largo. El atacante encuentra que MAC(a || c) = T y que MAC(b || c) = T. Como MAC(a || c) = E(MAC(a) XOR c) y MAC(b || c) = E(MAC(b) XOR c), entonces MAC(a) = MAC(b). Por lo tanto, si el atacante captura MAC(a || d), puede saber que MAC(b || d) tendrá el mismo tag.

Para la siguiente demostración, a la función MAC la voy a abreviar como M. Supongamos ahora que “a” y “b” tienen un bloque de largo. El atacante captura las MACs de “a”, “b” y “a || b”. Si captura “a || b”, entonces tiene E(M(a) XOR b). El atacante puede crear ahora la MAC del mensaje “b || M(a) XOR M(b) XOR b”. ¿Por qué? Ese mensaje tendría la siguiente MAC: E(M(b) XOR (M(a) XOR M(b) XOR b)). Si conmutamos y reasociamos, sería igual a E(M(b) XOR M(b) XOR M(a) XOR b). Pero M(b) XOR M(b) es igual a 0. Y 0 XOR ALGO es igual a ALGO. Entonces nos quedaría E(M(a) XOR b). PERO ESO ES M(a || b) QUE YA LO TENEMOS! Entonces usamos ese mismo tag y acabamos de autenticar un mensaje un tanto particular pero construido por nosotros 🙂

Artículo en base a información obtenida de Cryptography Engineering (B. Schneier). Demostración de martin.com.uy/sec.

16
Mar
2012

Autenticación de mensajes: CBC-MAC

Como mencionabamos en el artículo anterior (MAC: autenticación de mensajes), CBC-MAC es una implementación de MAC para autenticación de mensajes.

CBC-MAC

La idea detrás de esta implementación es transformar un algoritmo de cifrado con CBC (encadenamiento de bloques) en una función MAC. El tag MAC se obtiene al aplicar el algoritmo de cifrado con CBC al mensaje y tomar el último bloque -en ocasiones se utiliza la mitad del bloque-. Es importante que la clave utilizada en la obtención del MAC sea distinta a la clave utilizada para cifrar el mensaje. En caso contrario el MAC sería igual al último bloque del mensaje y podrían debilitarse tanto el cifrado como la autenticación.

Un ataque al CBC-MAC

Supongamos que un atacante, con suficiente tiempo, captura todos los mensajes de una comunicación y almacena su MAC en una base de datos con dos columnas: Mensaje – MAC. En determinado momento va a suceder que al almacenar una de esas tuplas mensaje-MAC, el valor de MAC ya se encuentra en la base de datos para un mensaje distinto. Esto es, en criptografía, una colisión. ¿Cuándo sucederá? Por la paradoja del cumpleaños, para un MAC de 128 bits ocurrirá en promedio al capturar 2^64 mensajes.


Leer el resto del artículo »

15
Mar
2012

MAC: autenticación de mensajes

La criptografía permite asegurar la confidencialidad de un mensaje pero no su integridad. Un atacante podría modificar (“tamperear”) un mensaje cifrado en medio de la comunicación y el receptor no tendría elementos para determinar si esto ocurrió.

Las técnicas de encadenamiento de bloques (block-chaining), utilizadas habitualmente en la criptografía, hacen que la tarea de modificar un mensaje no sea tan fácil. Si todos los bloques se encuentran encadenados y dependen de los anteriores, probablemente al realizar una modificación estemos introduciendo basura que no puede ser descifrada por el receptor. Sin embargo, en determinadas condiciones puede construirse un mensaje “válido” para el receptor a partir, por ejemplo, de mensajes cifrados -previamente interceptados- que guarden una estructura común.

MAC (Message Authentication Code) es una técnica destinada a autenticar mensajes y verificar, por lo tanto, su integridad. Dado un mensaje (m) y una clave (K), llamamos tag (T) al resultado de aplicarle al par mensaje-clave la función MAC. Para ser más claros: T = MAC(K, m).

Al enviar el mensaje al receptor adjuntamos T. El receptor, quien conoce previamente a K, realiza el mismo cálculo y comprueba de esa forma si el mensaje es auténtico. Un atacante que intercepte la comunicación no sabría, al modificar el mensaje, cómo generar un T válido.

Todo mensaje distinto tendrá un T distinto. Al igual que ocurre con las funciones de hash, el conjunto imagen (T) es finito y esto hace que la función no sea inyectiva. Si no fuera posible generar colisiones intencionadas, no se sabría qué bits agregar para hacer pasar un mensaje modificado por uno auténtico (dado un T conocido).

Según Bruce Schenier, en su libro Cryptography Engineering:

An ideal MAC function is a random mapping from all possible inputs to n-bits outputs.

En los próximos artículos veremos las implementaciones más comunes de MAC, como por ejemplo CBC-MAC, HMAC y GMAC.

13
Dec
2011

Mi propia implementación de SHA1

Quiero presentarles en este artículo mi propia implementación del algoritmo de hashing SHA1. Me basé en el estándar Secure Hash Standard (FIPS 180-1) de la Federal Information Processing Standards Publications (FIPS) (link).

El trabajo fue realizado con fines educativos únicamente. Desaconsejo su utilización en entornos de producción. Busqué además la claridad del código en lugar de la eficiencia en las operaciones y estructuras de datos.

Para el desarrollo utilicé el framework Qt y el lenguaje de programación C++. Si desean recompilar o ejecutar el binario, deberán instalar la SDK o las librerías de Qt respectivamente.

Los comandos de ejecución son los siguientes:

Calcular el hash a la cadena “abcdefg”
./Sha1 abcdefg

Calcular el hash a la cadena por defecto (“abc”)
./Sha1

Para calcular el hash a una cadena binaria arbitraria (no tiene por qué ser múltiplo de 8), se debe modificar el src -en el código hay comentarios para esto- y recompilar.


Leer el resto del artículo »

6
Dec
2011

Criptografía: IV + demo en OpenSSL

Como mencionamos en el artículo anterior, el IV o Initialization Vector es un vector de bits que permite aplicar una operación XOR con el primer bloque de largo fijo del mensaje a cifrar. De esta forma, si utilizamos como regla no repetir el IV entre distintos mensajes -para una misma clave-, por más que se repita el primer bloque a cifrar a nivel de plaintext, el ciphertext será diferente.

Propongo visualizar los conceptos explicados hasta el momento haciendo unas pruebas simples con OpenSSL.

Tenemos un archivo con el siguiente contenido:

root@martin-laptop:~/ciphers# cat archivo
plain text, este es un texto de pruebas que debe ocupar mas 128 bits
root@martin-laptop:~/ciphers# hexdump archivo
0000000 6c70 6961 206e 6574 7478 202c 7365 6574
0000010 6520 2073 6e75 7420 7865 6f74 6420 2065
0000020 7270 6575 6162 2073 7571 2065 6564 6562
0000030 6f20 7563 6170 2072 616d 2073 3231 2038
0000040 6962 7374 000a
0000045

Como podemos ver, el archivo contiene exactamente 70 bytes = 560 bits. Esto es igual a 4 bloques enteros de 128 bits (4 * 128 = 512 bits) + 48 bits más.


Leer el resto del artículo »

5
Dec
2011

Criptografía: Padding + ECB + CBC

Para el cifrado de un mensaje, se divide a nivel binario el mensaje en bloques de largo fijo. Este largo puede ser por ejemplo de 128 bits (4 bytes) y depende de cada algoritmo. Se llama block cipher al algoritmo que dado un bloque de largo fijo y una clave, lo transforma en un bloque cifrado (ciphertext).

Los mensajes que se desean cifrar no necesariamente cumplen con la propiedad de tener un largo múltiplo del largo fijo del bloque. Padding es una técnica que permite expandir el último bloque del mensaje hasta lograr el tamaño requerido. Esta operación debe poder ser revertida por el destinatario del mensaje. En otras palabras, el destinatario debe poder determinar con precisión en el último bloque cuántos bits corresponden al mensaje real y cuántos bits fueron agregados por la técnica de padding.

Existen múltiples técnicas de padding. Bruce Schenier, en su libro Cryptography Engineering, menciona dos:

  • Agregar al final del mensaje un byte con el valor 128 y luego agregar tantos 0’s como haga falta para alcanzar el largo del bloque de largo fijo.
  • Determinar el número de bytes que se requieren de padding. Supongamos que este número es n. Completar el mensaje con n bytes de valor n.

Cualquier técnica es válida mientras permita completar el mensaje hasta el largo requerido y el receptor pueda obtener con exactitud el mensaje original -sin bits extra y sin bits faltantes-.


Leer el resto del artículo »