【发布时间】:2020-12-13 20:57:37
【问题描述】:
在为 OpenSSL 和客户端证书使用 Windows 密钥库的过程中,我发现了这篇文章: https://anexdev.blogspot.com/2018/10/how-to-send-client-certificate-with.html
除了给定代码中的一些拼写错误外,该示例启发我编写了一些代码,这些代码利用 ENGINE CAPI 进行密钥使用。总而言之,在商店 ( L"MY") 中找到证书后,我能够发出 ENGINE_load_private_key() 最终返回一个新分配的 EVP_PKEY 结构。
但是我无法将此密钥与证书结合使用。经过一番调查,我发现该结构仅包含一个版本、一个模数和一个 pubkey 组件:
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 实现的代码。事实上, ENGINE_load_private_key() 至少在 CAPI 引擎明显不打算导出私钥的情况下。
在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, 0, PUBLICKEYBLOB, 0, pubkey, &len)) {
CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_ERROR);
capi_addlasterror();
goto err;
}
为什么capi_get_pkey() 用PUBLICKEYBLOB 调用CryptExportKey()?这是故意规避 Windows 的任何规则并由于已知的 Windows 错误而提取私钥,还是 ENGINE_load_private_key() 实际上与 CAPI 结合使用?
有人知道我的应用程序可以替换 ENGINE_load_private_key() 吗?
【问题讨论】: