【问题标题】:PKCS #7 encryptedDigest decryption and validation using Windows Crypto API and C++PKCS #7 encryptedDigest 使用 Windows Crypto API 和 C++ 解密和验证
【发布时间】: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


    【解决方案1】:

    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
    //
    ...
    

    进入示例的第二部分。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-08
      • 2010-12-03
      • 2021-09-22
      • 2018-06-26
      相关资源
      最近更新 更多