从.Net 4.7.2(.Net Standard 2.0)开始,可以仅使用C#/。Net创建自签名证书和证书签名请求,请参见MS Documentation。
虽然可以直接创建一个自签名证书来声明HasPrivateKey
(您只需致电CreateSelfSigned(notBefore, notAfter)
),但是我很难弄清楚如何获得私钥一般而言,例如如果我要创建由CA签名的证书,然后要将证书作为PFX文件持久保存,或者要将私钥保存在.PEM
文件中,或者要将其与证书一起存储在MS证书存储中,私钥,或者当我只想在内存中同时声明HasPrivateKey
时。
我所拥有的是一个“ RSAParameters”实例,该实例拥有相关的私人信息,但是我无法弄清楚如何(轻松地)将其用于相关目的(创建PFX文件或PEM文件或MS证书存储条目),而不必通读所有相关RFC并自己编写程序。 (该RSAParameter实例包含D
,Exponent
和Modulus
,因此我可以尝试将它们修补在一起(希望在this answer的帮助下),但我希望的C#方法将为我执行这些任务(目前我还找不到)。
当然,我们的想法是单独使用.Net功能。
关于如何实现这一目标的每条提示都值得赞赏。
答案 0 :(得分:1)
如果只有Modulus
,Exponent
和D
,则必须首先恢复CRT参数(P
,Q
,{{1} },DP
,DQ
)。
与其他问题一样,您主要缺少InverseQ
扩展方法和cert.CopyWithPrivateKey(key)
:
如果我想创建由CA签名的证书,然后想将该证书作为PFX文件持久保存
rsa.ImportParameters(RSAParameters)
或想将私钥保留在.PEM文件中
.NET Core 3.0每日内部版本中提供了此版本:
using (RSA rsa = RSA.Create())
{
rsa.ImportParameters(rsaParameters);
using (X509Certificate2 caSigned = GetCASignedCert(rsa))
using (X509Certificate2 withKey = caSigned.CopyWithPrivateKey(rsa))
{
File.WriteAllBytes("some.pfx", withKey.Export(X509ContentType.Pkcs12, "and a password"));
}
}
PKCS#8和加密的PKCS#8也可用。
在现有版本上,这需要使用RSAParameters和ITU-T X.690 DER编码器。
或要将其与私钥一起存储在MS证书存储中
RSAParameters rsaParameters = default(RSAParameters);
using (StreamWriter writer = new StreamWriter("rsa.key"))
using (RSA rsa = RSA.Create())
{
rsa.ImportParameters(rsaParameters);
writer.WriteLine("-----BEGIN RSA PRIVATE KEY-----");
writer.WriteLine(
Convert.ToBase64String(
rsa.ExportRSAPrivateKey(),
Base64FormattingOptions.InsertLineBreaks));
writer.WriteLine("-----END RSA PRIVATE KEY-----");
}
或者当我只想在内存中同时声明HasPrivateKey时。
using (RSA rsa = RSA.Create())
{
rsa.ImportParameters(rsaParameters);
using (X509Certificate2 caSigned = GetCASignedCert(rsa))
using (X509Certificate2 withKey = caSigned.CopyWithPrivateKey(rsa))
using (X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser))
{
X509Certificate2 persisted = new X509Certificate2(
withKey.Export(X509ContentType.Pkcs12, ""),
"",
X509KeyStorageFlags.PersistKeySet);
using (persisted)
{
store.Open(OpenFlags.ReadWrite);
store.Add(persisted);
}
}
}
答案 1 :(得分:0)
例如,如果您正在使用USB密钥之类的证书硬件安全模块(HSM),则不可能“获取”私有密钥,因为HSM仅提供使用私有密钥的接口。这是出于安全性考虑,因为一旦私钥在文件或内存中,它就有可能由第三方获得。
.NET历来没有提供足够灵活的界面,尽管它正在改进。因此,许多软件供应商都使用更完整和维护得更好的Bouncy Castle API(http://www.bouncycastle.org/csharp/),您会在网上找到很多文档。通常,如果.NET无法做到这一点,那么充气城堡就可以了。具有讽刺意味的是,HSM需要.NET加密访问,这是Windows上的私钥功能,但是您通常会以某种方式对其进行封装。
通常,使用加密API的学习曲线非常陡峭,如果没有想要编写的代码示例,您不太可能会获得很多帮助。