给定一个新生成的可导出公钥/私钥对CngKey
和一个SecureString
,我需要进行哪些API调用才能创建一个包含使用密码保护的公钥/私钥内容的PFX文件?给定一个PFX文件和一个SecureString
密码,需要什么API调用才能将内容加载到CngKey
中?
基类库似乎没有提供这一点,但我更喜欢p/invoke,而不是依赖第三方库。我还想避免将解密的私钥存储在内存中,即使有一种方法(类似于SecureString
)可以在PFX和CngKey
之间保持其安全。
当我试图理解这些概念时,我能找到的所有例子都涉及自签名证书。这不是证书,只是我想要密码保护的公共/私人blob。我不想将blob导入存储区,我想从PFX文件中使用它。
这是我自己所能做到的:
using (var key = CngKey.Create(CngAlgorithm.ECDsaP521, null, new CngKeyCreationParameters { ExportPolicy = CngExportPolicies.AllowExport, KeyUsage = CngKeyUsages.Signing }))
using (var algorithm = new ECDsaCng(key))
{
var container = new X509Certificate2();
container.PrivateKey = algorithm; // Exception: m_safeCertContext is an invalid handle
var pfxFileContents = container.Export(X509ContentType.Pkcs12, password);
using (var pfxFile = File.Create("text.pfx"))
pfxFile.Write(pfxFileContents, 0, pfxFileContents.Length);
}
在这种情况下,最好的解决方案是引用Security.Cryptography.dll。这个开源库是稳定的,如果我理解正确的话,可能已经合并到.NET Framework中;它背后的开发人员来自团队。
将CngKey
存储在受SecureString
保护的PFX流中:
// NB! X509Certificate2 does not implement IDisposable in .NET 4.5.2, but it does in 4.6.1.
using (var cert = key.CreateSelfSignedCertificate(new X509CertificateCreationParameters(new X500DistinguishedName("CN=Example Name"))
{
StartTime = DateTime.Now,
EndTime = DateTime.MaxValue,
TakeOwnershipOfKey = true,
SignatureAlgorithm = X509CertificateSignatureAlgorithm.ECDsaSha256 // Manually match your CngKey type (RSA/ECDSA)
}))
{
File.WriteAllBytes(pfxPath, cert.Export(X509ContentType.Pkcs12, pfxPassword));
}
从受SecureString
保护的PFX流加载CngKey
:
// NB! X509Certificate2 does not implement IDisposable in .NET 4.5.2, but it does in 4.6.1.
using (var cert = new X509Certificate2(pfxPath, pfxPassword))
return cert.GetCngPrivateKey();