【问题标题】:How to create a X509 certificate that prevents "server mode SSL must use certificate with associated private key" exception?如何创建防止“服务器模式 SSL 必须使用具有关联私钥的证书”异常的 X509 证书?
【发布时间】:2017-12-30 02:21:57
【问题描述】:

我正在尝试创建一个 X.509 证书文件,该文件将使用 smtp4dev 项目中的以下代码:

var certificate = new X509Certificate(Settings.Default.SSLCertificatePath);
var clientCertificateRequired = false;
var protocols = SslProtocols.Ssl2 | SslProtocols.Ssl3 | SslProtocols.Tls;
var checkRevocation = false;

var stream = new SslStream(stream);
stream.AuthenticateAsServer(certificate, clientCertificateRequired, protocols, checkRevocation);

Settings.Default.SSLCertificatePath 指向一个 .cer 文件。

无论我尝试什么,都会失败,并带有 System.NotSupportedException 消息:

服务器模式 SSL 必须使用带有相关私钥的证书。

我在提升的 PowerShell 会话中使用 New-SelfSignedCertificate PowerShell CommandLet 创建了 X509 证书:

New-SelfSignedCertificate `
    -DnsName "localhost" `
    -CertStoreLocation "cert:\CurrentUser\My" `
    -FriendlyName "smtp4dev" `
    -TextExtension "2.5.29.37={text}1.3.6.1.5.5.7.3.1" `
    -KeyUsage DigitalSignature,KeyEncipherment,DataEncipherment `
    -Provider "Microsoft RSA SChannel Cryptographic Provider"

我添加了这些选项以尽可能地镜像已存储在我的机器上并且由 IIS Express 安装程序生成的证书。因为那个特定的证书确实有效,虽然我不知道为什么。

这两个证书都位于Local Computer > Personal 证书存储中。对于这两个证书,证书管理器都提到“您有一个与此证书对应的私钥”。

当我比较这两个证书的属性时,smtp4dev 证书与 IIS Express 开发证书在以下 3 个方面不同(除了指纹和序列号):

  • Key Usage 被标记为关键扩展
  • 主题备用名称扩展名,值为DNS Name=localhost
  • 主题键标识符扩展,值为e7 12 f5 ...

我使用证书管理器将没有私钥的两个证书作为“Base-64 编码 x.509 (.CER)”文件导出到我的桌面。 (包含私钥会将导出格式限制为 smtp4dev 不支持的 PKCS #12 (.PFX)。)

以这种方式导出证书后,当我双击它们时,都没有显示关于拥有私钥的消息。

只有 IIS Express 开发证书适用于本问题开头显示的代码。 smtp4dev 没有。

我尝试过的其他事情:

  1. 我经常遇到使用makecert 的教程,但我没有那个程序。

  2. 我尝试使用由openssl 生成的自签名证书,并且只将Common Name 设置为localhost,但我得到了相同的异常(“服务器模式 SSL 必须使用具有关联的证书私钥”)。

  3. 更改代码以使用 X509Certificate2 不是一种选择,因为要获得另一个应用了补丁的 smtp4dev 版本会很耗时,因为该项目似乎没有积极开发。

  4. 实际上可以尝试不同的证书文件格式(例如 PFX),只要我将文件重命名为 .cer,我就可以欺骗 smtp4dev 使用该证书。这允许我在证书中包含私钥。它适用于 IIS Express 开发证书的导出,但不适用于 smtp4dev 证书的导出。

【问题讨论】:

  • 您可以使用 certutil -v -store my 添加证书详细信息吗?另外,.pfx/.p12 是支持存储私钥的扩展。如果我使用 .cer 证书,我希望会引发上述异常,因为它没有私钥。
  • @KaushalKumarPanday 它适用于“IIS Express 开发证书”,我也将其导出为 .cer 文件。所以这不是问题。
  • 这很有趣。因此,如果私钥没有发挥作用,那么您需要查看加密提供者。

标签: .net windows ssl x509certificate smtp4dev


【解决方案1】:

我想到的只有一件事:密钥提供程序兼容性。 SslStream 似乎不支持 CNG KSP(密钥存储提供程序),这是 New-SelfSignedCertificate` cmdlet 的默认密钥提供程序类型。

我建议在 PowerShell 调用中明确指定任何旧提供程序:

New-SelfSignedCertificate `
    -DnsName "localhost" `
    -CertStoreLocation "cert:\LocalMachine\My" `
    -FriendlyName "smtp4dev" `
    -TextExtension "2.5.29.37={text}1.3.6.1.5.5.7.3.1" `
    -KeyUsage DigitalSignature,KeyEncipherment,DataEncipherment `
    -Provider "Microsoft RSA SChannel Cryptographic Provider"

【讨论】:

  • 感谢您的建议,我根本没有考虑过!我使用您指定的提供程序选项创建了一个新证书,并将其导出到 .cer 文件。但不幸的是,我得到了同样的例外。我会阻止其他一些供应商。有没有办法在证书存储中找出用于生成现有证书的提供程序?
  • 我尝试了here 列出的所有提供程序,但没有一个提供在将其导出到 .cer 文件后可以工作的证书。
  • .cer? .cer 不包括私钥,因此出现错误。相反,您应该从证书存储中打开证书(通过 X509Store 类)。
  • .cer 在我使用“IIS Express 开发证书”时工作得很好。我编辑了我的问题以添加我在 .cer 与 .pfx 方面尝试过的内容。这一切都归结为一个证书有效,而另一个则无效。我想了解这些证书之间的区别,这些证书使它们中的一个有效而另一个无效。
  • 这确实有效。我第一次尝试时它不起作用的原因是,存储在 LocalMachine 存储中的证书的私钥需要更改其权限,以便常规(非管理员)用户运行的程序可以访问它们。我在问题中切换了生成证书的命令以使用 CurrentUser 存储,因此权限不再起作用。在这种情况下,您的答案绝对是正确的。谢谢!
猜你喜欢
  • 1970-01-01
  • 2015-10-15
  • 1970-01-01
  • 2015-10-22
  • 2021-07-12
  • 1970-01-01
  • 1970-01-01
  • 2017-03-23
  • 1970-01-01
相关资源
最近更新 更多