【问题标题】:Is it possibile to find out the length of original data from a AES-CBC cphertext?是否可以从 AES-CBC cphertext 中找出原始数据的长度?
【发布时间】:2015-03-09 21:54:23
【问题描述】:

我正在使用 VC++/OPENSSL 和 AES-256-CBC,我注意到由于 AES 是 OPENSSL 自动填充的,当我尝试解密时,我得到的数据是填充字节。不仅仅是原始数据。

是否有办法在解密时获取原始数据的长度,以便我可以削减填充字节?

这是我的代码

void Cryptology::OpenSSLAESDecodeByMapleArray(MapleByteArray& source, MapleByteArray& ba,MapleByteArray &res,bool nosalt)
{
    EVP_CIPHER_CTX de;

    unsigned int salt[] = { 56756, 352466 };

    int i, nrounds = 7;
    unsigned char key[32] = { 0 }, iv[32] = { 0 };
    if (nosalt)
    {
        i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), NULL, ba.data_ptr(), ba.GetLength(), nrounds, key, iv);
    }
    else
    {
        i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), (unsigned char *)salt, ba.data_ptr(), ba.GetLength(), nrounds, key, iv);
    }

    if (i != 32) {
        exit(0);
    }

    EVP_CIPHER_CTX_init(&de);
    EVP_DecryptInit_ex(&de, EVP_aes_256_cbc(), NULL, key, iv);


    int p_len = source.GetLength(), f_len = 0;
    unsigned char *plaintext = (unsigned char *)malloc(p_len + AES_BLOCK_SIZE);
    ZeroMemory(plaintext, p_len + AES_BLOCK_SIZE);

    EVP_DecryptInit_ex(&de, NULL, NULL, NULL, NULL);
    EVP_DecryptUpdate(&de, plaintext, &p_len, (unsigned char *)source.data_ptr(), source.GetLength());
    EVP_DecryptFinal_ex(&de, plaintext + p_len, &f_len);

    int len = p_len + f_len;


    //qDebug() << QString::number(len);

    EVP_CIPHER_CTX_cleanup(&de);


    res.fromByte((BYTE*)plaintext, p_len + AES_BLOCK_SIZE);

    ZeroMemory(plaintext, p_len + AES_BLOCK_SIZE);
    free(plaintext);
    ZeroMemory(key, 32);
    ZeroMemory(iv, 32);
    return;
}

【问题讨论】:

  • 填充通常遵循一个约定(只是暂时不记得了),例如ddddddppppb。其中d 是数据字节,p 是填充字节,b 是填充字节数。
  • 我看到了理查德。但是有没有让 OPENSSL 自动进行填充和取消填充?我懒得写代码了:P
  • 最好用数据编码数据大小,不要依赖填充和一些自动数据大小扣除。如果编码数据被截断,您希望能够检测到这一点。这就是为什么您在数据前面编码数据大小并检查数据是否被截断的原因。然后,删除填充或可能在加密消息之后添加的任何垃圾都是微不足道的。您的代码将更加健壮。
  • 快速阅读文档说 OpenSSL 使用 PKCS#7 填充,因此请在 OpenSSL 中找到 API 来添加/删除填充。
  • @chmike 如果您希望您的加密方案基于标准,则必须使用填充标准。例如,参见 PKCS#7 填充。

标签: c++ encryption aes


【解决方案1】:

如果启用了填充 - 那么EVP_DecryptFinal(..) 将验证填充但不会在结果中返回它。那些解密的数据会比加密的数据略短。

每次调用EVP_CipherUpdate(..)EVP_CipherFinal_ex(..) 时,都会在outl 变量中返回解密数据的实际长度

    int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
                         int *outl, unsigned char *in, int inl);
    int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm,
                          int *outl);

在您的代码中,len 的值恰好是您解密数据的长度。

【讨论】:

    猜你喜欢
    • 2011-07-03
    • 2022-01-02
    • 2017-11-21
    • 2020-02-02
    • 1970-01-01
    • 2014-04-10
    • 2021-05-11
    • 2017-01-15
    • 2017-05-23
    相关资源
    最近更新 更多