Winapi 如何从X.509证书获取HCRYPTKEY?

Winapi 如何从X.509证书获取HCRYPTKEY?,winapi,certificate,smartcard,cryptoapi,Winapi,Certificate,Smartcard,Cryptoapi,该证书是通过BSI API(gscBsiPkiGetCertificate)从智能卡获得的,我正在尝试获取其公钥/私钥对的密钥句柄,以使用CryptoAPI的CryptoEncrypt和CryptoDecrypt函数执行非对称加密操作 我试过的 gscBsiPkiGetCertificate以十六进制编码的形式返回原始证书数据,我能够对其进行解码,并成功调用CertCreateCertificateContext以获取CERT\u上下文结构。有了这个CERT\u上下文,我用参数尝试了CertGe

该证书是通过BSI API(
gscBsiPkiGetCertificate
)从智能卡获得的,我正在尝试获取其公钥/私钥对的密钥句柄,以使用CryptoAPI的
CryptoEncrypt
CryptoDecrypt
函数执行非对称加密操作

我试过的
gscBsiPkiGetCertificate
以十六进制编码的形式返回原始证书数据,我能够对其进行解码,并成功调用
CertCreateCertificateContext
以获取
CERT\u上下文
结构。有了这个
CERT\u上下文
,我用参数尝试了
CertGetCertificateContextProperty

  • CERT\u KEY\u CONTEXT\u PROP\u ID
  • CERT\u KEY\u PROV\u HANDLE\u PROP\u ID
  • CERT\u KEY\u PROV\u INFO\u PROP\u ID
  • CERT\u HCRYPTPROV\u或加密密钥\u句柄\u PROP\u ID
  • CERT\u HCRYPTPROV\u TRANSFER\u PROP\u ID
然而,他们都返回了
CRYPT\u E\u NOT\u FOUND
。我还尝试了
GetCryptProvFromCert
,希望获得证书容器句柄,这样我就可以通过
CryptGetUserKey
获得密钥句柄。但是,
GetCryptProvFromCert
失败,出现错误
CRYPT\u E\u NO\u KEY\u属性

我目前使用纯CryptoAPI作为解决方法:
CryptoAcquireContext
访问卡->
CryptoGetProvParam
枚举证书容器->
CryptoAcquireContext
访问容器->
CryptoGetUserKey
获取密钥句柄。这远非理想,因为我必须在容器中进行交互以找到所需的证书
gscBsiPkiGetCertificate
允许我指定一个AID值来直接获取证书

我还尝试过使用
CryptEncryptMessage
,它直接接受
PCCERT\u上下文
,从而避免了使用
HCRYPTKEY
。但是,尝试使用算法标识符
szOID\u RSA
szOID\u RSA\u ENCRPT
szOID\u RSA\u DH
时,所有返回的都是
CRYPT\u E\u UNKNOWN\u ALGO
。我很确定证书支持RSA加密,因为在通过CryptoAPI获得的密钥句柄上使用
KP\u ALGID
调用
CryptGetKeyParam
会返回我
CALG\u RSA\u KEYX

奖金挑战
我正在使用BSIAPI访问卡中的数据和证书容器。我希望避免这种变通方法,因为我希望将所有智能卡操作标准化,只使用BSI或CryptoAPI。如果我无法使用BSIAPI获得密钥句柄,那么我想知道如何使用CryptoAPI访问数据容器
CryptGetProvParam
仅枚举证书容器。

您可以尝试类似的方法
1) 您将获得证书上下文,例如
pSignerCertContext=CertFindCertificateInstaller(hCertStore、PKCS_7_ASN_编码、X509_ASN_编码、0、CERT_FIND_散列和散列,NULL)
2) 您可以获得密码提供者的句柄,例如:
CryptAcquireContext(&hProv,strContainer.c_str(),strProvider.c_str(),PROV_RSA_FULL,CRYPT_SILENT)
3) 您将证书上下文与加密提供程序关联,例如
CertSetCertificateContext属性(pSignerCertContext、证书设置、密钥、认证、句柄、属性ID、0和hProv)

4) 在此之后,您可以在内部仅包含公钥的CryptAcquireCertificatePrivateKey或CryptGetUserKey

证书。因此,您可以提取它并仅用于加密数据(或检查签名)。私钥由提供程序单独存储。所以,您需要在证书和提供者之间建立关系。CERT_KEY_PROV_INFO_PROP_ID和其他属性当然也不存储在证书中,而是存储在与CERT_上下文相关的内存结构中-CertGetCertificateContextProperty的结果非常依赖于您如何获得CERT_上下文。如果您是从应用商店(比如CertFindCertificateInstance)获得的,您可以获得其中一些属性。如果您从原始数据(CertCreateCertificateContext)创建CERT\u上下文-上下文中没有此属性是什么阻止您使用
gscbsipkicute()
?我的意思是,如果您必须访问
gscBsiPkiGetCertificate
,那么您还可以访问API中的其他函数,对吗?否则,您可能必须为CryptoAPI编写自己的CSP(加密服务提供商)/插件。@RbMm感谢您的澄清。我可以知道你是如何了解这些细节的吗?@MaartenBodewes不幸的是,BSI API似乎只支持BSI_RSA_NO_PAD算法,我认为这是没有填充的RSA算法。我需要带填充的RSA。