将 IP 地址作为备用名称添加到证书

问题描述 投票:0回答:1

我想使用 C# 中的证书注册库创建一个自签名证书。

我正在尝试向证书添加备用主题名称。对于 DNS 和 URL,这工作正常,但如果我尝试使用 IP 地址,它会抛出“值未落入预期范围”异常。

代码如下:

CX509CertificateRequestCertificate certificate = new();
...
// Add alternate names
CX509ExtensionAlternativeNamesClass alternateNames = new();
CAlternativeNamesClass cAlternativeNames = new();
foreach (CertificateAlias alias in settings.Aliases)
{
    CAlternativeNameClass cAlternativeName = new();
    // alias.Name is "100.120.140.160" in my test case
    cAlternativeName.InitializeFromString(alias.Type.ToAlternativeNameType(), alias.Name);
    cAlternativeNames.Add(cAlternativeName);
}
alternateNames.InitializeEncode(cAlternativeNames);
certificate.X509Extensions.Add(alternateNames as CX509Extension);

certificate.Encode();
...

“settings.Aliases”只是我存储的所需备用名称的列表。 “CertificateAlias”仅包含备用名称的类型(通过枚举映射)和实际名称,这里没什么花哨的。

我也尝试过使用像这样的InitializeFromRawData的方法

cAlternativeName.InitializeFromRawData(AlternativeNameType.XCN_CERT_ALT_NAME_IP_ADDRESS, EncodingType.XCN_CRYPT_STRING_BASE64, Convert.ToBase64String(Encoding.UTF8.GetBytes("100.120.140.160")));
但随后它在证书备用名称详细信息中显示为 Base64,这是不正确的。

另外我刚刚尝试过

cAlternativeName.InitializeFromRawData(AlternativeNameType.XCN_CERT_ALT_NAME_IP_ADDRESS, EncodingType.XCN_CRYPT_STRING_BASE64, "100.120.140.160");
但这会引发“无效数据”异常。

此时我一无所知。我如何在此处包含 IP 地址?

编辑:此证书仅用于本地计算机。

编辑 2:我让它工作,我必须从 Base64 编码中排除 IP 地址点并使用 InitializeFromRawData 而不是 FromString 像这样:

List<byte> bytes = new();
string[] octets = alias.Name.Split('.');
for (int i = 0; i < octets.Length; i++)
    bytes.Add(byte.Parse(octets[i]));
cAlternativeName.InitializeFromRawData(AlternativeNameType.XCN_CERT_ALT_NAME_IP_ADDRESS, EncodingType.XCN_CRYPT_STRING_BASE64, Convert.ToBase64String(bytes.ToArray()));
c# ssl-certificate x509certificate
1个回答
1
投票

您可以尝试使用此方法生成带有 ip 主题备用名称的证书。

using System.Net;
using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;


string subjectName = "CN=localhost";
using (RSA rsa = RSA.Create(2048))
{

    CertificateRequest req = new CertificateRequest(
        subjectName,
        rsa,
        HashAlgorithmName.SHA256,
        RSASignaturePadding.Pkcs1);

    //add subject aulternative name
    var sanBuilder = new SubjectAlternativeNameBuilder();
    sanBuilder.AddIpAddress(IPAddress.Parse("101.101.101.101"));
    req.CertificateExtensions.Add(sanBuilder.Build());

    //generate certificate
    var certificate = req.CreateSelfSigned(DateTimeOffset.UtcNow.AddDays(-1),DateTimeOffset.UtcNow.AddYears(50));


    var exportableCertificate = new X509Certificate2(
        certificate.Export(X509ContentType.Cert),
        (string)null,
        X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet
        ).CopyWithPrivateKey(rsa);


    // Create password for certificate protection
    var passwordForCertificateProtection = new SecureString();

    foreach (var @char in "123")
    {
        passwordForCertificateProtection.AppendChar(@char);
    }

    // Export certificate to a file.
    File.WriteAllBytes(
        "test.pfx",
        exportableCertificate.Export(
            X509ContentType.Pfx,
            passwordForCertificateProtection
        )
    );
}

安装后

© www.soinside.com 2019 - 2024. All rights reserved.