使用Windows CryptoAPI使用AES 256位密钥解密的简单代码有什么问题?

使用Windows CryptoAPI使用AES 256位密钥解密的简单代码有什么问题?,c,encryption,cryptography,aes,cryptoapi,C,Encryption,Cryptography,Aes,Cryptoapi,我有一个使用AES-256密钥加密文件的小程序。用于加密文件的密钥是随机生成的 加密程序如下所示: 获取加密上下文-CryptAcquireContext 使用CryptGenKey 使用此密钥加密文件--CryptEncrypt 释放到上下文--CryptReleaseContext 加密的文件是一个小的test.txt文件,其中包含字符串:“justatest”。因此,文件中的原始十六进制字节是: 6A 75 73 74 20 61 20 74 65 73 74 用于十六进制格式加密的

我有一个使用AES-256密钥加密文件的小程序。用于加密文件的密钥是随机生成的

加密程序如下所示:

  • 获取加密上下文-
    CryptAcquireContext
  • 使用
    CryptGenKey
  • 使用此密钥加密文件--
    CryptEncrypt
  • 释放到上下文--
    CryptReleaseContext
加密的文件是一个小的
test.txt
文件,其中包含字符串:“justatest”。因此,文件中的原始十六进制字节是:

6A 75 73 74 20 61 20 74 65 73 74
用于十六进制格式加密的AES-256密钥为:

3F10E23BB1A5DFD9C8CA06195E43043386A9BA4C63C35AC518F463B768F001B

加密文件
test.enc
则包含以下字节:

C8 B5 92 51 22 53 75 A1 34 80 EC AA 37 1C 6C BE 
问题:

如何编写c/c++程序,使用Windows CryptoAPI的
cryptoDecrypt
函数,使用十六进制AES-256密钥对这些字节进行解密

我尝试过的:

