Можно ли на лету генерировать SSL-сертификаты из корневого ЦС в C #? - PullRequest
0 голосов
/ 13 февраля 2019

Я настраиваю сервер под собственным корневым ЦС для генерации SSL-сертификатов на лету под .NET Core.

Я могу создавать самозаверяющие сертификаты, используя класс CertificateRequest.Однако эти сертификаты, очевидно, не доверяют клиентам с моим собственным корневым центром сертификации.Я использую метод CertificateRequest.CreateSelfSigned(), чтобы сделать это.Однако я не могу использовать свой корневой CA для подписи этих новых сертификатов.Использование метода CertificateRequest.Create() сгенерирует мой новый сертификат, но не предоставит закрытый ключ.

public static X509Certificate2 CreateSelfSignedCertificate(string domain)
{
    SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder();
    sanBuilder.AddDnsName(domain);

    X500DistinguishedName distinguishedName = new X500DistinguishedName($"CN=On-The-Fly Generated Cert");

    using (RSA rsa = RSA.Create(2048))
    {
        var request = new CertificateRequest(distinguishedName, rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

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


        request.CertificateExtensions.Add(
            new X509EnhancedKeyUsageExtension(
                new OidCollection { new Oid("1.3.6.1.5.5.7.3.1") }, false));

        request.CertificateExtensions.Add(sanBuilder.Build());

        var ca = new X509Certificate2(File.ReadAllBytes(@"E:\testing_ca_certificate.pfx"), "password"); //Open my root CA cert, generated in OpenSSL

        //Generates a cert, but does not provide a private key.
        var certificate = request.Create(ca, new DateTimeOffset(DateTime.UtcNow.AddDays(-1)), new DateTimeOffset(DateTime.UtcNow.AddDays(365)), new byte[] { 0, 1, 2, 3 }); 

        //Generates a usable cert, but is not under my root CA
        //var certificate = request.CreateSelfSigned(new DateTimeOffset(DateTime.UtcNow.AddDays(-1)), new DateTimeOffset(DateTime.UtcNow.AddDays(365)));

        return new X509Certificate2(certificate.Export(X509ContentType.Pfx, "password"), "password", X509KeyStorageFlags.DefaultKeySet);
    }

}

Используя метод CertificateRequest.Create(), я получу действительный сертификат без закрытого ключа.У меня должен быть этот закрытый ключ, чтобы я мог шифровать трафик SSL.

Ответы [ 2 ]

0 голосов
/ 29 апреля 2019

Используя метод CertificateRequest.Create(), я получаю действительный сертификат без закрытого ключа.

Реальные центры сертификации не должны иметь закрытый ключ CA и закрытый ключ, соответствующийсертификат должен быть создан в том же месте в то же время.Помимо того, что в настоящее время нет способа декодировать запрос на сертификацию (CSR), этот метод предполагает, что он используется с открытым ключом, предоставленным конструктору CertificateRequest.

После потока "ожидаемый""модель:

  • Клиент определяет необходимость нового сертификата
  • Клиент генерирует открытую / закрытую пару ключей
  • Клиент отправляет открытый ключ и другую необходимую информацию в ЦС (PKCS # 10 CertificationRequest или другим способом)
  • CA проверяет запрос
  • CA создает объект CertificateRequest с использованием открытого ключа клиента
  • CA создает сертификат с CertificateRequest.Create()
  • CA отправляет сертификат обратно клиенту (cert.RawData)
  • Клиент создает экземпляр X509Certificate2 экземпляр (только с открытым ключом)
  • Клиент использует CopyWithPrivateKey(расширение) метод, чтобы связать закрытый ключ с новым объектом сертификата.
  • Клиент делает то, что клиент хочет сейчас.

Итак, после

//Generates a cert, but does not provide a private key.
var certificate = request.Create(ca, new DateTimeOffset(DateTime.UtcNow.AddDays(-1)), new DateTimeOffset(DateTime.UtcNow.AddDays(365)), new byte[] { 0, 1, 2, 3 }); 

йовам следует добавить

certificate = certificate.CopyWithPrivateKey(rsa);

(Хотя на самом деле вы должны иметь объекты сертификата в операторах using, чтобы они удалялись, когда они больше не нужны, и в этом случае вам понадобится вторая переменная для храненияCERT-с-ключом)

0 голосов
/ 13 февраля 2019

Учитывая, что запрос сертификата был создан с использованием вашего экземпляра rsa, вы сможете экспортировать закрытый ключ из него.RSA.ToXmlString() позволяет экспортировать ключ в формат, который позже можно будет импортировать позже, используя RSA.FromXmlString().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...