如何解决使用CAPI时,ENGINE_load_private_key是否可以替代?
在将Windows密钥库用于OpenSSL和客户端证书的方式上,我发现了这篇文章: https://anexdev.blogspot.com/2018/10/how-to-send-client-certificate-with.html
除了给定代码中的某些拼写错误之外,该示例还启发了我编写一些代码,这些代码利用ENGINE CAPI进行键用法。总而言之,在商店( L"MY"
中找到证书之后,我可以发出ENGINE_load_private_key()并最终返回新分配的EVP_PKEY结构。
但是,我无法将此密钥与证书一起使用。经过一番调查,我发现该结构仅包含一个版本,一个模数和一个公钥组件:
RSAPrivateKey ::= SEQUENCE {
version Version,modulus INTEGER,-- n
publicExponent INTEGER,-- e
privateExponent INTEGER,-- d (this field and everything following is mising)
prime1 INTEGER,-- p
prime2 INTEGER,-- q
exponent1 INTEGER,-- d mod (p-1)
exponent2 INTEGER,-- d mod (q-1)
coefficient INTEGER,-- (inverse of q) mod p
otherPrimeInfos OtherPrimeInfos OPTIONAL
}
因此,我研究了OpenSSL实现的代码。实际上,至少在CAPI引擎显然不打算导出私钥的情况下,才是ENGINE_load_private_key()。
在openssl/crypto/engine/eng_pkey.c中,该函数调用所选引擎的成员load_privkey()
。如果使用CAPI,则在openssl/engines/e_capi.c中定义实现。此函数调用capi_find_key()
查找密钥,并调用capi_get_pkey()
接收密钥。
仔细研究static EVP_PKEY *capi_get_pkey(ENGINE *eng,CAPI_KEY *key)
的定义似乎可以解释我的问题的根源:
if (!CryptExportKey(key->key,PUBLICKEYBLOB,pubkey,&len)) {
CAPIerr(CAPI_F_CAPI_GET_PKEY,CAPI_R_PUBKEY_EXPORT_ERROR);
capi_addlasterror();
goto err;
}
为什么capi_get_pkey()
用CryptExportKey()
呼叫PUBLICKEYBLOB
?这是否是故意绕开Windows的任何规则并由于已知的Windows错误而提取私钥,还是与CAPI结合使用的事实{ENGINE_load_private_key()
实际上已被破坏?
有人知道我的应用程序可以替换ENGINE_load_private_key()
吗?
解决方法
我碰到了同一面墙并做了一个小调查。看起来这不是错误,而是 Microsoft CryptoAPI 的工作方式。对于不可导出的密钥,无法使用 CryptExportKey 和 PRIVATEKEYBLOB 从 Windows 证书存储中导出密钥。因此,您可以获得一个引用,一个密钥对的 id,稍后您可以使用它通过 CryptoAPI 进行所有加密操作(不能导出真正的密钥)。所以openssl CAPI引擎遵循了这个路径,他们只得到一个需要的密钥对id,然后将它泵入CryptoAPI来执行需要的操作。
我认为这也是没有实现 capi_rsa_priv_enc 的原因(CryptEncrypt 总是从提供的密钥对 id 中选择公钥)并且因为没有真正导出的私钥(只有密钥对 id),他们甚至无法执行加密甚至在 CryptoAPI 旁边也带有私钥。但这只是我的猜测。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。