我正在尝试执行以下操作来检查证书的 SignedData.SignerInfo.encryptedDigest :
1) Read
SignedData.contentInfo +
SignedData.SignerInfo.authenticatedAttributes
2) Calculate Hash of contentInfo and authenticatedAttributes
using SignedData.digestAlgorithm
3) Read SignerInfo.encryptedDigest and certificate's PUBLIC key
4) Decrypt encryptedDigest using the acquired key
(it is the problem, and the question is about this)
5) Compare decryptedDigest's hash
with hash of contentInfo and authenticatedAttributes (STEP 2)
我尝试了使用 Windows加密API 对证书的公钥进行RSA解密 encryptedDigest 的不同方法,但每个方法都会出错。
尝试使用 CryptDecrypt
结果:错误 2148073485 (密钥不存在)
请参阅下面的失败代码(示例#1)
简要搜索告诉我,API不允许使用公钥进行解密。
如果是错的,请给我一个如何做的提示。
尝试使用 CryptVerifySignature
结果:错误 87 (参数不正确)
请参阅下面的失败代码(示例#2)
试图以几种方式改变代码,但仍然无法找出返回无效参数错误的原因
样本#2有什么问题?
我不需要高级功能,由于性能要求,除执行所需的RSA解密外,还执行许多其他操作。
也不希望使用OpenSSL或其他加密库
// certPublicKey = certContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData[.cbData]
const size_t StructSize = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + certPublicKey.size();
boost::scoped_array<uint8_t> arr(new uint8_t[StructSize]);
BLOBHEADER* pHeader = (BLOBHEADER*)&arr[0];
pHeader->bType = PUBLICKEYBLOB;
pHeader->bVersion = CUR_BLOB_VERSION;
pHeader->reserved = 0;
pHeader->aiKeyAlg = CALG_RSA_KEYX;
RSAPUBKEY* pPubKey = (RSAPUBKEY*)&arr[sizeof(BLOBHEADER)];
pPubKey->magic = 0x31415352;
pPubKey->bitlen = certPublicKey.size() * 8;
pPubKey->pubexp = 65537; // ?? is it correct for RSA ?
uint8_t* pKeyData = &arr[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY)];
memcpy(pKeyData, &certPublicKey[0], certPublicKey.size());
HCRYPTKEY hKey;
BOOL res = CryptImportKey(g_hProv, (const BYTE*)&arr[0], StructSize, NULL, 0, &hKey);
PRINT_RES("CryptImportKey", res);
if (res)
{
blob_t decryptedData = encryptedText;
DWORD decryptedLength = encryptedText.size();
res = CryptDecrypt(hKey, NULL, TRUE, 0, decryptedData.data(), &decryptedLength);
PRINT_RES("CryptDecrypt", res); // err = 2148073485 (Key does not exist)
if (res)
{
...
}
res = CryptDestroyKey(hKey);
PRINT_RES("CryptDestroyKey", res);
}
// hashInput = SignedData.contentInfo + SignedData.SignerInfo[0].authenticatedAttributes
HCRYPTHASH hHash;
blob_t hashValue;
BOOL res = CryptCreateHash(g_hProv, CALG_SHA1, NULL, 0, &hHash);
PRINT_RES("CryptCreateHash", res);
if (res)
{
res = CryptHashData(hHash, hashInput.data(), hashInput.size(), 0);
PRINT_RES("CryptHashData", res);
PCCERT_CONTEXT certContext = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, certData.data(), certData.size());
PRINT_RES("CertCreateCertificateContext", certContext ? TRUE : FALSE);
if (certContext)
{
HCRYPTKEY hCertPubKey;
res = CryptImportPublicKeyInfo(g_hProv, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &certContext->pCertInfo->SubjectPublicKeyInfo, &hCertPubKey);
PRINT_RES("CryptImportPublicKeyInfo", res);
if (res)
{
res = CryptVerifySignatureA(hHash, encryptedText.data(), encryptedText.size(), hCertPubKey, NULL, 0);
PRINT_RES("CryptVerifySignature", res); // err = 87 (The parameter is incorrect)
res = CryptDestroyKey(hCertPubKey);
PRINT_RES("CryptDestroyKey", res);
}
CertFreeCertificateContext(certContext);
}
}
答案 0 :(得分:0)
encryptedDigest
包含签名,您不会对其进行解密,但会验证签名,因此您的第二个CryptVerifySignature
大道是有前途的。
这里可能会出现多种问题,例如您并没有真正告诉我们有关证书的任何信息。请按照MSDN上的Example C Program: Encoding and Decoding a Countersigned Message进行操作,您将在第2步中对CryptVerifyMessageSignature
感兴趣,
...
// From the recipient's point of view, the following code
// completes these steps:
// 1. Decodes the message
// 2. Verifies the signature on the message
// 3. Adds a countersignature to the signed message
//
...
朝向示例的第二部分。