【发布时间】:2014-02-22 15:23:07
【问题描述】:
简介
我正在尝试执行以下操作来检查证书的 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 Crypto API 使用证书的 public key 对 encryptedDigest 进行 RSA 解密,但每种方法都会出错.
尝试 #1 解决
尝试使用 CryptDecrypt
结果:错误2148073485(密钥不存在)
请参阅下面的失败代码(示例 #1)。
简短的搜索表明,该 API 不允许使用 公钥 进行 解密。
如果写错了,请指点一下怎么做。
尝试 #2 解决
尝试使用 CryptVerifySignature
结果:错误87(参数不正确)
请参阅下面的失败代码(示例 #2)。
尝试了多种方式更改代码,但仍然找不到返回无效参数错误的原因
示例 #2 有什么问题?
其他
我不需要高级函数,由于性能要求,除了所需的 RSA 解密之外,它还执行许多其他操作。
也不希望使用 OpenSSL 或其他加密库
代码示例 #1 (CryptDecrypt)
// 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);
}
代码示例 #2 (CryptVerifySignature)
// 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);
}
}
【问题讨论】:
标签: c++ windows encryption cryptoapi