如何从X.509证书获得HCRYPTKEY?

时间:2016-10-28 02:47:11

标签: winapi certificate smartcard cryptoapi

证书是通过BSI API(gscBsiPkiGetCertificate)从智能卡获得的,我试图获取其公钥/私钥对的密钥句柄,以使用CryptoAPI执行非对称加密操作&# 39; s CryptEncryptCryptDecrypt函数。

我尝试过什么

gscBsiPkiGetCertificate以十六进制编码形式返回原始证书数据,我能够对其进行解码并成功调用CertCreateCertificateContext以获取CERT_CONTEXT结构。使用此CERT_CONTEXT,我尝试了CertGetCertificateContextProperty参数

  • CERT_KEY_CONTEXT_PROP_ID
  • CERT_KEY_PROV_HANDLE_PROP_ID
  • CERT_KEY_PROV_INFO_PROP_ID
  • CERT_HCRYPTPROV_OR_NCRYPT_KEY_HANDLE_PROP_ID
  • CERT_HCRYPTPROV_TRANSFER_PROP_ID

但是所有人都返回了CRYPT_E_NOT_FOUND。我还试过GetCryptProvFromCert希望获得证书容器句柄,这样我就可以通过CryptGetUserKey获取密钥句柄了。但GetCryptProvFromCert失败,错误为CRYPT_E_NO_KEY_PROPERTY

我目前正在使用纯CryptoAPI作为解决方法:CryptAcquireContext来访问卡 - > CryptGetProvParam枚举证书容器 - > CryptAcquireContext访问容器 - > CryptGetUserKey获得关键句柄。这远非理想,因为我通过容器进行交互以找到所需的证书。 gscBsiPkiGetCertificate允许我指定AID值以直接获取证书。

我还尝试使用CryptEncryptMessage直接使用PCCERT_CONTEXT,因此无需使用HCRYPTKEY。但是,尝试使用算法标识szOID_RSAszOID_RSA_ENCRPTszOID_RSA_DH都会返回CRYPT_E_UNKNOWN_ALGO。我非常确定该证书支持RSA加密,因为通过CryptoAPI获取的密钥句柄上使用CryptGetKeyParam调用KP_ALGID会返回CALG_RSA_KEYX

奖金挑战

我正在使用BSI API访问卡内的数据和证书容器。我想避免解决方法,因为我想将所有智能卡操作标准化为仅使用BSI或CryptoAPI。如果我不可能使用BSI API获取密钥句柄,那么我想知道如何使用CryptoAPI来访问数据容器。 CryptGetProvParam仅枚举证书容器。

1 个答案:

答案 0 :(得分:0)

您可以尝试类似的方法
1)您获得证书上下文,例如
pSignerCertContext = CertFindCertificateInStore(hCertStore,PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,0,CERT_FIND_HASH,&hashBlob,NULL)
2)您可以获得加密提供者的句柄,例如:
CryptAcquireContext(&hProv,strContainer.c_str(),strProvider.c_str(),PROV_RSA_FULL,CRYPT_SILENT)
3)您将证书上下文与加密提供者相关联,例如
CertSetCertificateContextProperty(pSignerCertContext,CERT_SET_KEY_PROV_HANDLE_PROP_ID,0,&hProv)
4)之后,您可以使用CryptAcquireCertificatePrivateKey或CryptGetUserKey