在为 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()
调用?这是故意规避 Windows 的任何规则并由于已知的 Windows 错误而提取私钥,还是 <code>ENGINE_load_private_key() 实际上与 CAPI 结合使用?CryptExportKey()
PUBLICKEYBLOB
有谁知道我的应用程序的 <code>ENGINE_load_private_key() 替代品?