web-dev-qa-db-fra.com

Comment créer un X509Certificate2 valide et auto-signé par programme, sans chargement à partir d'un fichier dans .NET Core

Ce que je fais actuellement, c'est que j'utilise OpenSSL pour générer un fichier PFX. Cela provoque une dépendance indésirable, en particulier pour les utilisateurs de Windows. J'ai donc trouvé quelques exemples sur la façon de créer votre propre certificat à l'aide de BouncyCastle, mais cette bibliothèque n'est pas compatible .NET Core (ou je n'ai pas trouvé le package compatible).

Alors, est-il possible de créer votre propre certificat X509 auto-signé en utilisant uniquement le noyau .NET pour éviter la dépendance à OpenSSL (ou à tout autre outil externe générateur de certificat)?

EDIT: Il a été suggéré par quelqu'un (éditeur?) Que cette SO question Comment créer un un certificat auto-signé utilisant C #? fournit une réponse. Malheureusement, cela n'a rien à voir avec .NET Core. La réponse acceptée commence par This implementation uses the CX509CertificateRequestCertificate COM object (and friends - MSDN doc) from certenroll.dll to create a self signed certificate request and sign it, qui n'est évidemment PAS .NET Core .. En fait, aucune des réponses n'est compatible avec .NET Core.

23
Wapac

J'ai trouvé cet autre SO question qui m'a mis sur la bonne voie. L'API de certificats a été ajoutée à .Net Core sur la version 2.0. J'ai une fonction comme la suivante pour créer des certificats auto-signés que j'importe par la suite dans Mon magasin pour les utiliser sur IIS.

    private X509Certificate2 buildSelfSignedServerCertificate()
    {
        SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder();
        sanBuilder.AddIpAddress(IPAddress.Loopback);
        sanBuilder.AddIpAddress(IPAddress.IPv6Loopback);
        sanBuilder.AddDnsName("localhost");
        sanBuilder.AddDnsName(Environment.MachineName);

        X500DistinguishedName distinguishedName = new X500DistinguishedName($"CN={CertificateName}");

        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 certificate= request.CreateSelfSigned(new DateTimeOffset(DateTime.UtcNow.AddDays(-1)), new DateTimeOffset(DateTime.UtcNow.AddDays(3650)));
            certificate.FriendlyName = CertificateName;

            return new X509Certificate2(certificate.Export(X509ContentType.Pfx, "WeNeedASaf3rPassword"), "WeNeedASaf3rPassword", X509KeyStorageFlags.MachineKeySet);
        }
    }

Si vous voulez le pfx, la fonction Exporter sur X509Certificate2 devrait faire l'affaire. Il renvoie un tableau d'octets avec les données pfx brutes.

25