web-dev-qa-db-fra.com

Générer et signer une demande de certificat à l'aide du framework .net pur

J'essaie d'utiliser du code .net pur pour créer une demande de certificat et créer un certificat à partir de la demande de certificat contre un certificat d'autorité de certification existant dont je dispose (soit dans le magasin de certificats Windows, soit dans un fichier distinct).

Je sais que j'ai les cours X509Certificate et X509Certificate2 disponible pour charger des certificats et accéder à leurs informations, mais je ne vois aucune classe ou fonctionnalité dans le System.Security.Cryptography espace de noms qui pourrait être utilisé pour créer une demande de certificat ou pour signer une telle demande de certificat pour créer un nouveau certificat signé.

Et bien que la documentation sur le System.Security.Cryptography.Pkcs namespace dit:

L'espace de noms System.Security.Cryptography.Pkcs fournit des éléments de programmation pour les normes de cryptographie à clé publique (PKCS), y compris des méthodes pour signer des données, échanger des clés, demander des certificats , cryptage et décryptage à clé publique et autres fonctions de sécurité.

Alors, comment puis-je créer une demande de certificat et signer cette demande pour créer un nouveau certificat X509 en utilisant uniquement des classes .net pures de System.Security.Cryptography?


Remarque:

  • Je ne veux pas utiliser d'exécutable externe comme openssl ou MakeCert
  • Je ne veux pas utiliser BouncyCastle
  • Je ne veux pas utiliser Windows API d'inscription des certificats
  • Je ne veux pas utiliser les fonctions natives de l'API Win32
17
NineBerry

Réponse courte: vous pouvez démarrer dans .NET Framework 4.7.2.

Cette fonctionnalité a été initialement ajoutée à .NET Core 2.0 sous la forme de la classe CertificateRequest , qui peut générer une demande de signature de certification PKCS # 10 ou un certificat de clé publique X.509 (auto-signé ou chaîné) .

Les classes de cette fonctionnalité ont été mises à disposition dans .NET Framework 4.7.2.

using (RSA parent = RSA.Create(4096))
using (RSA rsa = RSA.Create(2048))
{
    CertificateRequest parentReq = new CertificateRequest(
        "CN=Experimental Issuing Authority",
        parent,
        HashAlgorithmName.SHA256,
        RSASignaturePadding.Pkcs1);

    parentReq.CertificateExtensions.Add(
        new X509BasicConstraintsExtension(true, false, 0, true));

    parentReq.CertificateExtensions.Add(
        new X509SubjectKeyIdentifierExtension(parentReq.PublicKey, false));

    using (X509Certificate2 parentCert = parentReq.CreateSelfSigned(
        DateTimeOffset.UtcNow.AddDays(-45),
        DateTimeOffset.UtcNow.AddDays(365)))
    {
        CertificateRequest req = new CertificateRequest(
            "CN=Valid-Looking Timestamp Authority",
            rsa,
            HashAlgorithmName.SHA256,
            RSASignaturePadding.Pkcs1);

        req.CertificateExtensions.Add(
            new X509BasicConstraintsExtension(false, false, 0, false));

        req.CertificateExtensions.Add(
            new X509KeyUsageExtension(
                X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.NonRepudiation,
                false));

        req.CertificateExtensions.Add(
            new X509EnhancedKeyUsageExtension(
                new OidCollection
                {
                    new Oid("1.3.6.1.5.5.7.3.8")
                },
                true));

        req.CertificateExtensions.Add(
            new X509SubjectKeyIdentifierExtension(req.PublicKey, false));

        using (X509Certificate2 cert = req.Create(
            parentCert,
            DateTimeOffset.UtcNow.AddDays(-1),
            DateTimeOffset.UtcNow.AddDays(90),
            new byte[] { 1, 2, 3, 4 }))
        {
            // Do something with these certs, like export them to PFX,
            // or add them to an X509Store, or whatever.
        }
    }
}

Réponse plus longue si vous êtes bloqué sur des versions plus anciennes: Pour atteindre votre objectif sans ajouter de nouveaux P/Invokes, vous devez lire et comprendre les documents suivants:

  • UIT-T X.68 - 201508, le langage ASN.1
  • IETF RFC 528 ou ITU-T X.509 , les documents qui expliquent les champs des certificats X.509.
  • IETF RFC 2986 , explique la demande de signature de certification PKCS # 10
  • UIT-T X.69 , explique la famille de codage BER pour ASN.1 (y compris DER) qui vous indique comment lire et écrire des octets pour obtenir la signification sémantique de X.509/PKCS # 10.

Et puis vous pourriez écrire un écrivain/lecteur DER, et émettre simplement les octets pour ce que vous voulez.

37
bartonjs