首页 > 解决方案 > 如何向 CertificateRequest 提供 X509KeyStorageFlags

问题描述

可以在 X509Certificate2 构造函数中指定 X509KeyStorageFlags,如下所示:

    var cert = new X509Certificate2(bytes, password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);

但就我而言,我使用 CertificateRequest 创建自签名证书,因此我没有证书构造函数:

var rsaKeyPair = RSA.Create();
var request = new CertificateRequest(
                      $"cn = {Environment.MachineName}",
                      rsaKeyPair,
                      HashAlgorithmName.SHA256,
                      RSASignaturePadding.Pkcs);

request.CertificateExtensions.Add(
                new X509KeyUsageExtension(X509KeyUsageFlags.KeyEncipherment |
                                          X509KeyUsageFlags.DigitalSignature, true));

var certificate = request.CreateSelfSigned(new DateTimeOffset(DateTime.UtcNow),
                                           new DateTimeOffset(DateTime.UtcNow.AddYears(2)));

有没有办法将 KeyStorageFags 添加到 request.CertificateExtension 或类似的东西?

标签: c#x509certificate2

解决方案


如何向 CertificateRequest 提供 X509KeyStorageFlags

CertificateRequest 对密钥存储一无所知。它所做的只是构建证书,然后调用cert.CopyWithPrivateKey(privateKey).

移动目标:

如何向 CopyWithPrivateKey 提供 X509KeyStorageFlags

CopyWithPrivateKey 复制当前状态的密钥。临时密钥保持短暂。持久键保持持久。

移动目标:

如何向 RSA.Create() 提供 X509KeyStorageFlags

RSA.Create() 总是创建临时密钥,它根本不理解密钥存储。您必须使用理解持久性的特定 RSA 实现——但这会将您锁定在 Windows 中(当然,您的调用代码可能因操作系统而异)。

RSA rsaKeyPair = BuildMachinePersistedKeyPair(2048);

...

private static RSA BuildMachinePersistedKeyPair(int keySize)
{
    CngKeyCreationParameters creationParameters = new CngKeyCreationParameters()
    {
        ExportPolicy = CngExportPolicies.Exportable,
        Provider = CngProvider.MicrosoftSoftwareKeyStorageProvider,
        KeyCreationOptions =
            CngKeyCreationOptions.OverwriteExistingKey |
            CngKeyCreationOptions.MachineKey,
    };

    CngProperty keySizeProperty = new CngProperty(
        KeyPropertyName.Length,
        BitConverter.GetBytes(keySize),
        CngPropertyOptions.None);

    creationParameters.Parameters.Add(keySizeProperty);

    using (CngKey cngKey = CngKey.Create(CngAlgorithm.Rsa, Guid.NewGuid().ToString(), creationParameters))
    {
        return new RSACng(cngKey);
    }
}

有没有更简单的方法?

当然,只需导出/导入临时的。

X509Certificate2 certificate;

using (X509Certificate2 ephemeral = request.CreateSelfSigned(...))
{
    certificate = new X509Certificate2(
        ephemeral.Export(X509ContentType.Pkcs12),
        string.Empty,
        X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
}

推荐阅读