从PFX文件读取私钥

mar*_*sze 7 c# pfx x509certificate2 private-key

我知道,有很多关于此的文章,但我仍然找不到解决方案来解决这个问题。我已经在我的机器上使用openssl生成了一个PFX-文件,如下所示:

openssl x509 -req -days 365 -in "myReqest.csr" -signkey "myPrivateKey.pem" -out "myCertificate.crt"
openssl pkcs12 -export -out "myCertificate.pfx" -inkey "myPrivateKey.pem" -in "myCertificate.crt" -certfile "myCertificate.crt"
Run Code Online (Sandbox Code Playgroud)

在我的C#应用​​中,我这样访问私钥:

var cert = new X509Certificate2("myCertificate.pfx", "myPassword");
cert.HasPrivateKey; // This is always true!
cert.PrivateKey; // Works on my machine (only)
Run Code Online (Sandbox Code Playgroud)

这在我的机器上工作得很好,但是当我在另一台机器上运行相同的代码时,它抛出:“找不到密钥集”,即使HasPrivateKey返回了true!私钥不应该包含在* .pfx文件中吗?你能告诉我吗:

  1. 创建我时,openssl是否将证书/私钥以某种方式自动安装在我的计算机上?

  2. 如何从* .PFX文件(或从* .PEM文件)读取私钥?

StackTrace的异常:

at System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContaier)
at System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContaier, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle)
at System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair()
at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters parameters, Boolean useDefaultKeySize)
at System.Security.Cryptography.RSACryptoServiceProvider..ctor(CspParameters parameter)
at System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey()
Run Code Online (Sandbox Code Playgroud)

更新:

我发现,以下方法确实有效:

// on my machine
// read certificate from file (exportable!)
X509Certificate2 cert = new X509Certificate2("filename.pfx", "password", X509KeyStorageFlags.Exportable)
// sign data etc.
((RSACryptoServiceProvider)cert.PrivateKey).SignData(...
// export private key to XML-file
File.WriteAllText("filename.xml", cert.PrivateKey.ToXmlString(true));

// on the other machine
// create new RSA object
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
// import private key from xml
rsa.FromXmlString(File.ReadAllText("filename.xml"));
// verify data etc.
rsa.VerifyData(...
Run Code Online (Sandbox Code Playgroud)

但是,对我来说,这只是一种解决方法,我想以一种更常规/符合标准的方式来做!

mar*_*sze 5

看来,在 .NET 中没有直接的方法可以做到这一点。因此,我现在决定直接从证书存储加载证书:

X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
X509Certificate2Collection certificates = store.Certificates.Find(X509FindType.FindByThumbprint, CERTIFICATE_THUMB_PRINT, false);
if (certificates.Count == 0)
{
    // "Certificate not installed."
}
else
{
    certificate = certificates[0];
}
store.Close();
Run Code Online (Sandbox Code Playgroud)

当然,为此,必须在机器上安装。

我认为这是解决这个问题的一个很好的解决方案,因为它增加了额外的安全层(应用程序必须在安装了证书的计算机上运行,​​并且作为安装它的用户,文件本身也可以存放在其他安全的地方)。


Bog*_*dan 5

您必须像这样加载证书:

X509Certificate2 cert = new X509Certificate2("a.pfx", "password", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet)

这篇文章解释了为什么http://paulstovell.com/blog/x509certificate2