繁体   English   中英

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

[英].NET Framework x509Certificate2 Class, HasPrivateKey == true && PrivateKey == null?

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

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

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

$my_cert | fl *的输出 $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属性应该随时可用,但显然我错过了一些东西。

我在这里读过类似的问题,例如x509certificate2中的Empty PrivateKey ,但似乎没有解决我的问题。 我还阅读了Paul Stovell 在.NET中使用X.509证书的八个技巧 ,这非常具有启发性,但最终没有帮助。 它确实帮助我验证私钥是否存在于正确的位置,据我所知,x509Certificate2类引用了正确的权限:

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

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

编辑:

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对象方便地引用私钥? 我如何获得访问权限?

这可能表示以下之一:

1)私有密钥存储在其中是不好的.NET支持和不支持的密钥存储提供程序(而不是传统的加密服务提供商) PrivateKey的财产X509Certificate2类的。 您可以通过运行以下命令来检查:

certutil -user -store my "<CertSerialNumber>"

2)私钥丢失。

HasPrivateKey财产并不一定反映真实的画面和可True不存在的键或False的现有密钥。 运行上面的certutil命令以确保是否显示密钥。

如果显示私钥,但绑定被破坏,您可以尝试通过运行以下命令来恢复绑定:

certutil -user -repairstore my "<CertSerialNumber>"

您的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 //加密/解密方法已经向下移动到RSA基类(具有略微不同,更具前瞻性的签名的albiet)。

我解决了这个问题。

出于某种原因,.NET框架无法从文件导入私有密钥,但是,它可以从导入内置Windows应用商店,这是因为专用密钥方法仅支持RSA和DSA密钥是按照微软规格 :阅读笔记在“备注”部分下。

无论如何,要获取PrivateKey对象以返回密钥信息,您需要执行以下操作:

1)双击将P12文件导入Windows密钥库。 2)当提示“当前用户”时选择“导入”3)确保选择“使密钥可导出”,

如果此选项不可用,则您的证书没有私钥

4)选择“自动放入商店”

5)编写以下代码以检索您的证书:

Dim CertDataInfo As System.Security.Cryptography.X509Certificates.X509Certificate2 
Dim Store As New System.Security.Cryptography.X509Certificates.X509Store("MY", Security.Cryptography.X509Certificates.StoreLocation.CurrentUser)

Store.Open(Security.Cryptography.X509Certificates.OpenFlags.ReadOnly)
Console.writeline (Store.Certificates.Count)

For I = 0 To Store.Certificates.Count - 1
 If Store.Certificates.Item(I).FriendlyName = "Heider Sati's Cert(48F57XTHVE)" Then
  CertDataInfo = Store.Certificates.Item(I)
 End If

 Console.writeline ("Cert: " & Store.Certificates.Item(I).FriendlyName)

Next
Store.Close()

If CertDataInfo.PrivateKey Is Nothing Then
 MsgBox("NULL")
Else
 MsgBox("YES")
End If

6)运行代码,如果你得到YES,那么私钥不是NULL(或NOTHING),这就是你要找的东西。

如果直接从文件加载相同的证书,私钥永远是NOTHING / NULL,但HasPrivateKey会说YES,这意味着(我知道有一个关键,不过不失,我不知道该怎么理解当您将其导入Windows商店时,Windows会将其转换为.NET兼容格式。

我希望这有帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM