Windows CertGetSubjectCertificateFromStore api 的 AS2 文件解密问题

问题描述 投票:0回答:1

我们有一个使用 AS2 协议交换文档的 EDI 应用程序,当我们从业务合作伙伴之一收到文档并尝试解密它时,我们收到错误 - 错误 = 0x8009200C(找不到用于解密的证书和私钥。 ) 我们正在使用 CertGetSubjectCertificateFromStore api 从 Windows 证书存储中读取证书

ptrEnvelopeCert = CertGetSubjectCertificateFromStore(dwCertStoreIdx, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, ptrCertInfo);

我们所有的合作伙伴都在使用相同的解决方案。

有人可以帮忙解决可能出现的问题吗?我们已与合作伙伴验证了有关证书配置、公钥和私钥的所有详细信息,但无法识别问题。

c++ windows winapi windows-server-2019
1个回答
0
投票

CRYPT_E_NO_DECRYPT_CERT
表示证书存在但不存在其私钥。 对
CryptAcquireCertificatePrivateKey
的调用失败

这里可以有3种变体:

  1. 证书上没有
    CERT_KEY_PROV_INFO_PROP_ID
  2. 没有容器。如果密钥不在智能卡上,它通常在文件中
  3. 私钥存在,但与证书中的公钥不匹配

我们可以用下面的代码来测试它:

template <typename T> 
T HR(HRESULT& hr, T t)
{
    hr = t ? NOERROR : GetLastError();
    return t;
}

HRESULT Compare(PCCERT_CONTEXT pCertContext, 
                HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProvOrNCryptKey,
                ULONG dwKeySpec)
{
    HRESULT hr;

    PCERT_PUBLIC_KEY_INFO pInfo = 0;
    ULONG cb = 0;
    while (HR(hr, CryptExportPublicKeyInfo(hCryptProvOrNCryptKey, dwKeySpec, X509_ASN_ENCODING, pInfo, &cb)))
    {
        if (pInfo)
        {
            if (!CertComparePublicKeyInfo(X509_ASN_ENCODING, pInfo, &pCertContext->pCertInfo->SubjectPublicKeyInfo))
            {
                hr = NTE_BAD_PUBLIC_KEY;
            }
            break;
        }

        pInfo = (PCERT_PUBLIC_KEY_INFO)alloca(cb);
    }

    return hr;
}

HRESULT TestPrivKey(PCCERT_CONTEXT pCertContext)
{
    union {
        PCRYPT_KEY_PROV_INFO pckpi;
        PVOID buf = 0;
    };

    union {
        HCRYPTPROV hProv;
        NCRYPT_PROV_HANDLE hProvider;
    };

    union {
        HCRYPTKEY hKey;
        NCRYPT_KEY_HANDLE hNCryptKey;
    };

    HRESULT hr;
    ULONG cb = 0;
    while(HR(hr, CertGetCertificateContextProperty(pCertContext, CERT_KEY_PROV_INFO_PROP_ID, buf, &cb)))
    {
        if (buf)
        {
            union {
                CHAR aFileName[0x100];
                WCHAR wFileName[0x100];
            };

            if (pckpi->dwProvType)
            {
                if (HR(hr, CryptAcquireContextW(&hProv, pckpi->pwszContainerName,
                    pckpi->pwszProvName, pckpi->dwProvType, pckpi->dwFlags & CRYPT_MACHINE_KEYSET)))
                {
                    if (CryptGetProvParam(hProv, PP_UNIQUE_CONTAINER, (PBYTE)aFileName, &(cb = sizeof(aFileName)), 0))
                    {
                        DbgPrint("\"%hs\"\n", aFileName);
                    }
                    hr = Compare(pCertContext, hProv, pckpi->dwKeySpec);
                    CryptReleaseContext(hProv, 0);
                }
            }
            else
            {
                if (NOERROR == (hr = NCryptOpenStorageProvider(&hProvider, pckpi->pwszProvName, 0)))
                {
                    hr = NCryptOpenKey(hProvider, &hNCryptKey, 
                        pckpi->pwszContainerName, 
                        pckpi->dwKeySpec, pckpi->dwFlags & NCRYPT_MACHINE_KEY_FLAG);

                    NCryptFreeObject(hProvider);

                    if (NOERROR == hr)
                    {
                        if (!NCryptGetProperty(hNCryptKey, NCRYPT_UNIQUE_NAME_PROPERTY, (PBYTE)wFileName, sizeof(wFileName), &cb, 0))
                        {
                            DbgPrint("\"%ws\"\n", wFileName);
                        }
                        
                        hr = Compare(pCertContext, hNCryptKey, pckpi->dwKeySpec);

                        NCryptFreeObject(hNCryptKey);
                    }
                }
            }
            break;
        }

        buf = alloca(cb);
    }

    return hr;
}
© www.soinside.com 2019 - 2024. All rights reserved.