Crypto

De Wikihaskell
Saltar a: navegación, buscar
Crypto
Crypto
Lenguaje Haskell
Biblioteca Crypto
Autores Ivan Bohorquez Barrios
Daniel Chaves Vázquez
Luis María Montero de Espinosa Díaz

Haskell nos permite codificar y decodificar utilizando diferentes tipos de encriptación:

  • DES
  • Blowfish
  • AES
  • TEA
  • SHA1
  • MD5
  • RSA

Crypto nos permite realizar estas tareas y para su mejor comprensión hemos creado esta wiki en la que se incluyen explicaciones de sus módulos, así como ejemplos de uso.

Contenido

Introducción

En el siguiente documento se realizará un estudio de la librería Criptográfica Crypto [1], desde su obtención e instalación, hasta la elaboración de algunos ejemplos que nos permitan comprobar su funcionalidad.

Descripción

La criptografía [2] actualmente se encarga del estudio de los algoritmos, protocolos y sistemas que se utilizan para dotar de seguridad a las comunicaciones, a la información y a las entidades que se comunican. El objetivo de la criptografía es diseñar, implementar, implantar, y hacer uso de sistemas criptográficos para dotar de alguna forma de seguridad. Por tanto el tipo de propiedades de las que se ocupa la criptografía son por ejemplo:

  • Confidencialidad.
  • Integridad.
  • No repudio.
  • Autenticación.

La biblioteca Crypto 4.2.5.1 agrupa existentes funciones criptográficas en un solo paquete, junto con pruebas HUnit [3], pruebas QuickCheck [4], propiedades y ejemplos.

Se trata de un cambio significativo con las versiones anteriores ya que ahora sólo contiene funciones criptográficas. Las funciones para trabajar con ASN.1 [5] y X.509 [6] estarán a cargo de una biblioteca totalmente independiente reduciendo así el número de dependencias.

Dependencias y requerimientos

Para el correcto funcionamiento de la biblioteca, antes de su instalación hemos de instalar las siguientes:

  • Base (en la versión 3 o superior)
  • HUnit
  • QuickCheck

Por otro lado, los autores comentan que la biblioteca ha sido probada usando GHC 6.6 [7] y Hugs [8] en su versión de septiembre de 2006.

Instalación

Instalación en Linux

Para poder instalar nuestra librería lo primero que tenemos que hacer es instalar cabal:

$  sudo apt-get install cabal-install

A continuación actualizamos la lista de paquetes:

$  cabal update

Por último usaremos cabal para instalar nuestra librería.

$  cabal install Crypto

Instalación en Windows

Para poder instalar nuestra librería, primero hemos de descargar cabal y Haskell Platform.

  1. Primero instalamos Haskell Platform.
  2. Acto seguido, abrimos una terminal y situamos la ruta en el mismo directorio en el que se encuentra el ejecutable cabal.exe.
  3. A continuación actualizamos la lista de paquetes:
$  cabal update
4. Por último usaremos cabal para instalar nuestra librería.
$  cabal install Crypto

Módulos

Módulo: Codec

Codec.Encryption.DES

Data Encryption Standard (DES)[9] fue creado en respuesta a una petición del Instituto Nacional de Normas y Tecnología (NIST) de un algoritmo de cifrado que cumpliera los requisitos:

  • Alto nivel de seguridad relacionado con una pequeña clave utilizada para cifrado y descifrado.
  • Comprensible.
  • Independencia de la confidencialidad del algoritmo.
  • Adaptable y económico.
  • Eficaz y exportable.

A finales de 1974 IBM propuso Lucifer siendo modificado posteriormente en 1976 para convertirse en DES.

Se trata de un sistema de cifrado simétrico por bloques de 64 bits, de los que 8 bits (un byte) se utilizan como control de paridad (para la verificación de la integridad de la clave). Cada uno de los bits de la clave de paridad (1 cada 8 bits) se utiliza para controlar uno de los bytes de la clave por paridad impar, es decir, que cada uno de los bits de paridad se ajusta para que tenga un número impar de "1" dentro del byte al que pertenece. Por lo tanto, la clave tiene una longitud "útil" de 56 bits, es decir, realmente sólo se utilizan 56 bits en el algoritmo.

