使用Windows CryptoAPI使用AES 256位密钥解密的简单代码有什么问题?
我有一个使用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 用于十六进制格式加密的
- 获取加密上下文-
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;
}