0

我需要从 OpenSSL 迁移到 MS CryptoAPI。

当我使用 OpenSSL 时,我得到了 N 字节(已经对齐 - 例如,假设数据长度 = 32 字节)的数据,并将其从一个缓冲区编码/解码到另一个缓冲区。一切正常。

现在我必须“使用 CryptoAPI!”。所以我写了类似的东西:

    // Import AES key
    if(!CryptImportKey(m_hProvider, (CONST BYTE*)&aeskey, structsize, NULL, 0, &m_hAesKey ) ) {
        throw WinAESException("SetKey: Import key failed");
    }

    // Set Mode
    DWORD dwMode = CRYPT_MODE_ECB; //I can also use CRYPT_MODE_CBC with set of IV but let simple the code;
    if(!CryptSetKeyParam(m_hAesKey, KP_MODE, (BYTE*)&dwMode, 0)) {
        throw WinAESException("SetKey: Set ECB mode failed");
    }

它工作正常,现在我尝试对数据进行编码

    DWORD d = (DWORD)psize;
    result = CryptEncrypt( m_hAesKey, NULL, TRUE, 0, buffer, &d, (DWORD)bsize );

而我看到了什么?数据的编码部分大于源。我知道 CryptEncrypt 函数以某种方式填充了已经填充的数据?

无论如何,是否有可能获得与普通数据相同大小的编码结果?

我不使用未对齐的块,我希望在加密 32 字节时得到正好 32 字节,而不是 48 ......

当我测试预期尺寸时

    DWORD d = 16;
    result = CryptEncrypt( m_hAesKey, NULL, TRUE, 0, 0, &d, (DWORD)bsize );  //need 32

    d = 32;
    result = CryptEncrypt( m_hAesKey, NULL, TRUE, 0, 0, &d, (DWORD)bsize );  //need 48 

    d = 48;
    result = CryptEncrypt( m_hAesKey, NULL, TRUE, 0, 0, &d, (DWORD)bsize );   //need 64

    d = 64;
    result = CryptEncrypt( m_hAesKey, NULL, TRUE, 0, 0, &d, (DWORD)bsize );  //need 80

WTHF 我做错了吗?PS如果我将加密结果截断为所需的大小,然后尝试解密它,则使用返回的预期错误代码完成解密,但数据解密正确。但这个黑客不适合我......

4

2 回答 2

0

首先,它不是编码和解码——它是加密和解密。

Microsoft 可能会默认添加 PKCS5_PADDING - 没有 NO_PADDING 这样的选项。这很奇怪,尤其是对于 ECB 模式,但它解释了为什么 CryptEncrypt 返回扩展缓冲区大小 - 它增加了一个填充块。

另一方面,您在上面的答案中使用 bFinal == FALSE 的“hack”实际上很好,因为 ECB 模式不需要任何最终确定过程。

如果您打算使用其他加密模式,那么您应该始终使用 bFinal == TRUE 进行加密。

此外,如果您想正确执行此操作,则应分两步进行加密:

DWORD dwEncryptedDataLen = dwRealDataLen; 
result = CryptEncrypt(m_hAesKey, NULL, TRUE, 0, NULL, &dwEncryptedDataLen, 0);
...
pbData = (BYTE*)malloc(dwEncryptedDataLen);
memcpy(pbData, pbRealData, dwRealDataLen);
...
result = CryptEncrypt(m_hAesKey, NULL, TRUE, 0, pbData, &dwRealDataLen, dwEncryptedDataLen);
...

不要忘记检查 Crypt 函数的结果值。

于 2019-11-21T12:35:57.413 回答
-1

看来我找到了临时解决方案。当我需要加密/解密整个块时 - 我需要的只是函数 - “它不是最后一个/唯一的块”:所以不要输入:

result = CryptEncrypt( m_hAesKey, NULL, TRUE, 0, buffer, &d, (DWORD)bsize );

但:

result = CryptEncrypt( m_hAesKey, NULL, FALSE, 0, buffer, &d, (DWORD)bsize );

现在它起作用了。并希望他们不要在最后一块的末尾改变填充数据的概念,以便在块的开头添加对齐...

于 2016-10-25T12:46:10.923 回答