在没有外部库的情况下生成自签名证书
Generating self-signed certificate without external libraries
我很想知道是否有一种创建自签名证书的简单方法可与下面的 New-SelfSignedCertificate
命令相媲美(例如,其他提供商也可以)。我只想使用不带 P/Invoke 的 .NET 库或 Bouncy Castle 等外部库或不从应用程序调用 PowerShell。
New-SelfSignedCertificate -DnsName $certificateName -CertStoreLocation $certificateStore -KeyExportPolicy Exportable -Provider "Microsoft Enhanced RSA and AES Cryptographic Provider" -NotAfter $certificateNotAfter
我想最简单的替代方法是调用 PowerShell 或使用诸如 Bouncy Castle 之类的 Nuget 库,如果这在没有外部工具的情况下是行不通的?虽然感觉如果我足够了解如何构建证书,就可以创建一个字节数组模板或类似的模板并在 X509Certificate2
构造函数中使用它。
看来需要
public X509Certificate2 GenerateCertificate(string fileName, string password, string subjectName, StoreName storeName, DateTime endDate, DateTime notAfter, string provider = "Microsoft Enhanced RSA and AES Cryptographic Provider")
{
//Could provider be taken from
var newCertificate = new X509Certificate2(fileName, password, X509KeyStorageFlags.Exportable);
/*
# The following creates a self-signed certificate with one year of running time.
$currentDate = Get-Date
$certificateEndDate = $currentDate.AddYears(1)
$certificateNotAfter = $certificateEndDate.AddYears(1)
$certificateName = "https://www.test.com/test"
$certificateStore = "Cert:\LocalMachine\My"
New-SelfSignedCertificate -DnsName $certificateName -CertStoreLocation $certificateStore -KeyExportPolicy Exportable -Provider "Microsoft Enhanced RSA and AES Cryptographic Provider" -NotAfter $certificateNotAfter
*/
}
我找到了几个选项:
一个博客postCreating Authority-Signed and Self-Signed Certificates in .NET by Steve Syfuhs and another SO post using Mono extensions, Mono.Security won't set multiple KeyUsages。除了已经讨论过的选项外,还有 "something like this".
在任何已发布的 .NET 版本中都无法创建证书。
.NET Core 2.0 (尚未发布,但应该很快)具有 并且 .NET Framework 4.7.2 已通过 CertificateRequest 添加了此功能( API 可以执行自签名证书、链签名证书或 PKCS#10 certificate/certification 签名请求)。
PowerShell 命令结合了三件事:
- 关键存储参数(CSP)
- 证书创建
- 证书存储(要将证书添加到的存储)
创建一个“简单”的自签名证书,用于本地主机上的 TLS 服务器身份验证:
X509Certificate2 certificate = null;
var sanBuilder = new SubjectAlternativeNameBuilder();
sanBuilder.AddDnsName("localhost");
// New .NET Core Create(int) method. Or use
// rsa = RSA.Create(), rsa.KeySize = newRsaKeySize,
// or (on .NET Framework) new RSACng(newRsaKeySize)
using (RSA rsa = RSA.Create(newRsaKeySize))
{
var certRequest = new CertificateRequest(
$"CN=localhost",
rsa,
HashAlgorithmName.SHA256,
RSASignaturePadding.Pkcs1);
// Explicitly not a CA.
certRequest.CertificateExtensions.Add(
new X509BasicConstraintsExtension(false, false, 0, false));
certRequest.CertificateExtensions.Add(
new X509KeyUsageExtension(
X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.KeyEncipherment,
true));
// TLS Server EKU
certRequest.CertificateExtensions.Add(
new X509EnhancedKeyUsageExtension(
new OidCollection
{
new Oid("1.3.6.1.5.5.7.3.1"),
},
false));
// Add the SubjectAlternativeName extension
certRequest.CertificateExtensions.Add(sanBuilder.Build());
DateTimeOffset now = DateTimeOffset.UtcNow;
certificate = certRequest.CreateSelfSigned(now, now.AddDays(365.25));
}
此创建的证书具有临时私钥 -- 当前未写入磁盘。如果您不关心它使用的密钥存储提供程序,那么此时您最好的选择是将证书(和私钥)导出为 PFX/PKCS#12,然后使用 [=13= 重新导入它](和 Exportable
,因为您需要),并将导入的副本添加到您选择的 X509Store。
如果您关心密钥存储提供程序(在您的情况下,是 CAPI CSP),或者您想避免 export/import,您可以使用预先保留的密钥创建它。所以你会用
替换 RSA.Create(newRsaKeySize)
CAPI:
var cspParameters = new CspParameters(
/* PROV_RSA_AES */ 24,
"Microsoft Enhanced RSA and AES Cryptographic Provider",
Guid.NewGuid().ToString());
using (RSA rsa = new RSACryptoServiceProvider(newRsaKeySize, cspParameters))
压缩天然气:
var keyParams = new CngKeyCreationParameters();
keyParams.Parameters.Add(
new CngProperty(
"Length",
BitConverter.GetBytes(newRsaKeySize),
CngPropertyOptions.Persist));
using (CngKey rsaKey = CngKey.Create(CngAlgorithm.RSA, Guid.NewGuid().ToString(), keyParams)
using (RSA rsa = new RSACng(rsaKey))
然后以通常的方式将其添加到打开的 X509Store 实例中。
it feels like that if I knew enough how to construct certificates, it'd be possible to create a byte array template or such and use that in the X509Certificate2 constructor.
没错。但这有点棘手。您需要学习 ASN.1(ITU-T X.680), DER (ITU-T X.690) and X.509 (either RFC 5280 or ITU-T X.509). If you wanted to create the certificate mated with the private key you'd then need to learn PFX/PKCS#12 (RFC 7292,但仅限于某些较旧的选项,除非您仅使用 Win10)并且它也具有大量先决条件知识。
我认为这些都是值得学习的有趣的东西,也是值得了解的好东西...但是当我开始在白板上涂鸦 DER 时,我的同事们用奇怪的眼神看着我,所以我可能并不代表普通开发人员对“有趣”的看法。
我很想知道是否有一种创建自签名证书的简单方法可与下面的 New-SelfSignedCertificate
命令相媲美(例如,其他提供商也可以)。我只想使用不带 P/Invoke 的 .NET 库或 Bouncy Castle 等外部库或不从应用程序调用 PowerShell。
New-SelfSignedCertificate -DnsName $certificateName -CertStoreLocation $certificateStore -KeyExportPolicy Exportable -Provider "Microsoft Enhanced RSA and AES Cryptographic Provider" -NotAfter $certificateNotAfter
我想最简单的替代方法是调用 PowerShell 或使用诸如 Bouncy Castle 之类的 Nuget 库,如果这在没有外部工具的情况下是行不通的?虽然感觉如果我足够了解如何构建证书,就可以创建一个字节数组模板或类似的模板并在 X509Certificate2
构造函数中使用它。
看来需要
public X509Certificate2 GenerateCertificate(string fileName, string password, string subjectName, StoreName storeName, DateTime endDate, DateTime notAfter, string provider = "Microsoft Enhanced RSA and AES Cryptographic Provider")
{
//Could provider be taken from
var newCertificate = new X509Certificate2(fileName, password, X509KeyStorageFlags.Exportable);
/*
# The following creates a self-signed certificate with one year of running time.
$currentDate = Get-Date
$certificateEndDate = $currentDate.AddYears(1)
$certificateNotAfter = $certificateEndDate.AddYears(1)
$certificateName = "https://www.test.com/test"
$certificateStore = "Cert:\LocalMachine\My"
New-SelfSignedCertificate -DnsName $certificateName -CertStoreLocation $certificateStore -KeyExportPolicy Exportable -Provider "Microsoft Enhanced RSA and AES Cryptographic Provider" -NotAfter $certificateNotAfter
*/
}
我找到了几个选项: 一个博客postCreating Authority-Signed and Self-Signed Certificates in .NET by Steve Syfuhs and another SO post using Mono extensions, Mono.Security won't set multiple KeyUsages。除了已经讨论过的选项外,还有 "something like this".
在任何已发布的 .NET 版本中都无法创建证书。
.NET Core 2.0 (尚未发布,但应该很快)具有 并且 .NET Framework 4.7.2 已通过 CertificateRequest 添加了此功能( API 可以执行自签名证书、链签名证书或 PKCS#10 certificate/certification 签名请求)。
PowerShell 命令结合了三件事:
- 关键存储参数(CSP)
- 证书创建
- 证书存储(要将证书添加到的存储)
创建一个“简单”的自签名证书,用于本地主机上的 TLS 服务器身份验证:
X509Certificate2 certificate = null;
var sanBuilder = new SubjectAlternativeNameBuilder();
sanBuilder.AddDnsName("localhost");
// New .NET Core Create(int) method. Or use
// rsa = RSA.Create(), rsa.KeySize = newRsaKeySize,
// or (on .NET Framework) new RSACng(newRsaKeySize)
using (RSA rsa = RSA.Create(newRsaKeySize))
{
var certRequest = new CertificateRequest(
$"CN=localhost",
rsa,
HashAlgorithmName.SHA256,
RSASignaturePadding.Pkcs1);
// Explicitly not a CA.
certRequest.CertificateExtensions.Add(
new X509BasicConstraintsExtension(false, false, 0, false));
certRequest.CertificateExtensions.Add(
new X509KeyUsageExtension(
X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.KeyEncipherment,
true));
// TLS Server EKU
certRequest.CertificateExtensions.Add(
new X509EnhancedKeyUsageExtension(
new OidCollection
{
new Oid("1.3.6.1.5.5.7.3.1"),
},
false));
// Add the SubjectAlternativeName extension
certRequest.CertificateExtensions.Add(sanBuilder.Build());
DateTimeOffset now = DateTimeOffset.UtcNow;
certificate = certRequest.CreateSelfSigned(now, now.AddDays(365.25));
}
此创建的证书具有临时私钥 -- 当前未写入磁盘。如果您不关心它使用的密钥存储提供程序,那么此时您最好的选择是将证书(和私钥)导出为 PFX/PKCS#12,然后使用 [=13= 重新导入它](和 Exportable
,因为您需要),并将导入的副本添加到您选择的 X509Store。
如果您关心密钥存储提供程序(在您的情况下,是 CAPI CSP),或者您想避免 export/import,您可以使用预先保留的密钥创建它。所以你会用
替换RSA.Create(newRsaKeySize)
CAPI:
var cspParameters = new CspParameters(
/* PROV_RSA_AES */ 24,
"Microsoft Enhanced RSA and AES Cryptographic Provider",
Guid.NewGuid().ToString());
using (RSA rsa = new RSACryptoServiceProvider(newRsaKeySize, cspParameters))
压缩天然气:
var keyParams = new CngKeyCreationParameters();
keyParams.Parameters.Add(
new CngProperty(
"Length",
BitConverter.GetBytes(newRsaKeySize),
CngPropertyOptions.Persist));
using (CngKey rsaKey = CngKey.Create(CngAlgorithm.RSA, Guid.NewGuid().ToString(), keyParams)
using (RSA rsa = new RSACng(rsaKey))
然后以通常的方式将其添加到打开的 X509Store 实例中。
it feels like that if I knew enough how to construct certificates, it'd be possible to create a byte array template or such and use that in the X509Certificate2 constructor.
没错。但这有点棘手。您需要学习 ASN.1(ITU-T X.680), DER (ITU-T X.690) and X.509 (either RFC 5280 or ITU-T X.509). If you wanted to create the certificate mated with the private key you'd then need to learn PFX/PKCS#12 (RFC 7292,但仅限于某些较旧的选项,除非您仅使用 Win10)并且它也具有大量先决条件知识。
我认为这些都是值得学习的有趣的东西,也是值得了解的好东西...但是当我开始在白板上涂鸦 DER 时,我的同事们用奇怪的眼神看着我,所以我可能并不代表普通开发人员对“有趣”的看法。