Как добавить IV (вектор инициализации) в шифрование AES-256 ECB для создания режима AES-256 CBC?
У меня есть следующий код, работающий для шифрования AES-256 ECB с использованием простой байт-ориентированной библиотеки AES-256, которую я нашел здесь.
Главный:
#define DUMP(s, i, buf, sz) {printf(s); \
for (i = 0; i < (sz);i++) \
printf("%02x ", buf[i]); \
printf("\n");}
int main (int argc, char *argv[])
{
aes256_context ctx;
uint8_t key[32] = "39P8TXDMBCYF4C1NI1CDFJ1WL6P5TTKZ";
uint8_t buf[16] = "KUC7EWG6M2D1WW8F";
uint8_t i;
DUMP("txt: ", i, buf, sizeof(buf));
DUMP("key: ", i, key, sizeof(key));
printf("---\n");
aes256_init(&ctx, key);
aes256_encrypt_ecb(&ctx, buf);
DUMP("enc: ", i, buf, sizeof(buf));
aes256_init(&ctx, key);
aes256_decrypt_ecb(&ctx, buf);
DUMP("dec: ", i, buf, sizeof(buf));
aes256_done(&ctx);
return 0;
}
Функция шифрования:
void aes256_encrypt_ecb(aes256_context *ctx, uint8_t *buf)
{
uint8_t i, rcon;
aes_addRoundKey_cpy(buf, ctx->enckey, ctx->key);
for(i = 1, rcon = 1; i < 14; ++i)
{
aes_subBytes(buf);
aes_shiftRows(buf);
aes_mixColumns(buf);
if( i & 1 ) aes_addRoundKey( buf, &ctx->key[16]);
else aes_expandEncKey(ctx->key, &rcon), aes_addRoundKey(buf, ctx->key);
}
aes_subBytes(buf);
aes_shiftRows(buf);
aes_expandEncKey(ctx->key, &rcon);
aes_addRoundKey(buf, ctx->key);
} /* aes256_encrypt */
Я хочу добавить IV к этой программе, чтобы создать режим AES-256 CBC. Из того, что я понимаю, IV реализация выглядит следующим образом:
- XOR первый блок с IV.
- XOR все последующие блоки с зашифрованным текстом предыдущего блока.
Мой вопрос в том, как выглядит логика? Как я могу реализовать это в моем коде?
1 ответ
Логика и объяснения можно найти в нескольких местах. Например, в режиме ECB против CBC или блочного шифра.
CBC = Cipher Block Chaining - это способ соединения блоков вместе.
Вместо того чтобы обрабатывать каждый блок отдельно, каждый блок будет XOR'ом с зашифрованным предыдущим блоком. Это фактически означает, что каждый блок зависит от вывода предыдущего блока.
Каждый блок XORed с зашифрованным текстом предыдущего блока, как это объясняется диаграммами в цитируемых статьях.
На практике один блок зашифровывается с помощью надписи ECB:
Cipher((state_t*)buf, ctx->RoundKey);
как в
void AES_ECB_encrypt(struct AES_ctx *ctx,const uint8_t* buf)
{
// The next function call encrypts the PlainText with the Key using AES algorithm.
Cipher((state_t*)buf, ctx->RoundKey);
}
CBC достигается с помощью XOR с IV на блоке, ECB на том же блоке и перемещением вдоль блоков в буфере.
Пример XOR с IV:
static void XorWithIv(uint8_t* buf, 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];
}
}
Пример CBC с использованием XOR с IV и ECB:
void AES_CBC_encrypt_buffer(struct AES_ctx *ctx,uint8_t* buf, uint32_t length)
{
uintptr_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;
//printf("Step %d - %d", i/16, i);
}
/* store Iv in ctx for next call */
memcpy(ctx->Iv, Iv, AES_BLOCKLEN);
}
Вышеуказанная реализация взята из крошечного AES, и вы можете изучить его и адаптировать к вашим потребностям. Я надеюсь, что это помогает.