我使用了微软上的数字信封的加解密函数,加密过程可以顺利完成但是解密数据时会报错:8009200c找不到可用于解密的证书和私钥。 这个问题是什么原因造成的,代码如下
//-------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Example of encrypting data and creating an enveloped
// message using CryptEncryptMessage.
#pragma comment(lib, "crypt32.lib")
#include <stdio.h>
#include <windows.h>
#include <Wincrypt.h>
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
void HandleError(char* s);
PCCERT_CONTEXT GetRecipientCert(HCERTSTORE hCertStore);
void ByteToStr(
DWORD cb,
void* pv,
LPSTR sz);
BOOL DecryptMessage(
BYTE* pbEncryptedBlob,
DWORD cbEncryptedBlob,
HCRYPTPROV hCryptProv,
HCERTSTORE hStoreHandle);
HCRYPTPROV GetCryptProv();
void main()
{
//--------------------------------------------------------------------
// 变量申明与初始化
BYTE* pbContent = (BYTE*)"Security is our business.";// 待加密消息
DWORD cbContent = strlen((char*)pbContent) + 1; // 消息长度
HCRYPTPROV hCryptProv; // CSP句柄
HCERTSTORE hStoreHandle; //证书库句柄
PCCERT_CONTEXT pRecipientCert; //接收证书
PCCERT_CONTEXT RecipientCertArray[1]; //接收证书列表
DWORD EncryptAlgSize;
CRYPT_ALGORITHM_IDENTIFIER EncryptAlgorithm;
CRYPT_ENCRYPT_MESSAGE_PARA EncryptParams;
DWORD EncryptParamsSize;
BYTE* pbEncryptedBlob;
DWORD cbEncryptedBlob;
printf("即将从消息 %s 开始.\n", pbContent);
printf("这个消息的长度是 %d 字节. \n", cbContent);
//获取加密服务者句柄
hCryptProv = GetCryptProv();
//--------------------------------------------------------------------
// 打开系统证书库.
if (hStoreHandle = CertOpenSystemStore(
hCryptProv,
"MY"))
{
printf(" MY 证书库已经打开. \n");
}
else
{
HandleError("获取证书库句柄出错.");
}
//--------------------------------------------------------------------
// 调用函数GetRecipientCert获取接收者证书
if (pRecipientCert = GetRecipientCert(
hStoreHandle))
{
printf("接收者的证书已经获取. \n");
}
else
{
printf("No certificate with a CERT_KEY_CONTEXT_PROP_ID \n");
printf("property and an AT_KEYEXCHANGE private key available. \n");
printf("While the message could be encrypted, in this case, \n");
printf("it could not be decrypted in this program. \n");
printf("For more information, see the documentation for \n");
printf("CrypteEncryptMessage and CryptDecryptMessage.\n\n");
HandleError("No Certificate with AT_KEYEXCHANGE key in store.");
}
//--------------------------------------------------------------------
// 创建接收证书列表.这里仅包含一个接收者证书
RecipientCertArray[0] = pRecipientCert;
//--------------------------------------------------------------------
// 初始化算法结构.
EncryptAlgSize = sizeof(EncryptAlgorithm);
//--------------------------------------------------------------------
// 初始化算法结构为0.
memset(&EncryptAlgorithm, 0, EncryptAlgSize);
//--------------------------------------------------------------------
// 设置算法结构的必要的成员变量.
EncryptAlgorithm.pszObjId = szOID_RSA_RC4;
//--------------------------------------------------------------------
// 初始化CRYPT_ENCRYPT_MESSAGE_PARA 结构.
EncryptParamsSize = sizeof(EncryptParams);
memset(&EncryptParams, 0, EncryptParamsSize);
EncryptParams.cbSize = EncryptParamsSize;
EncryptParams.dwMsgEncodingType = MY_ENCODING_TYPE;
EncryptParams.hCryptProv = hCryptProv;
EncryptParams.ContentEncryptionAlgorithm = EncryptAlgorithm;
//--------------------------------------------------------------------
// 调用 CryptEncryptMessage加密消息.
//获取加密后数据长度
if (CryptEncryptMessage(
&EncryptParams,
1,
RecipientCertArray,//收件证书列表
pbContent,
cbContent,
NULL,
&cbEncryptedBlob))
{
printf("加密消息是 %d 字节. \n", cbEncryptedBlob);
}
else
{
HandleError("获取加密后数据块长度失败.");
}
//--------------------------------------------------------------------
// 分配内存空间.
if (pbEncryptedBlob = (BYTE*)malloc(cbEncryptedBlob))
{
printf("已经为加密数据块分配了内存空间. \n");
}
else
{
HandleError("加密时内存分配出错.");
}
//--------------------------------------------------------------------
// 加密消息
if (CryptEncryptMessage(
&EncryptParams,
1,
RecipientCertArray,
pbContent,
cbContent,
pbEncryptedBlob,
&cbEncryptedBlob))
{
printf("加密成功. \n");
}
else
{
HandleError("加密失败.");
}
//--------------------------------------------------------------------
// 调用DecryptMessage解密消息
if (DecryptMessage(
pbEncryptedBlob,
cbEncryptedBlob,
hCryptProv,
hStoreHandle))
{
printf("解密成功. \n");
}
else
{
printf("解密失败. \n");
}
//--------------------------------------------------------------------
//释放内存空间.
CertFreeCertificateContext(pRecipientCert);
if (CertCloseStore(
hStoreHandle,
CERT_CLOSE_STORE_CHECK_FLAG))
{
printf("MY证书库顺利关闭. \n");
}
else
{
printf("加密后证书库关闭 -- \n"
"但是不是所有证书或证书撤消列表都被释放. \n");
}
if (hCryptProv)
{
CryptReleaseContext(hCryptProv, 0);
printf("CSP句柄已经释放. \n");
}
else
{
printf("CSP句柄为空. \n");
}
} // End of main
//--------------------------------------------------------------------
// 功能:解密用函数CryptDecryptMessage加密的消息.
// 参数
// pbEncryptedBlob:待解密的消息
// cbEncryptedBlob:待解密消息长度
// hCryptProv: CSP句柄
// hStoreHandle: 已打开的证书库句柄
BOOL DecryptMessage(
BYTE* pbEncryptedBlob,
DWORD cbEncryptedBlob,
HCRYPTPROV hCryptProv,
HCERTSTORE hStoreHandle)
{
//--------------------------------------------------------------------
//申明与初始化变量
DWORD cbDecryptedMessage;
char* EncryptedString = (char*)malloc(sizeof(char) * (cbEncryptedBlob * 2 + 1));
HCERTSTORE CertStoreArray[] = { hStoreHandle };
CRYPT_DECRYPT_MESSAGE_PARA DecryptParams;
DWORD DecryptParamsSize = sizeof(DecryptParams);
BYTE* pbDecryptedMessage;
LPSTR DecryptedString;
BOOL fReturn = TRUE;
ByteToStr(
cbEncryptedBlob,
pbEncryptedBlob,
EncryptedString);
//--------------------------------------------------------------------
//打印转化后的密文.
printf("加密后的字符串是: \n%s\n", EncryptedString);
//--------------------------------------------------------------------
// 初始化CRYPT_DECRYPT_MESSAGE_PARA结构.
memset(&DecryptParams, 0, DecryptParamsSize);
DecryptParams.cbSize = DecryptParamsSize;
DecryptParams.dwMsgAndCertEncodingType = MY_ENCODING_TYPE;
DecryptParams.cCertStore = 1;
DecryptParams.rghCertStore = CertStoreArray;//证书库列表
//--------------------------------------------------------------------
// 解密消息数据.
// 先调用CryptDecryptMessage确定解密后数据长度.
if (CryptDecryptMessage(
&DecryptParams,
pbEncryptedBlob,
cbEncryptedBlob,
NULL,
&cbDecryptedMessage,
NULL))
{
printf("解密后数据的长度是: %d.\n", cbDecryptedMessage);
}
else
{
HandleError("获取解密后消息长度出错");
}
//--------------------------------------------------------------------
// 分配空间
if (pbDecryptedMessage = (BYTE*)malloc(
cbDecryptedMessage))
{
printf("已经为解密消息分配了内存空间. \n");
}
else
{
HandleError("解密时内存分配出错");
}
//--------------------------------------------------------------------
// 调用 CryptDecryptMessage 解密数据.
if (CryptDecryptMessage(
&DecryptParams,
pbEncryptedBlob,
cbEncryptedBlob,
pbDecryptedMessage,
&cbDecryptedMessage,
NULL))
{
DecryptedString = (LPSTR)pbDecryptedMessage;
printf("消息解密成功. \n");
printf("被解密的字符串是: %s\n", DecryptedString);
}
else
{
printf("解密此消息出错 \n");
printf("错误代码 %x \n", GetLastError());
fReturn = FALSE;
}
//--------------------------------------------------------------------
//释放内存空间
free(pbEncryptedBlob);
free(pbDecryptedMessage);
return fReturn;
} // End of DecryptMessage
//--------------------------------------------------------------------
// ByteToStr: 转换BYTE类型数组为字符串
//参数:cb[in] 需要转换的BYTE数组的长度
// pv[in] 需要转换的BYTE数组指针
// sz[out] 字符串指针
void ByteToStr(
DWORD cb,
void* pv,
LPSTR sz)
{
BYTE* pb = (BYTE*)pv;
DWORD i;
int b;
for (i = 0; i < cb; i++)
{
//pb的前4位转换为字符
b = (*pb & 0xF0) >> 4;
*sz++ = (b <= 9) ? b + '0' : (b - 10) + 'A';
//pb的后4位转换为字符
b = *pb & 0x0F;
*sz++ = (b <= 9) ? b + '0' : (b - 10) + 'A';
pb++;
}
*sz++ = 0;
}
//--------------------------------------------------------------------
// 功能:遍历证书库中的证书,才,找到则返回此证书.
// 参数:hCertStore 证书库句柄
PCCERT_CONTEXT GetRecipientCert(
HCERTSTORE hCertStore)
{
//--------------------------------------------------------------------
// 申明与初始化变量
PCCERT_CONTEXT pCertContext = NULL;
BOOL fMore = TRUE;
DWORD dwSize = 0;
CRYPT_KEY_PROV_INFO* pKeyInfo = NULL;
DWORD PropId = CERT_KEY_PROV_INFO_PROP_ID;
//--------------------------------------------------------------------
// 寻找包含交换密钥对的证书
while (fMore && (pCertContext = CertFindCertificateInStore(
hCertStore, // 证书库句柄.
0, // 编码类型.
0, // dwFindFlags. 说明查询标准,这里没有使用
CERT_FIND_PROPERTY, // 查询类型,决定进行何种类型的查询。这里使用证书的特定扩展属性
&PropId, // pvFindPara. 给出查询的特定值,这里为 扩展属性的标识符
pCertContext))) //证书句柄,第一次调用时为NULL ,之后为上一次返回的指针
{
//-------------------------------------------------------------
// 获取证书属性:密钥对信息
if (!(CertGetCertificateContextProperty(
pCertContext,
CERT_KEY_PROV_INFO_PROP_ID,
NULL, &dwSize)))
{
HandleError("获取密钥特性出错.");
}
//--------------------------------------------------------------
// 分配空间
if (pKeyInfo)
free(pKeyInfo);
if (!(pKeyInfo = (CRYPT_KEY_PROV_INFO*)malloc(dwSize)))
{
HandleError("为变量 pKeyInfo 分配内存出错.");
}
//--------------------------------------------------------------
// 获取密钥信息块.
if (!(CertGetCertificateContextProperty(
pCertContext,
CERT_KEY_PROV_INFO_PROP_ID,
pKeyInfo,
&dwSize)))
{
HandleError("第二次调用此函数失败.");
}
//-------------------------------------------
// 检查密钥信息块是否包含交换密钥对.
if (pKeyInfo->dwKeySpec == AT_KEYEXCHANGE)
{
fMore = FALSE;
}
} // End of while loop
if (pKeyInfo)
free(pKeyInfo);
return (pCertContext);
} // End of GetRecipientCert
//获取加密提供者句柄
HCRYPTPROV GetCryptProv()
{
HCRYPTPROV hCryptProv; // 加密服务提供者句柄
//获取加密提供者句柄
if (CryptAcquireContext(
&hCryptProv, // 加密服务提供者句柄
"ruanou", // 密钥容器名,这里使用登陆用户名
MS_ENHANCED_PROV, // 加密服务提供者
PROV_RSA_FULL, // 加密服务提供者类型,可以提供加密和签名等功能
0)) // 标志
{
printf("加密服务提供者句柄获取成功!\n");
}
else
{
//重新建立一个新的密钥集
if (!CryptAcquireContext(&hCryptProv, "ruanou", MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET))
{
HandleError("重新建立一个新的密钥集出错!");
}
}
return hCryptProv;
}
// HandleError:错误处理函数,打印错误信息,并退出程序
void HandleError(char* s)
{
printf("程序执行发生错误!\n");
printf("%s\n", s);
printf("错误代码为: %x.\n", GetLastError());
printf("程序终止执行!\n");
exit(1);
}
就是CryptDecryptMessage()这个函数之后报的错误,请解答一下!