web-dev-qa-db-ja.com

純粋な.net Frameworkを使用して証明書要求を生成して署名する

純粋な.netコードを使用して証明書要求を作成し、利用可能な既存のCA証明書に対して証明書要求から証明書を作成しようとしています(Windows証明書ストアまたは別のファイルとして)。

クラスX509CertificateおよびX509Certificate2を使用して証明書をロードし、それらの情報にアクセスできることは知っていますが、System.Security.Cryptography名前空間内にクラスまたは機能が表示されない証明書要求を作成するか、そのような証明書要求に署名して新しい署名済み証明書を作成するために使用されます。

そして、 System.Security.Cryptography.Pkcs名前空間に関するドキュメント には次のように書かれていますが:

System.Security.Cryptography.Pkcs名前空間は、データの署名、キーの交換、証明書の要求、公開キーの暗号化および復号化などの方法を含む、公開キー暗号化標準(PKCS)のプログラミング要素を提供します、およびその他のセキュリティ機能。

それでは、証明書リクエストを作成し、そのリクエストに署名して、System.Security.Cryptographyからの純粋な.netクラスのみを使用して新しいX509証明書を作成する方法を教えてください。


注意:

  • OpensslやMakeCertなどの外部実行可能ファイルを使用したくない
  • BouncyCastleを使いたくない
  • Windowsを使用したくありません Certificate Enrollment API
  • ネイティブのWin32 API関数を使用したくない
17
NineBerry

短い答え:.NET Framework 4.7.2から開始できます。

この機能は、元々 CertificateRequest クラスの形式で.NET Core 2.0に追加され、PKCS#10証明書署名要求またはX.509(自己署名またはチェーン)公開鍵証明書を作成できます。 。

その機能のクラスは、.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.
        }
    }
}

古いバージョンにこだわっている場合の長い回答:新しいP/Invokesを追加せずに目標を達成するには、次のドキュメントを読んで理解する必要があります。

  • ITU-T X.68 -201508、ASN.1言語
  • IETF RFC 528 またはITU-T X.509 、X.509証明書のフィールドを説明するドキュメント。
  • IETF RFC 2986 、PKCS#10証明書署名要求について説明します
  • ITU-T X.69 、ASN.1(DERを含む)のBERエンコーディングファミリについて説明します。このファミリは、X.509/PKCS#10からセマンティックな意味を実現するためのバイトの読み取りおよび書き込み方法を示します。

そして、DERライター/リーダーを作成し、必要なバイトを送信することができます。

37
bartonjs