【问题标题】:CryptEncrypt does not encrypt whole textCryptEncrypt 不加密整个文本
【发布时间】:2017-07-25 14:51:54
【问题描述】:

我正在尝试使用 wincrypt 加密文本消息。然而,我的代码是不可预测的。它不会加密/解密整个明文,而只是其中的一部分。如果我更改密码的长度(例如“password123”),它会加密/解密不同数量的字符。这是我的代码。

#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;
}

提前感谢您的帮助!

【问题讨论】:

  • CryptEncrypt 的第一次调用将todwSize 的值更改为加密数据的大小,但您随后将其作为明文的大小传递给第二次调用缓冲区的大小。这是两个不同的值,你需要两个不同的变量。
  • strlen(message);strcpy((char*)depBuffer, message); - message 中的主要错误不是 0 终止字符串,而是可以包含 0 个字节的二进制数据。你已经拥有了它todwSize
  • 当您使用带有 NULL 名称而不是私钥/公钥的 CryptAcquireContext 时 - 只需使用 CRYPT_VERIFYCONTEXT 并调用 `CryptAcquireContext 一次。当然,您不会检查任何功能结果,也不会释放资源
  • 是的,那是我的错误,谢谢大家!

标签: c++ windows encryption cryptography wincrypt


【解决方案1】:

认为您的代码加密正常,但未能解密整个消息,因为您在调用 CryptDecrypt 中使用了错误的长度

您的主要错误是 DWORD dwSize = (DWORD)strlen(message);strcpy((char*)depBuffer, message); 但消息是加密缓冲区,而不是 0 终止 ansi 字符串。所以你不能在加密数据上使用strlenstrcpy - 你有CryptEncrypt 返回的加密数据长度:todwSize - 所以你必须使用memcpy 如果你需要复制加密缓冲区并传递@ 987654329@ 与CryptDecrypt 一样

还注意到Harry Johnston 您在调用CryptEncrypt 中错误地使用了普通数据/缓冲区大小。

在第一次调用时必须是CryptEncrypt(hKey, 0, TRUE, 0, NULL, &amp;(needSize = todwSize), 0)CryptEncrypt 的最后一个参数 dwBufLen 必须为 0,因为您使用 NULL 作为缓冲区,并且需要使用另一个变量 @987654335 @ 获取加密缓冲区的大小而不覆盖纯文本缓冲区的大小 (todwSize) 然后分配 needSize 缓冲区,复制到它 todSize 并调用 CryptEncrypt(hKey, 0, TRUE, 0, pBuffer, &amp;todwSize, needSize)。但是对于 RC4,加密和纯文本大小始终相等。所以needSize == todSize 总是在 RC4 情况下

在你的情况下,你也只需要使用标志CRYPT_VERIFYCONTEXT 调用一次CryptAcquireContext。并且总是需要检查函数结果。所以测试代码可以是这样的

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;
}

【讨论】:

    猜你喜欢
    • 2018-03-15
    • 1970-01-01
    • 2012-02-23
    • 2021-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多