CryptEncrypt 不加密整个文本
CryptEncrypt does not encrypt whole text
我正在尝试使用 wincrypt 加密短信。然而,我的代码是不可预测的。它不是 encrypt/decrypt 整个明文,而是其中的一部分。如果我更改密码长度(例如 "password123"),它会 encrypts/decrypts 不同数量的字符。这是我的代码。
#include <windows.h>
#include <wincrypt.h>
#include <stdio.h>
int main()
{
const char* passw = "password12";
const char* toencrypt = "consectetur adipiscing elit. In tellus nisl, sodales non arcu quis, sagittis maximus orci cras amet.";
HCRYPTPROV hProv;
HCRYPTHASH hHash;
HCRYPTKEY hKey;
DWORD todwSize = (DWORD)strlen(toencrypt);
PBYTE pBuffer;
CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_DELETEKEYSET);
CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET);
CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
CryptHashData(hHash, (BYTE*)passw, strlen(passw), 0);
CryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hKey);
//--------------------------------------------------------------------
CryptEncrypt(hKey, 0, TRUE, 0, NULL, &todwSize, todwSize);
pBuffer = (BYTE *)malloc(todwSize);
strcpy((char*)pBuffer, toencrypt);
CryptEncrypt(hKey, 0, TRUE, 0, pBuffer, &todwSize, todwSize);
PBYTE pBreturn = pBuffer;
const char* message = (const char*)pBreturn;
printf("%s", message);
//--------------------------------------------------------------------
DWORD dwSize = (DWORD)strlen(message);
PBYTE depBuffer;
depBuffer = (BYTE *)malloc(1460);
strcpy((char*)depBuffer, message);
CryptDecrypt(hKey, 0, TRUE, 0, depBuffer, &dwSize);
CryptDestroyKey(hKey);
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
if(GetLastError() != 0)
{
printf("%d", GetLastError());
}
PBYTE depBreturn = depBuffer;
printf("%s", (const char*)depBreturn);
printf("\n%d", strlen(message));
return 0;
}
在此先感谢您的帮助!
认为您的代码加密没问题,但无法解密整个消息,因为您在调用中使用了错误的长度CryptDecrypt
你的主要错误是 DWORD dwSize = (DWORD)strlen(message);
和 strcpy((char*)depBuffer, message);
但消息是加密缓冲区,而不是 0 终止 ansi 字符串。所以你不能在加密数据上使用 strlen
或 strcpy
- 你有 CryptEncrypt
返回的加密数据长度:todwSize
- 所以你必须使用 memcpy
如果您需要复制加密缓冲区并将 todwSize
原样传递给 CryptDecrypt
还注意到 Harry Johnston
你在调用 CryptEncrypt
中不正确地使用普通 data/buffer 大小。
必须是 CryptEncrypt(hKey, 0, TRUE, 0, NULL, &(needSize = todwSize), 0)
第一次调用(CryptEncrypt
dwBufLen 的最后一个参数必须是 0 因为你使用 NULL 作为缓冲区,并且需要使用另一个变量 DWORD needSize
来获取加密缓冲区的大小而不是覆盖纯文本缓冲区的大小 (todwSize
) 然后分配 needSize
缓冲区,复制到它 todSize
并调用 CryptEncrypt(hKey, 0, TRUE, 0, pBuffer, &todwSize, needSize)
。但是对于 RC4,加密文本和纯文本的大小始终相等。所以 needSize == todSize
始终以防 RC4
此外,在您的情况下,您只需要调用 CryptAcquireContext
一次并带有标志 CRYPT_VERIFYCONTEXT
。并且总是需要检查函数结果。所以测试代码可以像这样
int main()
{
const char* passw = "password12";
const char* toencrypt = "consectetur adipiscing elit. In tellus nisl, sodales non arcu quis, sagittis maximus orci cras amet.";
HCRYPTPROV hProv;
HCRYPTHASH hHash;
HCRYPTKEY hKey;
DWORD todwSize = (DWORD)strlen(toencrypt), needSize;
PBYTE pBuffer;
if (CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
if (CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
{
if (CryptHashData(hHash, (BYTE*)passw, (DWORD)strlen(passw), 0) &&
CryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hKey))
{
if (CryptEncrypt(hKey, 0, TRUE, 0, NULL, &(needSize = todwSize), 0))
{
memcpy(pBuffer = (BYTE *)_alloca(needSize), toencrypt, todwSize);
if (CryptEncrypt(hKey, 0, TRUE, 0, pBuffer, &todwSize, needSize))
{
if (CryptDecrypt(hKey, 0, TRUE, 0, pBuffer, &todwSize))
{
if (memcmp(pBuffer, toencrypt, strlen(toencrypt)))
{
__debugbreak();
}
}
}
}
CryptDestroyKey(hKey);
}
CryptDestroyHash(hHash);
}
CryptReleaseContext(hProv, 0);
}
return 0;
}
我正在尝试使用 wincrypt 加密短信。然而,我的代码是不可预测的。它不是 encrypt/decrypt 整个明文,而是其中的一部分。如果我更改密码长度(例如 "password123"),它会 encrypts/decrypts 不同数量的字符。这是我的代码。
#include <windows.h>
#include <wincrypt.h>
#include <stdio.h>
int main()
{
const char* passw = "password12";
const char* toencrypt = "consectetur adipiscing elit. In tellus nisl, sodales non arcu quis, sagittis maximus orci cras amet.";
HCRYPTPROV hProv;
HCRYPTHASH hHash;
HCRYPTKEY hKey;
DWORD todwSize = (DWORD)strlen(toencrypt);
PBYTE pBuffer;
CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_DELETEKEYSET);
CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET);
CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
CryptHashData(hHash, (BYTE*)passw, strlen(passw), 0);
CryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hKey);
//--------------------------------------------------------------------
CryptEncrypt(hKey, 0, TRUE, 0, NULL, &todwSize, todwSize);
pBuffer = (BYTE *)malloc(todwSize);
strcpy((char*)pBuffer, toencrypt);
CryptEncrypt(hKey, 0, TRUE, 0, pBuffer, &todwSize, todwSize);
PBYTE pBreturn = pBuffer;
const char* message = (const char*)pBreturn;
printf("%s", message);
//--------------------------------------------------------------------
DWORD dwSize = (DWORD)strlen(message);
PBYTE depBuffer;
depBuffer = (BYTE *)malloc(1460);
strcpy((char*)depBuffer, message);
CryptDecrypt(hKey, 0, TRUE, 0, depBuffer, &dwSize);
CryptDestroyKey(hKey);
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
if(GetLastError() != 0)
{
printf("%d", GetLastError());
}
PBYTE depBreturn = depBuffer;
printf("%s", (const char*)depBreturn);
printf("\n%d", strlen(message));
return 0;
}
在此先感谢您的帮助!
认为您的代码加密没问题,但无法解密整个消息,因为您在调用中使用了错误的长度CryptDecrypt
你的主要错误是 DWORD dwSize = (DWORD)strlen(message);
和 strcpy((char*)depBuffer, message);
但消息是加密缓冲区,而不是 0 终止 ansi 字符串。所以你不能在加密数据上使用 strlen
或 strcpy
- 你有 CryptEncrypt
返回的加密数据长度:todwSize
- 所以你必须使用 memcpy
如果您需要复制加密缓冲区并将 todwSize
原样传递给 CryptDecrypt
还注意到 Harry Johnston
你在调用 CryptEncrypt
中不正确地使用普通 data/buffer 大小。
必须是 CryptEncrypt(hKey, 0, TRUE, 0, NULL, &(needSize = todwSize), 0)
第一次调用(CryptEncrypt
dwBufLen 的最后一个参数必须是 0 因为你使用 NULL 作为缓冲区,并且需要使用另一个变量 DWORD needSize
来获取加密缓冲区的大小而不是覆盖纯文本缓冲区的大小 (todwSize
) 然后分配 needSize
缓冲区,复制到它 todSize
并调用 CryptEncrypt(hKey, 0, TRUE, 0, pBuffer, &todwSize, needSize)
。但是对于 RC4,加密文本和纯文本的大小始终相等。所以 needSize == todSize
始终以防 RC4
此外,在您的情况下,您只需要调用 CryptAcquireContext
一次并带有标志 CRYPT_VERIFYCONTEXT
。并且总是需要检查函数结果。所以测试代码可以像这样
int main()
{
const char* passw = "password12";
const char* toencrypt = "consectetur adipiscing elit. In tellus nisl, sodales non arcu quis, sagittis maximus orci cras amet.";
HCRYPTPROV hProv;
HCRYPTHASH hHash;
HCRYPTKEY hKey;
DWORD todwSize = (DWORD)strlen(toencrypt), needSize;
PBYTE pBuffer;
if (CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
if (CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
{
if (CryptHashData(hHash, (BYTE*)passw, (DWORD)strlen(passw), 0) &&
CryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hKey))
{
if (CryptEncrypt(hKey, 0, TRUE, 0, NULL, &(needSize = todwSize), 0))
{
memcpy(pBuffer = (BYTE *)_alloca(needSize), toencrypt, todwSize);
if (CryptEncrypt(hKey, 0, TRUE, 0, pBuffer, &todwSize, needSize))
{
if (CryptDecrypt(hKey, 0, TRUE, 0, pBuffer, &todwSize))
{
if (memcmp(pBuffer, toencrypt, strlen(toencrypt)))
{
__debugbreak();
}
}
}
}
CryptDestroyKey(hKey);
}
CryptDestroyHash(hHash);
}
CryptReleaseContext(hProv, 0);
}
return 0;
}