如何在 C#/.net 中保留 RSAParameter 的私钥
How to persist private key of RSAParameter in C#/.net
从 .Net 4.7.2(.Net Standard 2.0)开始,可以仅使用 C#/.Net 创建自签名证书和证书签名请求,请参阅 MS Documentation。
虽然创建一个声明 HasPrivateKey
的自签名证书很简单(您只需调用 CreateSelfSigned(notBefore, notAfter)
),但我很难弄清楚如何掌握一般的私钥,例如如果我想创建一个由 CA 签名的证书,然后想将证书保存为 PFX 文件,或者想将私钥保存在 .PEM
文件中,或者想将它与私钥,或者当我只想在内存中并断言 HasPrivateKey
.
我拥有的是一个 'RSAParameters' 实例,它拥有相关的私人信息,但我没有弄清楚如何(轻松地)将其用于相关目的(创建 PFX 文件或 PEM 文件或 MS 证书存储条目),而无需通读所有相关的 RFC 并自行编写程序。 (该 RSAParameter 实例包含 D
、Exponent
和 Modulus
,因此我可以尝试将其修补在一起(希望在 this answer 的帮助下),但我希望对于一个 C# 方法,它将为我执行这些任务(我现在找不到)。
当然,我们的想法也是单独使用 .Net 功能来做到这一点。
感谢您提供有关如何实现此目标的所有提示。
如果您使用的是证书硬件安全模块 (HSM),例如 USB 密钥,则无法 "get" 私钥,因为 HSM 仅提供使用私钥的接口钥匙。这是为了安全起见,因为一旦私钥在文件或内存中,第三方就有可能获得它。
此外,从历史上看,.NET 没有提供足够灵活的界面,尽管它正在改进。由于许多软件供应商使用更完整且维护良好的 Bouncy Castle API (http://www.bouncycastle.org/csharp/),您会在网上找到大量文档。一般来说,如果 .NET 做不到 - 充气城堡会。具有讽刺意味的是,HSM 需要 .NET 加密访问它在 windows 上的私钥功能,但您通常会以某种方式封装它。
一般来说,使用加密 APIs 是一个陡峭的学习曲线,如果没有您想要的代码示例,您不太可能获得很多帮助。
如果您只有 Modulus
、Exponent
和 D
,您首先必须恢复 CRT 参数(P
、Q
、DP
, DQ
, InverseQ
).
作为您的其他问题,您主要缺少 cert.CopyWithPrivateKey(key)
扩展方法和 rsa.ImportParameters(RSAParameters)
:
if I want to create a certificate signed by a CA and then want to persist the certificate as a PFX file
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"));
}
}
or want to persist the private key in a .PEM file
这个在 .NET Core 3.0 每日构建中可用:
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-----");
}
PKCS#8 和加密的 PKCS#8 也可用。
在现有版本中,这需要使用 RSAParameters 和 ITU-T X.690 DER 编码器。
or want to store it in the MS certificate store together with the private key
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);
}
}
}
or when I just want to have in memory and also assert HasPrivateKey.
using (RSA rsa = RSA.Create())
{
rsa.ImportParameters(rsaParameters);
using (X509Certificate2 caSigned = GetCASignedCert(rsa))
{
// Yes, this value can outlive both usings
return caSigned.CopyWithPrivateKey(rsa);
}
}
从 .Net 4.7.2(.Net Standard 2.0)开始,可以仅使用 C#/.Net 创建自签名证书和证书签名请求,请参阅 MS Documentation。
虽然创建一个声明 HasPrivateKey
的自签名证书很简单(您只需调用 CreateSelfSigned(notBefore, notAfter)
),但我很难弄清楚如何掌握一般的私钥,例如如果我想创建一个由 CA 签名的证书,然后想将证书保存为 PFX 文件,或者想将私钥保存在 .PEM
文件中,或者想将它与私钥,或者当我只想在内存中并断言 HasPrivateKey
.
我拥有的是一个 'RSAParameters' 实例,它拥有相关的私人信息,但我没有弄清楚如何(轻松地)将其用于相关目的(创建 PFX 文件或 PEM 文件或 MS 证书存储条目),而无需通读所有相关的 RFC 并自行编写程序。 (该 RSAParameter 实例包含 D
、Exponent
和 Modulus
,因此我可以尝试将其修补在一起(希望在 this answer 的帮助下),但我希望对于一个 C# 方法,它将为我执行这些任务(我现在找不到)。
当然,我们的想法也是单独使用 .Net 功能来做到这一点。
感谢您提供有关如何实现此目标的所有提示。
如果您使用的是证书硬件安全模块 (HSM),例如 USB 密钥,则无法 "get" 私钥,因为 HSM 仅提供使用私钥的接口钥匙。这是为了安全起见,因为一旦私钥在文件或内存中,第三方就有可能获得它。
此外,从历史上看,.NET 没有提供足够灵活的界面,尽管它正在改进。由于许多软件供应商使用更完整且维护良好的 Bouncy Castle API (http://www.bouncycastle.org/csharp/),您会在网上找到大量文档。一般来说,如果 .NET 做不到 - 充气城堡会。具有讽刺意味的是,HSM 需要 .NET 加密访问它在 windows 上的私钥功能,但您通常会以某种方式封装它。
一般来说,使用加密 APIs 是一个陡峭的学习曲线,如果没有您想要的代码示例,您不太可能获得很多帮助。
如果您只有 Modulus
、Exponent
和 D
,您首先必须恢复 CRT 参数(P
、Q
、DP
, DQ
, InverseQ
).
作为您的其他问题,您主要缺少 cert.CopyWithPrivateKey(key)
扩展方法和 rsa.ImportParameters(RSAParameters)
:
if I want to create a certificate signed by a CA and then want to persist the certificate as a PFX file
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"));
}
}
or want to persist the private key in a .PEM file
这个在 .NET Core 3.0 每日构建中可用:
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-----");
}
PKCS#8 和加密的 PKCS#8 也可用。
在现有版本中,这需要使用 RSAParameters 和 ITU-T X.690 DER 编码器。
or want to store it in the MS certificate store together with the private key
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);
}
}
}
or when I just want to have in memory and also assert HasPrivateKey.
using (RSA rsa = RSA.Create())
{
rsa.ImportParameters(rsaParameters);
using (X509Certificate2 caSigned = GetCASignedCert(rsa))
{
// Yes, this value can outlive both usings
return caSigned.CopyWithPrivateKey(rsa);
}
}