即将发布的 .NET Core 2.0 在此处添加了新的类来提供帮助。虽然我知道“powershell 可以”或“有一个版本的 powershell 可以”与 .NET Core 一起工作,但我不知道如何,所以这个答案可能需要一个适配器。
给定signingCert
一个 X509Certificate2 实例,它HasPrivateKey==true
:
private static X509Certificate2 CreateNewCertificate(
X509Certificate2 signingCert,
int newRsaKeySize,
IEnumerable<string> sanDnsEntries)
{
var sanBuilder = new SubjectAlternativeNameBuilder();
string primaryDnsName = null;
foreach (string dnsEntry in sanDnsEntries)
{
// Let's just use the first one as the subject.
primaryDnsName = primaryDnsName ?? dnsEntry;
sanBuilder.AddDnsName(dnsEntry);
}
// 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={primaryDnsName}, O=Et OU=Cetera",
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());
// Serial number.
// It needs to be unique per issuer.
// CA/Browser forum rules say 64 or more bits must come from a CSPRNG.
// RFC 3280 says not to use more than 20 bytes.
// Let's use 16 (two C# `long`s)
byte[] serialNumber = new byte[16];
using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
{
rng.GetBytes(serialNumber);
}
// If you care about monotonicity (and believe your clock is monotonic enough):
{
long ticks = DateTime.UtcNow.Ticks;
byte[] tickBytes = BitConverter.GetBytes(ticks);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(tickBytes);
}
Buffer.BlockCopy(tickBytes, 0, serialNumber, 0, tickBytes.Length);
}
DateTimeOffset now = DateTimeOffset.UtcNow;
return certRequest.Create(
signingCert,
now,
now.AddDays(90),
serialNumber);
}
}
API 文档