c# - .NET Framework x509Certificate2 类,HasPrivateKey == true && PrivateKey == null?

标签 c# powershell x509 x509certificate2

我正在尝试使用 X509 证书,该证书最初是使用 MMC 的“证书”管理单元导入到 Windows 10 计算机上的 CurrentUser keystore 中的。在 Windows 8.1 计算机上测试了相同的过程,结果相同。

使用标准的 PowerShell PKI 模块,我使用 Get-Item 获取 X509Certificate2 对象:

$my_cert = Get-Item Cert:\CurrentUser\My\ADAA82188A17THUMBPRINTXXXXXXXXXXX

$my_cert | 的输出fl * 如下:

PSPath                   : Microsoft.PowerShell.Security\Certificate::CurrentUser\My\XXXXXXXXXXXXXXXXXXX
PSParentPath             : Microsoft.PowerShell.Security\Certificate::CurrentUser\My
PSChildName              : XXXXXXXXXXXXXXXXXXX
PSDrive                  : Cert
PSProvider               : Microsoft.PowerShell.Security\Certificate
PSIsContainer            : False
EnhancedKeyUsageList     : {Secure Email (1.3.6.1.5.5.7.3.4), IP security user (1.3.6.1.5.5.7.3.7), Encrypting File
                           System (1.3.6.1.4.1.311.10.3.4), Document Signing (1.3.6.1.4.1.311.10.3.12)...}
DnsNameList              : {My Name}
SendAsTrustedIssuer      : False
EnrollmentPolicyEndPoint : Microsoft.CertificateServices.Commands.EnrollmentEndPointProperty
EnrollmentServerEndPoint : Microsoft.CertificateServices.Commands.EnrollmentEndPointProperty
PolicyId                 : {D52C406F-C279-4BF2-B7C2-EE704290DB3E}
Archived                 : False
Extensions               : {System.Security.Cryptography.Oid, System.Security.Cryptography.Oid,
                           System.Security.Cryptography.Oid, System.Security.Cryptography.Oid...}
FriendlyName             :
IssuerName               : System.Security.Cryptography.X509Certificates.X500DistinguishedName
NotAfter                 : 4/15/2017 2:15:16 PM
NotBefore                : 4/15/2016 2:15:16 PM
HasPrivateKey            : True
PrivateKey               :
PublicKey                : System.Security.Cryptography.X509Certificates.PublicKey
RawData                  : {56, 130, 19, 252...}
SerialNumber             : 4F0000002F700000000000000000000000
SubjectName              : System.Security.Cryptography.X509Certificates.X500DistinguishedName
SignatureAlgorithm       : System.Security.Cryptography.Oid
Thumbprint               : XXXXXXXXXXXXXXXXXXX
Version                  : 3
Handle                   : 2241663016272
Issuer                   : CN=Issuing CA, DC=My, DC=Domain, DC=us
Subject                  : E=my.name@my.domain.us, CN=My Name

因此 HasPrivateKey == True,但 PrivateKey == null。我一直在试图弄清楚如何获得对私钥的访问权限以执行加密和解密。我在网上看到的例子似乎都表明 X509Certificate2 类的 PrivateKey 属性应该很容易获得,但显然我错过了一些东西。

我在这里读过类似的问题,比如Empty PrivateKey in x509certificate2 ,但似乎都无法解决我的问题。我也读过 Eight tips for working with X.509 certificates in .NET保罗·斯托维尔 (Paul Stovell) 的著作,很有启发性,但最终无济于事。它确实帮助我验证了私钥是否存在于正确的位置,据我所知,它具有 x509Certificate2 类引用的正确权限:

C:\Users\My.Name\AppData\Roaming\Microsoft\SystemCertificates\My\Keys

key 文件的名称与证书上的主题 key 标识符匹配。

编辑:

certutil -user -store my "Serial Number" 的输出是:

Serial Number: 4f000000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Issuer: CN=Issuing CA, DC=My, DC=Domain, DC=us
 NotBefore: 4/15/2016 2:15 PM
 NotAfter: 4/15/2017 2:15 PM
Subject: E=my.name@my.domain.us, CN=My Name
Non-root Certificate
Template: Userv1, User v1
Cert Hash(sha1): ad ab 82 18 8a 17 4d 75 11 04 48 7c 43 43 d4 05 b9 74 c8 4c
  Key Container = te-Userv1-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  Unique container name: fcbba1aa0xxxxxxxxxxxxxxxxxxxxxxx_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  Provider = Microsoft Software Key Storage Provider
Encryption test passed
CertUtil: -store command completed successfully.

我在这里缺少什么“关键”信息?为什么不能方便地从 X509Certificate2 对象引用私钥?我如何获得访问权限?

最佳答案

您的 certutil 信息显示 Provider = Microsoft Software Key Storage Provider,这意味着私钥存储在 Windows CNG 下,而不是 Windows CryptoAPI (CAPI)。

.NET 4.6 添加了 GetRSAPrivateKey(扩展)方法以促进让 PrivateKey 属性返回不是 RSACryptoServiceProvider(或 DSACryptoServiceProvider)的内容的其他破坏性更改。如果您有权访问该方法(我不确定 PowerShell 使用的是哪个版本的框架),那么它将解决您的问题。

不过有两点需要注意:

  1. GetRSAPrivateKey 每次都返回一个唯一的 Disposable 对象。您应该将其放在 using 语句中/在完成后手动调用 Dispose(与 cert.PrivateKey 相反,它不是唯一的,因此不应被 Disposed)。
  2. sign/verify//encrypt/decrypt 方法已向下移动到 RSA 基类(尽管签名略有不同,但更具前瞻性)。

关于c# - .NET Framework x509Certificate2 类,HasPrivateKey == true && PrivateKey == null?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36730596/

相关文章:

c# - 绑定(bind)重定向

windows - 文件/目录路径应如下所示 - Powershell 输出

Java/Erlang : Diffie Hellman Key Exchange not Working

c# - 强制加载 WPF 视觉对象的适当方式

c# - VS 2019 中的 CreatePkgDef 异常

c# - 如何在 C# 中返回引用?

powershell - 如何在 Powershell 中使用 select-string 进行多管道

powershell - 使用产品 ID 生成产品 URL

ssl - 更新 SSL 证书的 PKI 最佳实践

c# - 如何使用makecert创建WCF接受的X509证书