Hoy en día, DES se considera inseguro para muchas aplicaciones. Esto se debe principalmente a que el tamaño de clave de 56 bits es corto; las claves de DES se han roto en menos de 24 horas. Se considera que el algoritmo es seguro su variante de Triple DES, aunque existan ataques teóricos.

 encrypt :: Word64 -> Word64 -> Word64 

Cifrado básico DES que recibe una clave y un bloque de texto claro y devuelve el bloque de texto cifrado, encriptado de acuerdo con el estándar.

 decrypt :: Word64 -> Word64 -> Word64 

Descifrado básico DES que recibe una clave y un bloque de texto cifrado y devuelve el bloque descifrado de texto claro, de acuerdo con el estándar.

Codec.Encryption.AES

Advanced Encryption Standard (AES)[10], también conocido como Rijndael, fue elegido en noviembre de 2001 por el Instituto Nacional de Normas y Tecnología (NIST), para ser el estándar en los próxmios 20 años. Rijndael fue elegido después de pasar un periodo de análisis durante aproximadamente 3 años, siendo la mejor opción de 15 candidatos, sus principales características fueron:

  • Fácil diseño.
  • Versatilidad en ser implementado en diferentes dispositivos.
  • Inmune a los ataques conocidos hasta la fecha.
  • Soporta bloques de datos de 128 bits y claves de 128, 192 y 256 bits.

La idea básica general es tener un estándar que mejore el TDES (Triple cifrado DES) y sea resistente a los ataques conocidos.

 encrypt :: AESKey a => a -> Word128 -> Word128 

Cifrado básico AES que recibe una clave y un bloque de texto claro y devuelve el bloque de texto cifrado, encriptado de acuerdo con el estándar.

 decrypt :: AESKey a => a -> Word128 -> Word128 

Descifrado básico AES que recibe una clave y un bloque de texto cifrado y devuelve el bloque descifrado de texto claro, de acuerdo con el estándar.

Codec.Encryption.Blowfish

En criptografía, Blowfish [11] es un codificador de bloques simétricos, diseñado por Bruce Schneier en 1993 e incluido en un gran número de conjuntos de codificadores y productos de cifrado.

Schneier diseñó Blowfish como un algoritmo de uso general, que intentaba reemplazar al antiguo DES y evitar los problemas asociados con otros algoritmos. Al mismo tiempo, muchos otros diseños eran propiedad privada, patentados o los guardaba el gobierno. Schneier declaró:

Blowfish no tiene patente, y así se quedará en los demás continentes. El algoritmo está a disposición del público, y puede ser usado libremente por cualquiera

Blowfish usa bloques de 64 bits y claves que van desde los 32 bits hasta 448 bits. Es un codificador de 16 rondas Feistel y usa llaves que dependen de las Cajas-S.

$  encrypt :: Integral a => a -> Word64 -> Word64

El cifrado básico de Blowfish tiene una clave y un bloque de texto claro y devuelve el bloque de texto cifrado encriptado de acuerdo con el estándar. Las claves típicas son word8, Word16, Word32, Word64, Word128.

$  decrypt :: Integral a => a -> Word64 -> Word64

El descifrado básico de Blowfish tiene una clave y un bloque de texto cifrado y devuelve el bloque descifrado de texto plano.

Codec.Encryption.Modes (CBC)

En el modo cipher-block chaining (CBC)[12], a cada bloque de texto plano se le aplica la operación XOR con el bloque cifrado anterior antes de ser cifrado. De esta forma, cada bloque de texto cifrado depende de todo el texto en claro procesado hasta este punto. Para hacer cada mensaje único se utiliza asimismo un vector de inicialización.

$  cbc :: Bits block => (key -> block -> block) -> block -> key -> [block] -> [block]
$  unCbc :: Bits block => (key -> block -> block) -> block -> key -> [block] -> [block]

