如何正确使用来自 mbedtls 的 aes cbc api

Posted

技术标签:

【中文标题】如何正确使用来自 mbedtls 的 aes cbc api【英文标题】:How to properly use the aes cbc api from mbedtls 【发布时间】:2021-01-03 17:52:57 【问题描述】:

根据 golang 的 aes 实现检查,我当前的方法甚至无法生成正确的加密数据。它也不会解密回原始明文,但如果加密步骤无法正常工作,这是可以预期的。我最好的猜测是我以某种方式滥用了 api。这是一个独立的示例,可以按原样运行。

#include <mbedtls/aes.h>

#include <vector>

void LogVec(const std::vector<uint8_t>& bin)

    printf("(size: %i) ", bin.size());
    printf("");
    for (auto& b : bin)
    
        printf("%#02x, ", b);
    
    printf("\n");


mbedtls_aes_context AesContext;

std::vector<uint8_t> EncryptAes(std::vector<uint8_t>& iv, std::vector<uint8_t>& data)

    std::vector<uint8_t> ivCpy(iv);

    uint8_t padByte = 16 - (data.size() % 16);
    for (int i = 0; i < padByte; i++)
        data.push_back(padByte);

    std::vector<uint8_t> ret(data.size());
    mbedtls_aes_crypt_cbc(&AesContext, MBEDTLS_AES_ENCRYPT, data.size(), ivCpy.data(), data.data(), ret.data());

    return ret;


std::vector<uint8_t> DecryptAes(const std::vector<uint8_t>& iv, std::vector<uint8_t>& data)

    std::vector<uint8_t> ivCpy(iv);

    std::vector<uint8_t> ret(data.size());
    mbedtls_aes_crypt_cbc(&AesContext, MBEDTLS_AES_DECRYPT, data.size(), ivCpy.data(), data.data(), ret.data());

    ret.resize(ret.size() - ret[ret.size() - 1]);
    
    return ret;


int main() 

    mbedtls_aes_init(&AesContext);

    std::vector<uint8_t> data =  0x3b, 0xb1, 0x99, 0x3, 0x67, 0xf3, 0x2e, 0x1f, 0x00, 0x67, 0x38, 0xc9, 0x53, 0x92, 0xa4 ;

    std::vector<uint8_t> key =  0x15, 0x1, 0xc0, 0xd0, 0xe4, 0xfd, 0xdf, 0xd7, 0x7a, 0x65, 0xf1, 0x2f, 0x45, 0x61, 0xb, 
        0x59, 0xd9, 0xa, 0x9c, 0x61, 0xc, 0x4, 0x76, 0xdb, 0xb, 0xbe, 0x9e, 0xe4, 0x7f, 0x8d, 0xe1, 0x46 ;

    std::vector<uint8_t> iv =  0xa2, 0x78, 0xc9, 0xa4, 0xd8, 0x34, 0x88, 0x9b, 0x28, 0xdc, 0xb9, 0xe2, 0xc0, 0x58, 0x8c, 0xbc ;

    mbedtls_aes_setkey_enc(&AesContext, key.data(), 256);
    mbedtls_aes_setkey_dec(&AesContext, key.data(), 256);

    std::vector<uint8_t> dataEnc = EncryptAes(iv, data);
    printf("Encrypted data: ");
    LogVec(dataEnc);

    //std::vector<uint8_t> dataDec = DecryptAes(iv, dataEnc);
    //printf("Decrypted data: ");
    //LogVec(dataDec);

    getchar();
    return 1;

输出:

Encrypted data: (size: 16) 0x5d, 0x1c, 0x9, 0x2e, 0x92, 0x8e, 0x24, 0x43, 0xfa, 0xaf, 0xb3, 0xf5, 0x37, 0x8, 0x99, 0x93, 

在 golang 中使用相同键 iv 数据的预期输出:

Encrypted: 34730cba3543e5facf4b94ba9dc8a275

【问题讨论】:

【参考方案1】:

在调用mbedtls_aes_crypt_cbc 进行加密之前,您应该调用mbedtls_aes_setkey_enc,在调用mbedtls_aes_crypt_cbc 进行解密之前,您应该调用mbedtls_aes_setkey_dec。当两者都像在您的代码中那样在初始化时调用时,对 setkey_dec 的后一个调用将覆盖由加密所需的 setkey_enc 设置的上下文结构中的重要数据。

【讨论】:

以上是关于如何正确使用来自 mbedtls 的 aes cbc api的主要内容,如果未能解决你的问题,请参考以下文章

mbedtls 和 openssl 之间的不同 AES-256 加密输出

使用mbedtls的使用说明和AES加密方法(原来的PolarSSL)

基于MbedTLS的AES加密实现,含STM32H7和STM32F4的实现例程

STM32F4系列单片机上使用CUBE配置MBEDTLS实现pem格式公钥导入

如何使用 mbedtls 验证证书是不是验证密钥?

FreeRTOS+TCP 和 mbedTLS+TCP