gpt4 book ai didi

c - WinAPI - CryptDecrypt() 在 AES 256 中无法正常工作

转载 作者:行者123 更新时间:2023-12-03 20:29:48 33 4
gpt4 key购买 nike

我曾经与 crypto++ 一起工作以前在 Visual Studio 中,但现在我想使用 wincrypt.h使用 加密字符串的 API 函数AES 256 带有 (cbc 模式)。

我做了以下步骤,但我对 CryptEncrypt() 感到困惑和 CryptDecrypt()功能,因为它们似乎无法正常工作:

  • CryptAcquireContextA定义为创建 CSP :
    // create a cryptographic service provider (CSP)
    CryptAcquireContextA(&hProv, NULL, MS_ENH_RSA_AES_PROV_A, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)
  • 对于设置键,我使用这种方式(导入键):
    CryptImportKey(hProv, (BYTE*)&AESBlob, sizeof(AES256KEYBLOB), NULL, CRYPT_EXPORTABLE, &hKey)
  • IV、 key 、明文大小分别为:
    #define     DEFAULT_AES_KEY_SIZE    32
    #define DEFAULT_IV_SIZE 16
    #define BUFFER_FOR_PLAINTEXT 32

  • 这是我的全部 code :
    // handles for csp and key
    HCRYPTPROV hProv = NULL;
    HCRYPTPROV hKey = NULL;
    BYTE szKey[DEFAULT_AES_KEY_SIZE + 1] = {0};
    BYTE szIV[DEFAULT_IV_SIZE + 1] = {0};
    // plain bytes
    BYTE szPlainText[BUFFER_FOR_PLAINTEXT + 1] = {0};
    DWORD dwPlainSize = 0;

    // initalize key and plaintext
    StrCpyA((LPSTR)szKey, "00112233445566778899001122334455");
    StrCpyA((LPSTR)szIV, "4455667788990011");
    StrCpyA((LPSTR)szPlainText, "abcdefghijklmnopqrstuvwxyzabcdef");

    // blob data for CryptImportKey() function (include key and version and so on...)
    struct AES256KEYBLOB
    {
    AES256KEYBLOB() { StrCpyA((LPSTR)szBytes, 0); }
    BLOBHEADER bhHdr;
    DWORD dwKeySize;
    BYTE szBytes[DEFAULT_AES_KEY_SIZE + 1];
    } AESBlob;

    AESBlob.bhHdr.bType = PLAINTEXTKEYBLOB;
    AESBlob.bhHdr.bVersion = CUR_BLOB_VERSION;
    AESBlob.bhHdr.reserved = 0;
    AESBlob.bhHdr.aiKeyAlg = CALG_AES_256;
    AESBlob.dwKeySize = DEFAULT_AES_KEY_SIZE;
    StrCpyA((LPSTR)AESBlob.szBytes, (LPCSTR)szKey);

    // create a cryptographic service provider (CSP)
    if(CryptAcquireContextA(&hProv, NULL, MS_ENH_RSA_AES_PROV_A, PROV_RSA_AES, CRYPT_VERIFYCONTEXT))
    {
    if(CryptImportKey(hProv, (BYTE*)&AESBlob, sizeof(AES256KEYBLOB), NULL, CRYPT_EXPORTABLE, &hKey))
    {
    if(CryptSetKeyParam(hKey, KP_IV, szIV, 0))
    {
    if(CryptEncrypt(hKey, NULL, TRUE, 0, szPlainText, &dwPlainSize, lstrlenA((LPCSTR)szPlainText) + 1))
    {
    printf("\nEncrypted data : %s\nSize : %d\n", (LPCSTR)szPlainText, dwPlainSize);

    if(CryptDecrypt(hKey, NULL, TRUE, 0, szPlainText, &dwPlainSize)) {
    printf("\nDecrypted data : %s\nSize : %d\n", (LPCSTR)szPlainText, dwPlainSize);
    }
    else
    printf("failed to decrypt!");
    }
    else
    printf("failed to encrypt");
    }
    }
    }

    它只是加密了一半的明文 而解密没有完成!甚至只需改变 szPlainText值,它总是给我波纹管输出(这意味着 CryptEncrypt()CryptDecrypt() 没有按预期工作!):
    Encrypted data : U╡π7ÑL|FΩ$}├rUqrstuvwxyzabcdef
    Size : 16

    Decrypted data : U╡π7ÑL|FΩ$}├rUqrstuvwxyzabcdef
    Size : 0

    最佳答案

    这是我从 VStudio 2015 运行的一个变体。

    代码.c:

    #include <windows.h>
    #include <wincrypt.h>
    #include <stdio.h>
    #include <Shlwapi.h>

    #define DEFAULT_AES_KEY_SIZE 32
    #define DEFAULT_IV_SIZE 16
    #define BUFFER_FOR_PLAINTEXT 32

    #define CLEANUP_CRYPT_STUFF(PROV, KEY) \
    CryptDestroyKey(KEY); \
    CryptReleaseContext(PROV, 0)

    #define PRINT_FUNC_ERR_AND_RETURN(FUNC) \
    printf("%s (line %d) failed: %d\n", ##FUNC, __LINE__, GetLastError()); \
    return -1


    typedef struct AES256KEYBLOB_ {
    BLOBHEADER bhHdr;
    DWORD dwKeySize;
    BYTE szBytes[DEFAULT_AES_KEY_SIZE + 1];
    } AES256KEYBLOB;


    int main() {
    // handles for csp and key
    HCRYPTPROV hProv = NULL;
    HCRYPTKEY hKey = NULL;
    BYTE szKey[DEFAULT_AES_KEY_SIZE + 1] = { 0 };
    BYTE szIV[DEFAULT_IV_SIZE + 1] = { 0 };
    // plain bytes
    BYTE szPlainText[BUFFER_FOR_PLAINTEXT + 1] = { 0 }, *pBuf = NULL;
    AES256KEYBLOB AESBlob;
    memset(&AESBlob, 0, sizeof(AESBlob));

    // initalize key and plaintext
    StrCpyA((LPSTR)szKey, "00112233445566778899001122334455");
    StrCpyA((LPSTR)szIV, "4455667788990011");
    StrCpyA((LPSTR)szPlainText, "abcdefghijklmnopqrstuvwxyzabcdef");
    DWORD dwPlainSize = lstrlenA((LPCSTR)szPlainText), dwBufSize = dwPlainSize, dwBufSize2 = dwPlainSize;

    // blob data for CryptImportKey() function (include key and version and so on...)
    AESBlob.bhHdr.bType = PLAINTEXTKEYBLOB;
    AESBlob.bhHdr.bVersion = CUR_BLOB_VERSION;
    AESBlob.bhHdr.reserved = 0;
    AESBlob.bhHdr.aiKeyAlg = CALG_AES_256;
    AESBlob.dwKeySize = DEFAULT_AES_KEY_SIZE;
    StrCpyA((LPSTR)AESBlob.szBytes, (LPCSTR)szKey);

    // create a cryptographic service provider (CSP)
    if (!CryptAcquireContextA(&hProv, NULL, MS_ENH_RSA_AES_PROV_A, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
    PRINT_FUNC_ERR_AND_RETURN(CryptAcquireContextA);
    }
    if (!CryptImportKey(hProv, (BYTE*)&AESBlob, sizeof(AES256KEYBLOB), NULL, CRYPT_EXPORTABLE, &hKey)) {
    CryptReleaseContext(hProv, 0);
    PRINT_FUNC_ERR_AND_RETURN(CryptImportKey);
    }
    if (!CryptSetKeyParam(hKey, KP_IV, szIV, 0)) {
    CLEANUP_CRYPT_STUFF(hProv, hKey);
    PRINT_FUNC_ERR_AND_RETURN(CryptSetKeyParam);
    }
    if (CryptEncrypt(hKey, NULL, TRUE, 0, NULL, &dwBufSize, 0)) {
    printf("%d bytes required to hold the encrypted buf\n", dwBufSize);
    if ((pBuf = calloc(dwBufSize, sizeof(BYTE))) == NULL)
    {
    CLEANUP_CRYPT_STUFF(hProv, hKey);
    PRINT_FUNC_ERR_AND_RETURN(calloc);
    }
    StrCpyA(pBuf, szPlainText);
    } else {
    CLEANUP_CRYPT_STUFF(hProv, hKey);
    PRINT_FUNC_ERR_AND_RETURN(CryptEncrypt);
    }
    if (CryptEncrypt(hKey, NULL, TRUE, 0, pBuf, &dwBufSize2, dwBufSize)) {
    printf("\nEncrypted data: [%s]\nSize: %d\n", (LPCSTR)pBuf, dwBufSize2);
    if (CryptDecrypt(hKey, NULL, TRUE, 0, pBuf, &dwBufSize)) {
    printf("\nDecrypted data: [%s]\nSize: %d\n", (LPCSTR)pBuf, dwBufSize);
    } else {
    free(pBuf);
    CLEANUP_CRYPT_STUFF(hProv, hKey);
    PRINT_FUNC_ERR_AND_RETURN(CryptDecrypt);
    }
    } else {
    free(pBuf);
    CLEANUP_CRYPT_STUFF(hProv, hKey);
    PRINT_FUNC_ERR_AND_RETURN(CryptEncrypt);
    }
    free(pBuf);
    CLEANUP_CRYPT_STUFF(hProv, hKey);
    return 0;
    }

    备注 :
  • 删除了 AES256KEYBLOB 构造函数,因为我遇到了访问冲突(这在使用“不是你的”内存时很正常)。用 memset 调用替换了结构初始化
  • (逻辑)错误是缓冲区不够大,无法存储加密文本(与 dwPlainSize 的错误值( 0 )相结合 - 使函数误导性地成功)。根据 [MS.Docs]: CryptEncrypt function :

    If this parameter contains NULL, this function will calculate the required size for the ciphertext and place that in the value pointed to by the pdwDataLen parameter.



    要找出所需的大小,请额外调用该函数,将 pbData 设置为 NULL(在其他 WinAPI 中也遇到这种做法)。然后分配一个缓冲区,用所需的数据填充它,并使“main”调用该缓冲区上的函数...
  • 添加了缺少的 #includes 和 main
  • 添加代码以在不再需要时释放已用资源
  • 重构:
  • 否定 if 条件,因为我不喜欢这么多嵌套级别
  • 添加了一些方便的宏(CLEANUP_CRYPT_STUFF、PRINT_FUNC_ERR_AND_RETURN),以避免代码重复
  • 其他小修复/改进
  • 您可能想要添加一个精确打印 的函数。电话 来自缓冲区的字节,如“ %s ”说明符仅在遇到“\0 ”时停止,并且只有(愚蠢的)运气阻止了控制台被垃圾填满(甚至程序崩溃)打印缓冲区时
  • 可能还有一些与此功能相关的其他方面我没有处理(因为我不是这方面的专家),但目标只是让我正常工作

  • 输出 :

    48 bytes required to hold the encrypted buf

    Encrypted data: [<É╙åh∩φ:bOPs r2w~w╪c╟D╡ï╥V╟neΓßv∩·J8cÅ╥²²²²s]
    Size: 48

    Decrypted data: [abcdefghijklmnopqrstuvwxyzabcdefΓßv∩·J8cÅ╥²²²²s]
    Size: 32

    关于c - WinAPI - CryptDecrypt() 在 AES 256 中无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51839466/

    33 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com