«Сертификат X509 не имеет закрытого ключа» при создании самозаверяющего сертификата для Identity Server 4 - PullRequest
0 голосов
/ 27 ноября 2018

Вот что я пытаюсь достичь.Мы разрабатываем приложение для микросервисов в Kubernetes.Одним из микросервисов является экземпляр IdentityServer.Сначала я хочу проверить решение локально на Docker, чтобы убедиться, что оно работает.Для этого я хочу вставить сертификат в appsettings.json.В конце концов это значение будет заменено секретом Kubernetes.В моем классе запуска это, как я пытаюсь загрузить свой сертификат:

 services.AddIdentityServer()
         .AddSigningCredential(GetIdentityServerCertificate())
         .AddConfigurationStore(...

    private X509Certificate2 GetIdentityServerCertificate()
    {
        var clientSecret = Configuration["Certificate"];
        var pfxBytes = Convert.FromBase64String(clientSecret);
        var certificate = new X509Certificate2(pfxBytes);
        return certificate;
    }

Сертификат сгенерирован мной с помощью openssl:

openssl req –newkey rsa:2048 –nodes –keyout XXXXX.key –x509 –days 365 –out XXXXX.cer

openssl pkcs12 –export –in XXXX.cer –inkey XXXX.key –out XXXX.pfx

Затем я получаю сертификат с помощью:

openssl pkcs12 -in XXXX.pfx -info -nokeys

-----BEGIN CERTIFICATE-----
i take this content and paste into appconfig.json
-----END CERTIFICATE-----

Когда я отлаживаю его, результат: System.InvalidOperationException: 'Сертификат X509 не имеет закрытого ключа.'

1 Ответ

0 голосов
/ 05 декабря 2018

Вот пример, который работает в ядре .net:

Используйте инструмент openssl.Откройте терминал и введите следующие команды:

openssl genrsa -out private.pem 2048 
openssl rsa -in private.pem -outform PEM -pubout -out public.pem

Это приведет к созданию 2 файлов.

Есть еще одна вещь, прежде чем мы сможем использовать наши ключи RSA в приложении .NET Core.Нам нужно конвертировать их в XML.Используйте «Конвертер RSA PEM в XML».Это можно сделать здесь: Онлайн-конвертер RSA-ключей Перед копированием XML в файлы private-rsa-key.xml и public-rsa-key.xml отформатируйте их, используя: XML Formatter

Закрытый ключ требуется только для службы, ответственной за генерацию токена.Это нельзя использовать за пределами этого проекта.

Startup.cs:

public class Startup
{
    public IConfiguration Configuration { get; }
    private SigningCredentials _signingCredentials;

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        // other code
        services
                .AddIdentityServer()
                .AddSigningCredential(_signingCredentials)
                .AddInMemoryApiResources(_identityConfig.GetApiResources())
                .AddInMemoryClients(_identityConfig.GetClients());
        // other code
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseMvc();
        app.UseIdentityServer();
    }

    private void InitializeRsaKey()
    {
        try
        {
            RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(2048);
            var rsaParametersPrivate = RSAExtensions.RSAParametersFromXmlFile(Configuration.GetSection("JwtSettings:rsaPrivateKeyXml").Value);
            rsaProvider.ImportParameters(rsaParametersPrivate);
            var securityKey = new RsaSecurityKey(rsaProvider);
            _signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.RsaSha256);
        }
        catch(Exception ex)
        {
            throw new Exception("Identity Server RSA Key initialization failed. " + ex.ToString());
        }
    }
}

Класс RSAExtensions:

public static class RSAExtensions
{
    /// <summary>
    /// Gets RSA Parameters from XML file.
    /// </summary>
    /// <param name="xmlFilePath">The XML file path.</param>
    /// <returns>RSAParameters.</returns>
    /// <exception cref="Exception">Invalid XML RSA key.</exception>
    public static RSAParameters RSAParametersFromXmlFile(string xmlFilePath)
    {
        RSAParameters parameters = new RSAParameters();

        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.LoadXml(File.ReadAllText(xmlFilePath));

        if (xmlDoc.DocumentElement.Name.Equals("RSAKeyValue"))
        {
            foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes)
            {
                switch (node.Name)
                {
                    case "Modulus": parameters.Modulus = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
                    case "Exponent": parameters.Exponent = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
                    case "P": parameters.P = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
                    case "Q": parameters.Q = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
                    case "DP": parameters.DP = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
                    case "DQ": parameters.DQ = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
                    case "InverseQ": parameters.InverseQ = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
                    case "D": parameters.D = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
                }
            }
        }
        else
        {
            throw new Exception("Invalid XML RSA key.");
        }

        return parameters;
    }
}

В appsettings.json добавьте следующее:

"JwtSettings": {
    "rsaPrivateKeyXml": "RSAKeys/private-rsa-key.xml",
},

Я не знаю, можете ли вы сохранить сырой XML в appsettings.json.Если нет, то вы можете написать вспомогательный метод для преобразования pem в xml и сохранения исходного содержимого pem в переменной конфигурации.

Я нашел пример проекта в GitHub, который может помочь вам при конвертации: Rsa-Dotnet-Core

...