为什么 CertificateRequest 的 PublicKey.Key 与私钥不在同一提供商中?

Why is PublicKey.Key of CertificateRequest isn't in the same provider as the private key?

我使用这个创建证书请求:

CertificateRequest req = new CertificateRequest(
                          "cn=test",
                          Key,
                          HashAlgorithmName.SHA256,
                          RSASignaturePadding.Pkcs1);

key 从 CSP 设置:

提供商名称:“Utimaco CryptoServer CSP”

KeyContainerName:“默认容器”

但是在调试时我发现 req.PublicKey.Key.CspKeyContainerInfo 指的是另一个提供者:

ProviderName:“Microsoft 增强型 RSA 和 AES 加密提供程序”

KeyContainerName: 空

当我尝试获取 Exportable 值时:

var isExportable = ((RSACryptoServiceProvider)req.PublicKey.Key).CspKeyContainerInfo.Exportable;

它抛出一个CryptographicException:密钥不存在

我不明白为什么私钥和公钥分别存储在不同的供应商?! 还是其他意思?

TL;DR 该提供程序设置为通用 RSA 提供程序,但请注意 KeyContainerNamenull。这是因为它只是在内存中生成,并没有存储在任何地方。

证书签名请求 (CSR) 是从应用程序内部创建的 public 文件。此时与私钥的“唯一”关系是:

  1. 需要包含[=36​​=]键;
  2. 需要用私钥签名(以表明您在创建 CSR 时可以访问它,并防止它被更改);

为此,它从密钥对中加载 public 密钥,从中创建未签名的 CSR,然后使用私钥对其进行签名。 除此之外,CSR 仅用于请求实际证书。 无需简单地将 CSR/私钥存储在 HSM 中。 这反映在(例如)PKCS#11 根本没有任何 CSR 的概念。

请注意,丢失 CSR 的风险很小,您可以随时重新创建一个。此外,如果有人在您将 CSR 发送给 CA 之前获得它,那么它会被签名验证捕获(或者您会得到一个带有错误 public 密钥的无效证书,请始终确保这是验证并尽快发送 CSR。

当您收到实际证书时,将其存储在 HSM 中是有意义的。通常会存储到根的整个证书链,因为协议(包括 TLS 和 CMS)通常需要中间证书。毕竟它们被用于每一个签名创建 - 希望你没有将私有对用于你为其创建它的 PKI 之外的任何其他东西。


许多 HSM 确实提供了存储通用数据的规定。尽管您可以将 CSR 放在那里,但它只是一个通用存储;密钥存储本身不会 link 带有私钥的 CSR,因此您不妨将其保存在存储中,希望在某个受保护的位置,只有您的密钥管理器具有写入权限。