Criptografía en Python - AES

Junto con
Joan Daemen, Vincent Rijmen diseñó el algoritmo de cifrado
Rijndael, que fue seleccionado como AES en
2000
Índice

    ¿Qué es AES?

    AES (Advanced Encryption Standard, en inglés), también
    conocido como Rijndael (pronunciado "Rain Doll" en inglés), es un
    esquema de cifrado por bloques adoptado como un estándar de cifrado por el
    gobierno de los Estados Unidos, creado en Bélgica. Se transformó en un
    estándar efectivo el 26 de mayo de 2002. Desde 2006, el AES es uno de los
    algoritmos más populares usados en criptografía simétrica.
    El cifrado fue desarrollado por dos criptólogos belgas, Joan Daemen y
    Vincent Rijmen, y fue enviado al proceso de selección AES bajo el
    nombre "Rijndael", como parte de un concurso.

    AES y sus modos de cifrado

    AES no es un simple algoritmo que se le pasa un dato de entrada y te
    devuelve uno salida, él funciona con modos de operación los cuales son
    varios, pero aquí una pequeña lista de los muchos que podríamos usar:
    • Cipher-block chaining (CBC):
      En el modo cipher-block chaining (CBC), 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.

    • Counter (CTR): Al igual que OFB, el modo contador convierte una unidad de
      cifrado por bloques en una unidad de flujo de cifrado. Genera el
      siguiente bloque en el flujo de claves cifrando valores
      sucesivos de un contador. El contador puede ser cualquier
      función sencilla que produzca una secuencia de números donde los
      resultados se repiten con muy baja frecuencia. Si bien la
      operación más usada es un contador, el modo CTR tiene
      características similares al OFB, pero permite también usar una
      propiedad de acceso aleatorio para el descifrado.

    • Electronic Code-Book (ECB): El más sencillo es el modo electronic codebook (ECB), en el
      cual los mensajes se dividen en bloques y cada uno de ellos es
      cifrado por separado utilizando la misma clave K. La desventaja de
      este método es que a bloques de texto plano o claro idénticos les
      corresponden bloques idénticos de texto cifrado, de manera que se
      pueden reconocer estos patrones como guía para descubrir el texto en
      claro a partir del texto cifrado. De ahí que no sea recomendable
      para protocolos cifrados.
    • Galois/Counter Mode (GCM): En criptografía,
      Galois/Counter Mode (GCM) es un modo de operación
      para los cifrados de bloques criptográficos de clave simétrica
      ampliamente adoptados para su rendimiento.
      Las tasas de rendimiento de GCM para canales de comunicación de
      alta velocidad de última generación se pueden lograr con
      recursos de hardware económicos. 
      La operación es un
      algoritmo de cifrado autenticado diseñado para proporcionar
      autenticidad de datos (integridad) y confidencialidad.
      GCM se define para cifrados de bloques con un tamaño de bloque
      de 128 bits.
      Galois Message Authentication Code (GMAC) es una
      variante de autenticación solamente del GCM que puede formar un
      código de autenticación de mensajes incremental.
      Tanto GCM como GMAC pueden aceptar vectores de inicialización
      de longitud arbitraria.

    La lista puede seguir y seguir, pero lo importante es elegir uno que
    se acople mejor a la situación, que sea seguro y eficiente.

    AES en python

    Ya hemos visto lo que puede hacer la librería pycryptodome en
    el
    artículo anterior, pero no hemos explotado todo lo que nos ofrece, entre ello está
    la posibilidad de usar AES.
    En este tutorial crearemos dos funciones, una para cifrar y otra
    para descifrar usando el modo EAX.
    Primero importamos el módulo AES:
    from Crypto.Cipher import AES
    

    Ahora creamos la función para encriptar:
    def encrypt(key, data):
        cipher = AES.new(key, AES.MODE_EAX)
        ciphertext, tag = cipher.encrypt_and_digest(data)
    
        return cipher.nonce + tag + ciphertext
    Muy bien, una vez hemos creado la función para encriptar necesitamos
    comprender cada parámetro, variables y demás dato que nos sea de
    utilidad.
    Lo primero que hay que saber, es que key es la clave,
    contraseña, etc, con la que queramos cifrar los datos, mientras que
    data son los datos a cifrar. Cada uno de ellos debe ser de
    tipo bytes, aunque ya lo veremos detenidamente en una breves
    instantes.
    La variable ciphertext es la que hace referencia al resultado
    de los datos cifrados; tag es el código de autenticación de
    mensajes (MAC) calculado durante el cifrado. Y por último pero no
    menos importante el nonce (number occuring once [número que
    ocurre una vez, en español]), también conocido como el vector de
    inicialización, el cual es un número aleatorio que se utiliza para
    mejorar la aleatorización.
    Ahora creamos la función para desencriptar:
    def decrypt(key, data):
        nonce = data[:AES.block_size]
        tag = data[AES.block_size:AES.block_size * 2]
        ciphertext = data[AES.block_size * 2:]
    
        cipher = AES.new(key, AES.MODE_EAX, nonce)
        
        return cipher.decrypt_and_verify(ciphertext, tag)
    Lo primero que hay que saber, es que necesitamos calcular todo lo que el destinatario nos ha enviado. En el caso del nonce ímplicitamente estamos colocando un índice del 0-16 (la constante block_size del módulo AES vale 16), es recomendable usar la constante explícitamente en vez del número que conozcamos. Ya partiendo con el siguiente dato deseado, el tag, que ahora debe comenzar con un índice de 16-32 y por último, ciphertext con un índice de 32-[Hasta el último dato].

    De la teoría a la práctica

    Ya hemos presenciado lo más trivial de la usabilidad de AES en python gracias a la disposición de la librería pycryptodome, pero ahora pongamos en práctica lo que hemos creado con tanto esfuerzo. Llamaremos a todo lo que hemos escrito aes.py (o como deseamos), importemoslo y vamos a usarlo directamente, todo desde la consola de python:
    Cifrando y descifrando desde la consola de python
    El código de nuestro módulo para cifrar/descifrar datos usando AES

    Lecturas recomendadas:

    Todo lo que hemos y veremos son cosas sumamente básicas, son más introductorias que de enseñanza avanzada, realización hecha con esa metodología porque ayudará a las personas más noveles a adentrarse con el pie derecho en la criptografía, en la implemetación o por lo menos en la creación de aplicaciones seguras. La criptografía no es un juego, es muy fácil cometer errores que pueden costar caro, por lo que recomiendo leer más allá de lo que sea plantea en este diminuto artículo. En este caso les recomiendo las siguientes lecturas:
    • https://pycryptodome.readthedocs.io
    • https://pycryptodome.readthedocs.io/en/latest/src/examples.html#encrypt-data-with-aes
    • https://es.wikipedia.org/wiki/Cifrado_por_bloques
    • https://en.wikipedia.org/wiki/Initialization_vector
    • http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html
    ~ DtxdF

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

    Subir

    Te has suscrito correctamente al boletín

    Se produjo un error al intentar enviar tu solicitud. Inténtalo de nuevo.

    Mi Diario Python will use the information you provide on this form to be in touch with you and to provide updates and marketing.