Para descifrar en CBC, descifrar cada bloque, a continuación aplicar la operación XOR con el bloque anterior resultado de texto plano. Tenga en cuenta que el vector de inicialización es tratado como el bloque de orden cero de texto plano. Toma una función de descifrado, un vector de inicialización, una clave y una lista de bloques cifrados utilizando CBC y devuelve bloques de texto plano.

Codec.Encryption.Padding (PCKS#5)

PCKS#5 [13] establece un sistema de rellenado (padding en inglés) para cifrados por bloque que consiste en rellenar con tantos bytes como se necesiten y el valor de los bytes será el mismo que el número de los bytes introducidos. Por ejemplo si faltan 3 bytes entonces al final del texto en claro se rellena con 3 bytes de valor 03 (en binario 00000011). Para evitar posibles malinterpretaciones, si no hace falta rellenado se insertan tantos bytes como el tamaño del bloque con el valor el tamaño del bloque. Por definición este sistema sólo vale para cifrados con bloques de tamaño menor que 256 (valor máximo que puede tener un byte).

$  pkcs5 :: (Integral a, Bits a) => [Octet] -> [a]

Cuando el último bloque de texto plano es más corto que el tamaño de bloque, entonces debe ser relleno. PKCS#5 especifica que los octetos de relleno deben contener cada uno el número de octetos que deben sacarse. Así, por ejemplo, con un tamaño de bloque de 8 0a0b0c se rellena con 05, resultando en "0a0b0c0505050505". Si el último bloque es un bloque completo de 8 octetos entonces todo un bloque de 0808080808080808 se adjunta.

$  unPkcs5 :: (Bits a, Integral a) => [a] -> [Octet]

Recibe una lista con los bloques rellenos usando el método PKCS#5 y devuelve una lista de octetos sin rellenar. Nota: esta función no comprueba que el bloque de relleno es correcto y sólo debe utilizarse para bloques que han sido rellenados correctamente.

$  padNulls :: (Integral a, Bits a) => [Octet] -> [a]

Cuando el último bloque de texto plano es más corto que el tamaño de bloque, entonces debe ser rellenado. El relleno nulo especifica que los octetos de relleno deben contener cada uno un valor nulo. Así, por ejemplo, con un tamaño de bloque de 8 0a0b0c se rellenará a 0a0b0c0000000000. Si el último bloque es un bloque completo de 8 octetos entonces todo un bloque de 0000000000000000 se adjunta. Esto sólo es adecuado para los datos que no contienen valores nulos, por ejemplo, ASCII.

$  unPadNulls :: (Bits a, Integral a) => [a] -> [Octet]

Recibe una lista con bloques rellenados con ceros y devuelve una lista de octetos sin rellenar. Si los bloques contienen un valor nulo, el resultado es impredecible.

Codec.Encryption.RSA

La seguridad de este algoritmo radica en el problema de la factorización de números enteros. Los mensajes enviados se representan mediante números, y el funcionamiento se basa en el producto, conocido, de dos números primos grandes elegidos al azar y mantenidos en secreto. Actualmente estos primos son del orden de , y se prevé que su tamaño crezca con el aumento de la capacidad de cálculo de los ordenadores.

$  encrypt :: ([Octet], [Octet]) -> [Octet] -> [Octet]

Recibe el módulo de la clave RSA, la clave pública expresada en listas de octetos y el texto plano expresado en listas de octetos y develve el texto cifrado como una lista de octetos.

$  decrypt :: ([Octet], [Octet]) -> [Octet] -> [Octet]

Recibe el módulo de la clave RSA, la clave privada expresada en listas de octetos y el texto cofradoo expresado en listas de octetos y develve el texto plano como una lista de octetos.

Codec.Encryption.RSA.EMEOAEP

$  encode :: (([Octet] -> [Octet]) -> [Octet] -> Int -> [Octet]) -> ([Octet] -> [Octet]) -> [Octet] -> [Octet] -> [Octet] -> [Octet] -> [Octet]

Recibe una función de generación de máscara, una función hash, una etiqueta (que puede ser nula), una semilla aleatoria, el módulo de la clave y el mensaje, y devuelve el mensaje codificado. Otra opción para esta función era pasarle la longitud del modulo de la clave pero parece más seguro hacerlo pasandole el modulo en si y calcular la longitud caundo se requiera.[14]

$  decode :: (([Octet] -> [Octet]) -> [Octet] -> Int -> [Octet]) -> ([Octet] -> [Octet]) -> [Octet] -> [Octet] -> [Octet]

Recibe una función de generación de máscara, una función hash, una etiqueta (que puede ser nula) y el mensaje, y devuelve el mensaje decodificado.

Codec.Encryption.RSA.MGF

$  mgf :: ([Octet] -> [Octet]) -> [Octet] -> Int -> [Octet]

Recibe una función hash, una semilla y la longitud prevista de la máscara y devuelve una mascara de la longitud requerida.

Codec.Encryption.RSA.NumberTheory

La encriptación RSA que utiliza Teoría numérica[15] consta de las funciones mostradas a continuación.

$  inverse :: Integer -> Integer -> Integer
$  extEuclGcd :: Integer -> Integer -> (Integer, Integer)
$  simplePrimalityTest :: Integer -> Bool
$  getPrime :: Int -> IO Integer
$  pg :: Integer -> Integer -> Integer -> IO Integer
$  isPrime :: Integer -> IO Bool
$  rabinMillerPrimalityTest :: Integer -> IO Bool
$  expmod :: Integer -> Integer -> Integer -> Integer
$  factor :: Integer -> [Int]
$  testInverse :: Integer -> Integer -> Bool
$  primes :: [Integer]
$  (/|) :: Integer -> Integer -> Bool

Codec.Encryption.TEA

El algoritmo Tiny Encription Algorithm (TEA)[16] es uno de los algoritmos criptográficos simétricos más utilizados en la actualidad presentado en 1994, esto es debido a que posee las siguientes características:

  • Sencillez.
  • Robustez.
  • Facilidad de implementación.

Actualmente este algoritmo se emplea sobre todo en aparatos electrónicos que no dispongan de procesadores muy rápidos como teléfonos móviles, etc... y en programas informáticos que necesiten una alta velocidad de encriptación como servidores de IRC.

TEA opera sobre bloques de 64 bits y usa una clave de 128 bits. Posee una generación de claves extremadamente simple, mezclando todo el contenido de la clave de la misma manera para cada ciclo.

 encrypt :: TEAKey -> Word64 -> Word64 

Cifrado básico TEA que recibe una clave y un bloque de texto claro y devuelve el bloque de texto cifrado.

 decrypt :: TEAKey -> Word64 -> Word64 

Descifrado básico TEA que recibe una clave y un bloque de texto cifrado y devuelve el bloque descifrado de texto claro.

Módulo: Data

Data.Digest.MD5

MD5[17] es uno de los algoritmos de reducción criptográficos diseñados por el profesor Ronald Rivest del MIT (Massachusetts Institute of Technology, Instituto Tecnológico de Massachusetts). Fue desarrollado en 1991 como reemplazo del algoritmo MD4 después de que Hans Dobbertin descubriese su debilidad.

A pesar de su amplia difusión actual, la sucesión de problemas de seguridad detectados desde que, en 1996, Hans Dobbertin anunciase una colisión de hash, plantea una serie de dudas acerca de su uso futuro.

La codificación del MD5 de 128 bits es representada típicamente como un número de 32 dígitos hexadecimal.

 hash :: [Octet] -> [Octet] 

Toma un [Octet] y devuelve un [Octet] de acuerdo con el estándar. La longitud del resultado es siempre de 16 octetos o 128 bits, como es requerido por el estándar.

Data.Digest.SHA-#

La familia SHA[18] (Secure Hash Algorithm, Algoritmo de Hash Seguro) es un sistema de funciones hash criptográficas relacionadas de la Agencia de Seguridad Nacional de los Estados Unidos y publicadas por el National Institute of Standards and Technology (NIST). El primer miembro de la familia fue publicado en 1993 es oficialmente llamado SHA. Sin embargo, hoy día, no oficialmente se le llama SHA-0 para evitar confusiones con sus sucesores. Dos años más tarde el primer sucesor de SHA fue publicado con el nombre de SHA-1. Existen cuatro variantes más que se han publicado desde entonces cuyas diferencias se basan en un diseño algo modificado y rangos de salida incrementados: SHA-224, SHA-256, SHA-384, y SHA-512 (llamándose SHA-2 a todos ellos).

SHA-1

 hash :: [Word8] -> Word160 

SHA-2 (224, 256, 384, 512)

 hash :: [Octet] -> [Octet] 

Ejemplos de uso

Ejemplo de codificación Blowfish

Ejemplo con una clave de 8 bits

Importamos los ficheros necesarios para ejecutar la codificación:

$  import Codec.Encryption.Blowfish as Blowfish
$  import Data.Word

Definimos el bloque a codificar y la clave que utilizaremos, ambos en hexadecimal.

  • bloque: 18364758544493064720
  • clave: 240
$  bloque = 0xFEDCBA9876543210 :: Word64
$  clave = 0xF0 :: Word8

A continuación codificamos el bloque definido anteriormente

$  codificado = Blowfish.encrypt clave bloque

Cuya salida será: 17991134476764905566. Por último decodificamos el bloque para demostrar que se obtiene el mismo bloque que inicialmente

$  decodificado = Blowfish.decrypt clave codificado

Podemos comprobar que el resultado obtenido equivale al bloque inicial, por lo que el algoritmo funciona correctamente.

Ejemplo con una clave de 128 bits

Importamos los ficheros necesarios para ejecutar la codificación:

$  import Codec.Encryption.Blowfish as Blowfish
$  import Data.Word
$  import Data.LargeWord

Definimos el bloque a codificar y la clave que utilizaremos, ambos en hexadecimal.

  • bloque: 18364758544493064720
  • clave: 320187260592966088227705887823340838415
$  bloque = 0xFEDCBA9876543210 :: Word64
$  clave = 0xF0E1D2C3B4A5968778695A4B3C2D1E0F :: Word128

A continuación codificamos el bloque definido anteriormente

$  codificado = Blowfish.encrypt clave bloque

Cuya salida será: 10598140387392217436. Por último decodificamos el bloque para demostrar que se obtiene el mismo bloque que inicialmente

$  decodificado = Blowfish.decrypt clave codificado

Podemos comprobar que el resultado obtenido equivale al bloque inicial, por lo que el algoritmo funciona correctamente.

Enlaces externos

Referencias de la biblioteca Crypto:

Referencias de interés:


Referencias

  1. Sitio web http://hackage.haskell.org/package/Crypto
  2. Wiki Criptografía http://es.wikipedia.org/wiki/Criptografía
  3. HUnit http://hunit.sourceforge.net/
  4. QuickCheck http://es.wikipedia.org/wiki/QuickCheck/
  5. ASN.1 http://es.wikipedia.org/wiki/ASN.1
  6. X.509 http://es.wikipedia.org/wiki/X.509
  7. Descargar GHC http://www.haskell.org/ghc/
  8. Descargar Hugs http://www.haskell.org/hugs/
  9. DES http://es.wikipedia.org/wiki/Data_Encryption_Standard#Descripci.C3.B3n
  10. AES http://es.wikipedia.org/wiki/Advanced_Encryption_Standard
  11. Blowfish http://http://es.wikipedia.org/wiki/Blowfish
  12. CBC http://es.wikipedia.org/wiki/Modos_de_operaci%C3%B3n_de_una_unidad_de_cifrado_por_bloques#Modo_CBC_.28Cipher-block_chaining.29
  13. PCKS http://es.wikipedia.org/wiki/PKCS
  14. RSA.EMEOAEP ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf
  15. RSA.NumberTheory http://www.stanford.edu/class/cs103a/handouts/40%20Theorems,%20Examples,%20RSA.pdf
  16. TEA http://es.wikipedia.org/wiki/Tiny_Encryption_Algorithm
  17. MD5 http://es.wikipedia.org/wiki/MD5
  18. SHA http://es.wikipedia.org/wiki/SHA-1#SHA-1
Herramientas personales