首页 > 解决方案 > 不要正确加密wincrypt

问题描述

我正在尝试使用 AES128 将字符串加密为 8 字节(64 位)的大小wincrypt.h请注意该字符串小于 128 位的 AES 块大小。

HCRYPTKEY hKey;
if (!CryptDeriveKey(hProv, CALG_AES_128, hHash, 0, &hKey)) {
    dwStatus = GetLastError();
    printf("CryptDeriveKey failed: %x\n", dwStatus);
    CryptReleaseContext(hProv, 0);
    system("pause");
    return dwStatus;
}

printf("[+] CryptDeriveKey Success\n");

const size_t string_size = 8;
BYTE string[8] = { "Foooooo" };   // \0 counts as 1 byte
DWORD out_len = 8;


if (!CryptEncrypt(hKey, NULL, TRUE, 0, string, &out_len, string_size)) {
        printf("[-] CryptEncrypt failed\n");
}

printf("%s", string);
printf("\n");

if (!CryptDecrypt(hKey, NULL, TRUE, 0, string, &out_len)) {
    printf("[-] CryptDecrypt failed\n");

}

printf("%s", string);
printf("\n");

但它看起来不能很好地加密/解密,因为我得到了这个输出:

[+] CryptDeriveKey Success
Fooooooo
[-] CryptEncrypt failed
ÉÆ╠1╔P█ídhù;$§┴
[-] CryptDecrypt failed

我做错了什么?&out_len或者string_size应该是 128 作为 AES 块大小?

标签: cencryptionaeswincrypt

解决方案


CryptEncrypt的文档表明输入/输出长度以字节为单位,因此对于 AES* 这应该是 16 的倍数

我认为这也是您问题的关键:CryptEncrypt 就地运行——也就是说,它用输出密文覆盖输入明文。您的缓冲区太小而无法接收 16 字节的输出,因此最后 8 字节很可能在您的 Encrypt 和 Decrypt 操作之间被损坏。

尝试碰撞

BYTE string[8] = { "Foooooo" }; const size_t string_size = 8;

BYTE string[16] = { "Foooooo" }; const size_t string_size = 16;

另外,请阅读 PKCS7 填充,这可能是 wincrypt 确定您的密文错误的方式。

*除了密文窃取模式或流模式。这些模式在解密时不会“失败”,因此 wincrypt 没有使用其中一种。


与您的问题无关,但通过打印密文printf也不是一个好主意。通过以十六进制打印密文,您将获得更好的理解:

{DWORD i; for(DWORD i=0; i < out_len; i++) printf("%02x ", string[i]); printf("\n");}


推荐阅读