【问题标题】:Is there any replacement for ENGINE_load_private_key() when working with CAPI?使用 CAPI 时是否可以替换 ENGINE_load_private_key()?
【发布时间】: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() 吗?

【问题讨论】:

    标签: c openssl schannel


    【解决方案1】:

    我碰到了同一堵墙并做了一个小研究。看起来这不是一个错误,而是 Microsoft CryptoAPI 的一种工作方式。在不可导出密钥的情况下,无法使用 CryptExportKey 和 PRIVATEKEYBLOB 从 Windows 证书存储中导出密钥。因此,您可以只获得一个参考,一个密钥对的 id,稍后您可以使用它通过 CryptoAPI 进行所有加密操作(不能导出真正的密钥)。所以 openssl CAPI 引擎遵循了这条路径,他们只得到一个所需的密钥对 id,然后将其泵入 CryptoAPI 以执行所需的操作。

    我认为这也是 capi_rsa_priv_enc 未实现的原因(CryptEncrypt 总是从提供的密钥对 id 中选择公钥)并且因为没有真正导出的私钥(只有密钥对 id),他们甚至无法执行加密即使在 CryptoAPI 旁边也有私钥。但这只是我的猜测。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-03-24
      • 1970-01-01
      • 1970-01-01
      • 2015-05-15
      • 2017-08-26
      • 2023-03-04
      • 1970-01-01
      相关资源
      最近更新 更多