Comprensión de la implementación del código AES_CBC

Directorio de artículos

1. AES y CBC

AES significa Estándar de cifrado avanzado y es un algoritmo de cifrado de clave simétrica que se utiliza para cifrar y descifrar datos electrónicos. Los ejemplos de este blog utilizan claves de 128 bits para cifrar y descifrar datos.

El modo CBC es un modo de cifrado de cifrado de bloque comúnmente utilizado en algoritmos de cifrado simétrico. El diagrama de estructura específico de CBC es el siguiente:
Insertar descripción de la imagen aquí
cuando escribimos un algoritmo y necesitamos implementar este proceso, ¿cómo debemos hacerlo? Al consultar los dos enlaces siguientes, podemos adquirir algo de experiencia.
https://github.com/kokke/tiny-AES-c/blob/master/aes.c
https://github.com/kokke/tiny-AES-c/blob/master/test.c

2. aes.c

En aes.c, el algoritmo AES correspondiente se implementa utilizando una variedad de modos de cifrado de bloques diferentes. Aquí nos centramos en la implementación del CBC.

El primero es AES_CBC_encrypt_bufferel método.

void AES_CBC_encrypt_buffer(struct AES_ctx *ctx, uint8_t* buf, size_t length)
{
    
    
  size_t i;
  uint8_t *Iv = ctx->Iv;
  for (i = 0; i < length; i += AES_BLOCKLEN)
  {
    
    
    XorWithIv(buf, Iv);
    Cipher((state_t*)buf, ctx->RoundKey);
    Iv = buf;
    buf += AES_BLOCKLEN;
  }
  /* store Iv in ctx for next call */
  memcpy(ctx->Iv, Iv, AES_BLOCKLEN);
}

Este código es una implementación de función que utiliza el modo CBC del algoritmo AES para el cifrado.

El nombre de la función AES_CBC_encrypt_bufferacepta tres parámetros: ctxun puntero al contexto AES, bufel búfer de datos que se cifrará lengthy la longitud de los datos que se cifrarán.

La lógica principal de la función es la siguiente:

  1. Inicialice un puntero Ivque apunte al vector de inicialización en el contexto ctx.
  2. Utilice un bucle para iterar a través bufde los datos en el búfer de datos, procesando una longitud de bloque AES (AES_BLOCKLEN) de datos a la vez.
  3. En cada iteración, primero se aplica XOR al búfer de datos bufcon el vector de inicialización , que es una de las características del modo CBC que puede aumentar la seguridad del cifrado.Iv
  4. Tome el búfer de datos XOR como entrada y cifrelo bufusando la función de cifrado del algoritmo AES ( ), usando la clave redonda en el contexto ( ).CipherctxRoundKey
  5. Utilice el búfer de datos cifrados actual bufcomo vector de inicialización para la siguiente iteración.
  6. Actualice el puntero del búfer de datos bufpara que apunte al siguiente bloque AES.
  7. Repita hasta que se hayan procesado todos los datos.
  8. Finalmente, el último bloque de datos cifrados se utiliza como vector de inicialización la próxima vez que se llama a la función y se almacena en el ctxvector de inicialización ( Iv) en el contexto.

Los métodos correspondientes XorWithIvson los siguientes.

static void XorWithIv(uint8_t* buf, const uint8_t* Iv)
{
    
    
  uint8_t i;
  for (i = 0; i < AES_BLOCKLEN; ++i) // The block in AES is always 128bit no matter the key size
  {
    
    
    buf[i] ^= Iv[i];
  }
}

buf[i] ^ Iv[i]Se puede ver que cada vez que se llama a este método, la posición correspondiente de buf será reemplazada AES_BLOCKLENpor texto cifrado.

3. prueba.c

En el programa de prueba podemos ver que está definido el vector de inicialización Iv, la clave correspondiente a AES con diferentes dígitos, así como el texto plano a cifrar y el resultado de salida esperado.

static int test_encrypt_cbc(void)
{
    
    
#if defined(AES256)
    uint8_t key[] = {
    
     0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
                      0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 };
    uint8_t out[] = {
    
     0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6,
                      0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d, 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d,
                      0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf, 0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61,
                      0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc, 0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b };
#elif defined(AES192)
    uint8_t key[] = {
    
     0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b };
    uint8_t out[] = {
    
     0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d, 0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8,
                      0xb4, 0xd9, 0xad, 0xa9, 0xad, 0x7d, 0xed, 0xf4, 0xe5, 0xe7, 0x38, 0x76, 0x3f, 0x69, 0x14, 0x5a,
                      0x57, 0x1b, 0x24, 0x20, 0x12, 0xfb, 0x7a, 0xe0, 0x7f, 0xa9, 0xba, 0xac, 0x3d, 0xf1, 0x02, 0xe0,
                      0x08, 0xb0, 0xe2, 0x79, 0x88, 0x59, 0x88, 0x81, 0xd9, 0x20, 0xa9, 0xe6, 0x4f, 0x56, 0x15, 0xcd };
#elif defined(AES128)
    uint8_t key[] = {
    
     0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c };
    uint8_t out[] = {
    
     0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d,
                      0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2,
                      0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16,
                      0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7 };
#endif
    uint8_t iv[]  = {
    
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
    uint8_t in[]  = {
    
     0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
                      0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
                      0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
                      0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 };
    struct AES_ctx ctx;

    AES_init_ctx_iv(&ctx, key, iv);
    AES_CBC_encrypt_buffer(&ctx, in, 64);

    printf("CBC encrypt: ");

    if (0 == memcmp((char*) out, (char*) in, 64)) {
    
    
        printf("SUCCESS!\n");
	return(0);
    } else {
    
    
        printf("FAILURE!\n");
	return(1);
    }
}

Al final de este método, se utiliza el método memcmp para comparar la entrada y la salida para determinar si AES_CBC se ejecuta correctamente y ha logrado la función de verificación.

Supongo que te gusta

Origin blog.csdn.net/weixin_46841376/article/details/132163247
Recomendado
Clasificación