我已经编写了以下解密程序(对

#包括
#包括
#包括
#pragma注释(lib,“crypt32.lib”)
#定义块_len128
HCRYPTPROV HCRYPTPROV;
int wmain(int argc,wchar_t*argv[])
{
wchar_t default_key[]=L“PXDIO7GL39NIYGYZXKMEM4APUKXJW1RFGPRJUNAPBS”;
wchar\u t*key\u str=默认密钥;
尺寸长度=lstrlenW(关键长度);
if(!CryptAcquireContext)(
&hCryptProv,
无效的
吴恩华女士,
证明,
空)
{

/*std::cout简单演示程序

这是一个小的C程序,它使用你的密钥和加密数据,并再次解密原始文本

为了简单起见,它不从文件系统读取文件,而是将C程序中的数据定义为十六进制字符串

结果

运行程序时,以下输出将输出到控制台:

decrypted result: 'just a test'
C代码

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

void error(const char* what) {
    fprintf(stderr, "%s failed with last error 0x%x\n", what, GetLastError());
    exit(1);
}

#define AES_KEY_SIZE 32
typedef struct {
    BLOBHEADER hdr;
    DWORD dwKeySize;
    BYTE rgbKeyData[AES_KEY_SIZE];
} AES256KEYBLOB;

BYTE *hex2byte(const char *hex) {
    int len = strlen(hex) / 2;
    BYTE* bytes = malloc(len);
    if (bytes == NULL) { 
        error("malloc");  
        return NULL; 
    }
    unsigned char val[2];

    for (int i = 0; i < len; i++) {
        sscanf_s(&hex[i * 2], "%2hhx", &val);
        bytes[i] = val[0];
    }
    return bytes;
}

int main() {
    BYTE *key = hex2byte("3F10E23BB1A5DFD9C8CA06195E43043386A9BA4C63C35AC518F463BA768F001B");

    AES256KEYBLOB aes256KeyBlob;
    aes256KeyBlob.hdr.bType = PLAINTEXTKEYBLOB;
    aes256KeyBlob.hdr.bVersion = CUR_BLOB_VERSION;
    aes256KeyBlob.hdr.reserved = 0;
    aes256KeyBlob.hdr.aiKeyAlg = CALG_AES_256;
    aes256KeyBlob.dwKeySize = AES_KEY_SIZE;
    memcpy(aes256KeyBlob.rgbKeyData, key, AES_KEY_SIZE);

    HCRYPTPROV hProv;
    if (!CryptAcquireContextA(&hProv, NULL, MS_ENH_RSA_AES_PROV_A, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
        error("CryptAcquireContext");
    }

    HCRYPTKEY hKey;
    if (!CryptImportKey(hProv, (BYTE*)& aes256KeyBlob, sizeof(AES256KEYBLOB), 0, CRYPT_EXPORTABLE, &hKey)) {
        CryptReleaseContext(hProv, 0);
        error("CryptImportKey");
    }

    const char *encodedHex = "C8B59251225375A13480ECAA371C6CBE";
    DWORD numBytes = strlen(encodedHex) / 2;
    BYTE *encoded = hex2byte(encodedHex);

    if (CryptDecrypt(hKey, 0, TRUE, 0, encoded, &numBytes)) {
        printf("decrypted result: '");
        for (DWORD i = 0; i < numBytes; i++) {
            printf("%c", encoded[i]);
        }
        printf("'\n");
    } else {
        CryptDestroyKey(hKey);
        CryptReleaseContext(hProv, 0);
        error("CryptDecrypt");
    }


    free(key);
    free(encoded);

    CryptDestroyKey(hKey); 
    CryptReleaseContext(hProv, 0);
    return 0;
}
#包括
#包括
#包括
无效错误(常量字符*什么){
fprintf(stderr,“%s失败,最后一个错误为0x%x\n”,什么,GetLastError());
出口(1);
}
#定义AES\u键\u大小32
类型定义结构{
BLOBHEADER hdr;
DWORD dwKeySize;
字节rgbKeyData[AES_KEY_SIZE];
}AES256KEYBLOB;
字节*hex2byte(常量字符*hex){
int len=strlen(十六进制)/2;
字节*字节=malloc(len);
如果(字节==NULL){
错误(“malloc”);
返回NULL;
}
无符号字符val[2];
对于(int i=0;i
微软文档

KEYBLOB结构记录在此处:

然而,您可以在这里找到有关BLOBHEADER结构的信息:

当CryptDecrypt失败时,会出现什么错误?调用并打印GetLastError并检查MSDN对应的错误?您对错误密钥的想法可能是正确的,但最好先看看GetLastError返回的是什么。另外,您是否可以尝试使用CryptImportKey而不是CryptDeriveKey?
CryptImportKey
希望密钥位于密钥中带有正确blob头的YBLOB格式。我已经研究过了,但无法使用原始十六进制字符串为CryptImportKey生成正确的KEYBLOB字节数组。我很久没有处理Windows Crypto API了,但我记得有一种方法可以从密钥创建blob。看看这里:您需要做的就是创建使用密钥字节数组和算法id重新构造。但您是否也检查了CryptDecrypt中的GetLastError?谢谢!您在其中编译了什么?在Visual Studio 2019中构建它会给我带来错误:
'BOOL CryptDecrypt(HCRYPTKEY,HCRYPTHASH,BOOL,DWORD,BYTE*,DWORD*)不能将参数6从“int *”转换为“dWord */CONTHEL”:另一个错误:“代码>初始化”:不能从“Value**”转换为“unChalchar *”/代码>在VisualStudio中使用C或C++吗?我正在使用VisualStudio16.0.3-稍后更新和重试。请确保使用C文件(文件后缀.c)而不是C++。哎呀。用C编译器编译的。现在工作!
#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>

void error(const char* what) {
    fprintf(stderr, "%s failed with last error 0x%x\n", what, GetLastError());
    exit(1);
}

#define AES_KEY_SIZE 32
typedef struct {
    BLOBHEADER hdr;
    DWORD dwKeySize;
    BYTE rgbKeyData[AES_KEY_SIZE];
} AES256KEYBLOB;

BYTE *hex2byte(const char *hex) {
    int len = strlen(hex) / 2;
    BYTE* bytes = malloc(len);
    if (bytes == NULL) { 
        error("malloc");  
        return NULL; 
    }
    unsigned char val[2];

    for (int i = 0; i < len; i++) {
        sscanf_s(&hex[i * 2], "%2hhx", &val);
        bytes[i] = val[0];
    }
    return bytes;
}

int main() {
    BYTE *key = hex2byte("3F10E23BB1A5DFD9C8CA06195E43043386A9BA4C63C35AC518F463BA768F001B");

    AES256KEYBLOB aes256KeyBlob;
    aes256KeyBlob.hdr.bType = PLAINTEXTKEYBLOB;
    aes256KeyBlob.hdr.bVersion = CUR_BLOB_VERSION;
    aes256KeyBlob.hdr.reserved = 0;
    aes256KeyBlob.hdr.aiKeyAlg = CALG_AES_256;
    aes256KeyBlob.dwKeySize = AES_KEY_SIZE;
    memcpy(aes256KeyBlob.rgbKeyData, key, AES_KEY_SIZE);

    HCRYPTPROV hProv;
    if (!CryptAcquireContextA(&hProv, NULL, MS_ENH_RSA_AES_PROV_A, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
        error("CryptAcquireContext");
    }

    HCRYPTKEY hKey;
    if (!CryptImportKey(hProv, (BYTE*)& aes256KeyBlob, sizeof(AES256KEYBLOB), 0, CRYPT_EXPORTABLE, &hKey)) {
        CryptReleaseContext(hProv, 0);
        error("CryptImportKey");
    }

    const char *encodedHex = "C8B59251225375A13480ECAA371C6CBE";
    DWORD numBytes = strlen(encodedHex) / 2;
    BYTE *encoded = hex2byte(encodedHex);

    if (CryptDecrypt(hKey, 0, TRUE, 0, encoded, &numBytes)) {
        printf("decrypted result: '");
        for (DWORD i = 0; i < numBytes; i++) {
            printf("%c", encoded[i]);
        }
        printf("'\n");
    } else {
        CryptDestroyKey(hKey);
        CryptReleaseContext(hProv, 0);
        error("CryptDecrypt");
    }


    free(key);
    free(encoded);

    CryptDestroyKey(hKey); 
    CryptReleaseContext(hProv, 0);
    return 0;
}