.NET Framework x509Certificate2 Class,HasPrivateKey == true && PrivateKey == null?
.NET Framework x509Certificate2 Class, HasPrivateKey == true && PrivateKey == null?
我正在尝试使用 X509 证书,该证书最初是使用 MMC 的 "Certificates" 管理单元导入到 Windows 10 计算机上的 CurrentUser 密钥库中的。在 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 class 的 PrivateKey 属性 应该很容易获得,但显然我错过了一些东西。
我在这里读过类似的问题,例如 Paul Stovell 的 , but none seem to resolve my issue. I've also read Eight tips for working with X.509 certificates in .NET,很有启发性,但最终没有帮助。它确实帮助我验证私钥是否存在于正确的位置,据我所知,x509Certificate2 class:
引用了正确的权限
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.
我在这里缺少什么 "key" 信息?为什么不能方便地从 X509Certificate2 对象引用私钥?我如何获得访问权限?
这可能表示以下情况之一:
1) 私钥存储在密钥存储提供程序(而不是传统的加密服务提供程序)中,它不受 .NET 的支持,并且不受 PrivateKey
属性 of [=13] 的支持=] class 完全没有。您可以通过 运行 以下命令进行检查:
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 属性 return 不是 RSACryptoServiceProvider(或 DSACryptoServiceProvider)的东西的其他破坏性变化。如果您可以访问该方法(我不确定 PowerShell 使用的是哪个版本的框架),那么它将解决您的问题。
不过有两点需要注意:
- GetRSAPrivateKey return每次都是一个唯一的 Disposable 对象。完成后,您应该将其放入使用 statement/manually 调用 Dispose 中(与 cert.PrivateKey 相反,它不是唯一的,因此不应该被 Disposed)。
- sign/verify//encrypt/decrypt 方法已向下移动到 RSA 基础 class(尽管签名略有不同,更具前瞻性)。
我解决了问题。
出于某种原因,.NET framework 无法从文件中导入私钥,但是,它可以从内置的 windows 存储中导入,这是因为 PrivateKey 方法仅支持 RSA 和 DSA 密钥根据 Microsoft Spec:阅读 "Remarks" 部分下的注释。
总之,要获取return密钥信息的PrivateKey对象,您需要执行以下操作:
1) 通过双击将 P12 文件导入 Windows 密钥库。
2)Select"Import"时提示进入"Current User"
3) 确保你 select "Make Key Exportable",
if this option is not available then your certificate has no private
key
。
4) Select "Automatically place into store"
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 兼容格式。
希望对您有所帮助。
我正在尝试使用 X509 证书,该证书最初是使用 MMC 的 "Certificates" 管理单元导入到 Windows 10 计算机上的 CurrentUser 密钥库中的。在 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 class 的 PrivateKey 属性 应该很容易获得,但显然我错过了一些东西。
我在这里读过类似的问题,例如 Paul Stovell 的
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.
我在这里缺少什么 "key" 信息?为什么不能方便地从 X509Certificate2 对象引用私钥?我如何获得访问权限?
这可能表示以下情况之一:
1) 私钥存储在密钥存储提供程序(而不是传统的加密服务提供程序)中,它不受 .NET 的支持,并且不受 PrivateKey
属性 of [=13] 的支持=] class 完全没有。您可以通过 运行 以下命令进行检查:
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 属性 return 不是 RSACryptoServiceProvider(或 DSACryptoServiceProvider)的东西的其他破坏性变化。如果您可以访问该方法(我不确定 PowerShell 使用的是哪个版本的框架),那么它将解决您的问题。
不过有两点需要注意:
- GetRSAPrivateKey return每次都是一个唯一的 Disposable 对象。完成后,您应该将其放入使用 statement/manually 调用 Dispose 中(与 cert.PrivateKey 相反,它不是唯一的,因此不应该被 Disposed)。
- sign/verify//encrypt/decrypt 方法已向下移动到 RSA 基础 class(尽管签名略有不同,更具前瞻性)。
我解决了问题。
出于某种原因,.NET framework 无法从文件中导入私钥,但是,它可以从内置的 windows 存储中导入,这是因为 PrivateKey 方法仅支持 RSA 和 DSA 密钥根据 Microsoft Spec:阅读 "Remarks" 部分下的注释。
总之,要获取return密钥信息的PrivateKey对象,您需要执行以下操作:
1) 通过双击将 P12 文件导入 Windows 密钥库。 2)Select"Import"时提示进入"Current User" 3) 确保你 select "Make Key Exportable",
if this option is not available then your certificate has no private key
。 4) Select "Automatically place into store"
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 兼容格式。
希望对您有所帮助。