c - 不要正确加密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 块大小?
解决方案
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");}
推荐阅读
- java - 错误:在顶级目录中找到 Main.class(模块中不允许使用未命名的包)
- c++ - C++ Winsock 发送向量可能吗?
- css - 卡片布局自定义帖子设计wordpress
- javascript - Javascript通过正则表达式拆分字符串以获取数字模式 - 仅在匹配前拆分
- java - 在android studio中对自定义对象的排序列表(API级别问题)
- excel - 从 Excel 单元格中删除所有 CSS
- algorithm - 哈密顿路径 - 当每个顶点只能被覆盖一次时,我可以两次覆盖边吗?
- asp.net-mvc - .NET Core 在中间件中捕获 Json 反序列化错误
- scala - WSL 上的 sbt 安装失败
- java - 堆删除和重建方法?(爪哇)