0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TLS通信したい (2) サーバー自己署名証明書

Last updated at Posted at 2025-08-28

1. はじめに

続きです。クライアントからClientHelloを受け取ったら、ServerHello をクライアントに返します。でもその際に「サーバー証明書」が必要になります。

自己署名証明書というものを作っていきます。「テスト用ならこれでいいんだけれども...」と何度もChatGPT君に言われてました。テストだから良いのです。

俗に「オレオレ証明書」と言われているものです。

pfx でエクスポートすると あとで使う時に非常に楽になるのでオプションで出すようにします。

2. サーバー自己署名証明書を作ろう

2-1. opensslで作る

これがたぶん一番楽です。

2-1-1.秘密鍵を作成

サーバーの秘密鍵を作ってserver.keyというファイル名で保存するようにします。

openssl genrsa -out server.key 2048

2-1-2.CSR(証明書署名要求)を作る

サーバーの秘密鍵からCSR(証明書署名要求)を作ります。
本来なら「サーバーの公開鍵で中身を作る」のですが、公開鍵は秘密鍵から作れるので、秘密鍵さえ判ればいいのです。

CN(CommonName) は後でクライアントがサーバー認証をするときに使う(可能性がある)ので、ドメイン名を入れます。

openssl req -new -key server.key -out server.csr -subj "/CN=www.mydomain.com"

他のパラメータもこんな感じで追加できます。

openssl req -new -key server.key -out server.csr -subj "/C=JP/ST=Tokyo/L=Chiyoda/O=Example Inc./CN=www.maydomain.com"

使わないなら単純に

openssl req -new -key server.key -out server.csr

2-1-3.サーバーの自己署名証明書(server.crt)を作る

openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

ここでは有効期限を365日としています。そのうち47日になります。

2-1-4.pfx形式で保存する

作成した サーバーの秘密鍵 (server.key) とサーバーの自己署名証明書 (server.crt) をまとめて PFX(PKCS#12)形式 に変換します。PFX は Windows の IIS や多くのアプリケーションで使いやすい形式です。もちろん後でサーバー認証の時に使います。

openssl pkcs12 -export -out server.pfx -inkey server.key -in server.crt

パスワードを求められます。このパスワードはpfxファイルのパスワードであり、それ以外の用途はありません。

パスワードをいちいち聞かれるのも面倒です。セキュリティ的にアレなのですが、コマンドラインからパスワードを指定できます。

openssl pkcs12 -export -out server.pfx -inkey server.key -in server.crt -passout pass:p@ssw0rd

パスワードをコマンドラインに書きたくなければ環境変数に書いておくといいでしょう。

openssl pkcs12 -export -out server.pfx -inkey server.key -in server.crt -passout env:PFX_PASS

2-2.どうしてもプログラムで書きたい人向け

.NET Framework でサーバー自己署名証明書が作れます。

2-2-1. RSA版とECDSA版

ChatGPT君によるとECDSA版の方がよりモダンなのだとか。
せっかくなので両方作ってもらいましょう。

ServerCert.cs

using System;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

class Program
{
    static void Main()
    {
        string ecdsaPath = @"server_ecdsa.pfx";
        string rsaPath = @"server_rsa.pfx";
        string password = "p@ssw0rd";

        // ECDSA 証明書作成
        CreateEcdsaCertificate(ecdsaPath, password);

        // RSA 証明書作成
        CreateRsaCertificate(rsaPath, password);
    }

    static void CreateEcdsaCertificate(string path, string password)
    {
        using (ECDsa ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP256))
        {
            var req = new CertificateRequest(
                "CN=localhost",
                ecdsa,
                HashAlgorithmName.SHA256);

            AddStandardExtensions(req);

            var cert = req.CreateSelfSigned(DateTimeOffset.Now, DateTimeOffset.Now.AddYears(1));
            File.WriteAllBytes(path, cert.Export(X509ContentType.Pfx, password));
            Console.WriteLine($"ECDSA PFX 作成完了: {path}");
        }
    }

    static void CreateRsaCertificate(string path, string password)
    {
        using (RSA rsa = RSA.Create(4096))
        {
            var req = new CertificateRequest(
                "CN=localhost",
                rsa,
                HashAlgorithmName.SHA256,
                RSASignaturePadding.Pkcs1);

            AddStandardExtensions(req);

            var cert = req.CreateSelfSigned(DateTimeOffset.Now, DateTimeOffset.Now.AddYears(1));
            File.WriteAllBytes(path, cert.Export(X509ContentType.Pfx, password));
            Console.WriteLine($"RSA PFX 作成完了: {path}");
        }
    }

    static void AddStandardExtensions(CertificateRequest req)
    {
        // SAN
        var sanBuilder = new SubjectAlternativeNameBuilder();
        sanBuilder.AddDnsName("localhost");
        req.CertificateExtensions.Add(sanBuilder.Build());

        // 基本制約(CA ではない)
        req.CertificateExtensions.Add(
            new X509BasicConstraintsExtension(false, false, 0, false));

        // KeyUsage と EKU(TLS サーバー用)
        req.CertificateExtensions.Add(
            new X509KeyUsageExtension(
                X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.KeyEncipherment, false));

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

2-2.サーバー自己署名証明書の確認

openssl で 作ったサーバー自己証明書を確認できます。

openssl pkcs12 -in server.pfx -nokeys -out cert.pem
openssl x509 -in cert.pem -noout -text

確認ポイント:
・Signature Algorithm → 設定したアルゴリズムであること
・Public-Key: (256 bit) → 設定したアルゴリズムであること
・Not Before / Not After → 有効期限
・SAN -> 設定したSANであること

3. 終わりに

サーバー自己署名証明書 が作れたので次回に続きます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?