22
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OpenSSLで検証用証明書を発行するCAを作ってみる

22
Last updated at Posted at 2025-12-12

はじめに

この記事はシスコの有志による Cisco Systems Japan Advent Calendar 2025 (シリーズ2) の 13日目として投稿しています。
2025年版

過去のカレンダーは2025年度版のカレンダーの中にリンクがありますので、こちらも合わせてご参照ください!

デジタル証明書

ITエンジニアとして仕事をしていると、Webサーバ、SSL VPN、802.1x、IPsecなど、いろいろな場面でデジタル証明書を使うことがあります。

証明書を発行するには、商用のCAやLet's Encryptのような無償のCAを利用することができますが、商用CAの場合は当然お金がかかりますし、信頼できる組織やドメインに対してしか証明書を発行してくれません。
検証環境のような閉じられた空間で利用する場合は、自前のCA局を運用して証明書を管理するのが望ましい姿といえます。

OpenSSL

OpenSSLは、安全な通信を実現するためのオープンソースのソフトウェアライブラリです。主に、ウェブサイトのHTTPS通信などで利用されるSSL/TLSプロトコル(Secure Sockets Layer / Transport Layer Security)の実装を提供しています。

OpenSSLの主な機能は以下の通りです。

  • 暗号化と復号化:
    データの盗聴や改ざんを防ぐために、対称暗号方式(AESなど)や公開鍵暗号方式(RSAなど)を用いた暗号化・復号化を行います
  • デジタル証明書の管理:
    サーバーやクライアントの身元を証明するデジタル証明書の生成、管理、検証をサポートします
  • 鍵生成:
    安全な通信に必要な秘密鍵や公開鍵などの暗号鍵を生成します
  • ハッシュ化:
    データが改ざんされていないことを確認するためのハッシュ関数を提供します

LinuxやMac、Windows WSLなどには、通常OpenSSLはプリインストールされているため、特別な操作なしで利用することが可能です。
検証環境でCAを作る場合、Windows ServerのADCSを利用されることがあるかもしれませんが、イマイチわかりにくいし自由度が低いと感じる(個人的に)ので、私はOpenSSLを使ってCA局を構成しています。

本記事では、証明書を管理するCA局の構築を行いますが、証明書の生成には上記の主な機能が全て使われています。

OpenSSLのコマンドをステップバイステップで実行していけば、証明書の作成を完遂することができます。しかしながら、実行ステップが多いため、一連の流れをShell scriptでまとめて実行し、作業を簡略化しています。

CAの初期化

Filesにあるinitca.shca.cnfをファイルとして保存し、Shell scriptに実行権限を付与します。

chmod +x initca.sh

initca.shは、必要とするファイルやディレクトリの準備を行い、CA局の秘密鍵とCA証明書を生成します。
CAを作り直したい場合には、このスクリプトを実行し直すことで対応することが可能です。この場合、発行ずみの証明書は全て削除されます。

aktosa@DESKTOP-J0O1K31:~/CA_root$ ./initca.sh
#############################################
### generate self-signed root certificate ###
#############################################
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [JP]:
Organization Name (eg, company) [Example Corp]:
Organizational Unit Name (eg, section) [Test lab]:
Common Name (e.g. server FQDN or YOUR name) []:Test lab root CA
Email Address []:
Using configuration from ca.cnf
aktosa@DESKTOP-J0O1K31:~/CA_root$

上記のように、実行するとOUやCNの入力を求めらるので、それぞれの内容を入力します。
[xxx]のようにデフォルト値を持つものについてはEnterを押すとその内容が利用されます。デフォルト値は、ca.cnfファイル内のセクション名=req_distinguished_nameで定義されているので、環境に合わせて内容を変更してください。

証明書発行

FilesにあるcertGen.shをファイルとして保存し、Shell scriptに実行権限を付与します。

chmod +x certGen.sh

certGen.shをオプションなしで実行すると、使い方が表示されます。

aktosa@DESKTOP-J0O1K31:~/CA_root$ ./certGen.sh
-s or -c or -i or -o is mandatory option!!

usage: ./certGen.sh <-s|-c|-i|-o> [-a <SAN>] <cert name>
  -s: Generate server certificate
  -c: Generate client certificate
  -i: Generate IPsec authentication certificate
  -o: Generate OCSP signing certificate
  -a: Add subject alternative name. ex) IP:1.1.1.1,IP:10.0.0.1,DNS:host.example.com,UPN:user@example.com (do not include white space)
  <cert name>: dir and file name to be creatd under certs dir
aktosa@DESKTOP-J0O1K31:~/CA_root$
Option 説明
-s サーバ証明書を発行
-c クライアント証明書を発行
-i IPsecのIKE認証用証明書を発行
-o OCSP署名用証明書を発行
-a Subject Alternative Name (SAN)を付与
IPアドレス, DNS名, UPNを追加可能です
複数指定する場合には、スペースなしのカンマ区切りで記述します
設定例:
- 複数のDNS名を追加 = DNS:app1.example.com,DNS:app2.example.com
- UPNを追加 = UPN:user@example.com
<cert name> 証明書の名前
証明書を保存するディレクトリや、ファイル名に利用されます

このShell scriptは、オプションの指定内容に従い、証明書に関連するファイルを自動的に生成します。
certsディレクトリ配下に <cert name> で指定したディレクトリを作成し、以下のファイルが生成されます。

ファイル名 内容
extensions.txt 証明書発行時のX.509各種属性指定内容
passphrase.txt 以下のファイルに設定されたパスフレーズ
- 暗号化された秘密鍵 (XXX_keyenc.pem)
- PKCS12証明書 (XXX_cert.p12, XXX _cert.pfx)
<cert name>_csr.pem PEM形式のCSR
<cert name>_key.pem PEM形式の秘密鍵 (暗号化なし)
<cert name>_keyenc.pem PEM形式の秘密鍵 (暗号化あり)
<cert name>_cert.cer DER形式の署名済み証明書 (Binary)
<cert name>_cert.pem PEM形式の署名済み証明書 (Text)
<cert name>_cert.pfx PFX形式の署名済み証明書 + 秘密鍵 (Binary)
<cert name>_cert.p12 Base64形式の署名済み証明書 + 秘密鍵 (Text)

大まかな実行内容は以下のとおりです。

以下の実行例は、Common Name (CN)に *.example.com, Subject Alternative Name (SAN)に web1.example.comweb2.example.com という2つのFQDNを指定し証明書を作成した場合のものです。

aktosa@DESKTOP-J0O1K31:~/CA_root$ ./certGen.sh -s -a DNS:web1.example.com,DNS:web2.example.com server
############################
### generate Private key ###
############################
writing RSA key

####################
### generate CSR ###
####################
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [JP]:
Organization Name (eg, company) [Example Corp]:
Organizational Unit Name (eg, section) [Test lab]:
Common Name (e.g. server FQDN or YOUR name) []:*.example.com
Email Address []:

###############################
### Sign to the certificate ###
###############################
Using configuration from ca.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'JP'
organizationName      :PRINTABLE:'Example Corp'
organizationalUnitName:PRINTABLE:'Test lab'
commonName            :T61STRING:'*.example.com'
Certificate is to be certified until Dec 30 04:26:39 2026 GMT (390 days)

Write out database with 1 new entries
Database updated

#########################################################
### generate PKCS12 (binary format - PFX) certificate ###
#########################################################

################################################
### generate PKCS12 (PEM format) certificate ###
################################################
aktosa@DESKTOP-J0O1K31:~/CA_root$

上記実行例で作成したサーバ証明書を、x509コマンドで確認すると以下のような内容になり、Common Name (CN) がワイルドカード CN = *.example.com、Subject Alternative Name (SAN) に2つのFQDNが含まれている DNS:web1.example.com, DNS:web2.example.com ことが確認できます。

aktosa@DESKTOP-J0O1K31:~/CA_root$ openssl x509 -text -in certs/server/server_cert.pem
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 257 (0x101)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = JP, O = Example Corp, OU = Test lab, CN = Test lab root CA
        Validity
            Not Before: Dec  5 04:26:39 2025 GMT
            Not After : Dec 30 04:26:39 2026 GMT
        Subject: C = JP, O = Example Corp, OU = Test lab, CN = *.example.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:c4:0b:5e:a2:db:0e:19:e0:2f:cf:10:49:f2:1e:
                    04:23:8d:ac:0f:86:76:14:43:f4:9e:b8:07:f5:52:
                    8f:c5:53:18:e0:6b:0c:d6:4f:6c:bd:99:ef:6b:9f:
                    ce:f6:68:cd:b3:53:3e:7f:b3:62:de:92:0e:53:59:
                    13:1b:a3:e7:23:19:33:d1:47:1b:92:02:26:58:af:
                    2a:fb:50:fd:6e:a9:5a:f7:09:4a:38:b5:0f:c6:76:
                    09:de:25:57:57:3b:ec:7f:8f:f3:3c:35:ed:da:43:
                    c8:d9:b2:2b:a7:ce:86:d1:b3:98:41:3d:07:f0:d3:
                    c7:0d:01:41:94:59:c6:81:af:4a:ed:bb:00:5f:f5:
                    53:54:c4:ac:6f:1f:52:78:42:07:96:c9:33:34:c3:
                    03:64:e1:e0:d4:ec:8c:39:68:11:3a:14:a2:34:a4:
                    3d:bf:b2:31:24:ac:32:80:c6:0d:e9:fb:9d:f2:05:
                    4d:1a:aa:02:80:75:27:5e:dc:f9:11:cb:a0:32:4e:
                    8b:13:4f:28:02:48:fa:78:8b:41:c7:07:51:92:3c:
                    16:4a:94:d8:49:ba:8d:10:fa:a0:92:a3:2b:3e:0f:
                    b2:63:8f:03:42:9a:f5:ff:10:46:d9:af:7d:f7:68:
                    af:b9:d8:ab:21:bd:c0:7d:58:a9:17:19:fc:ff:13:
                    a6:31
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                15:21:BC:23:1A:42:05:4F:C9:AE:3A:22:E1:FF:8D:3B:C5:D9:7D:DA
            X509v3 Authority Key Identifier:
                A1:DF:06:87:20:94:2B:AE:CF:5E:13:F3:7E:63:41:0E:2C:6A:FD:3E
            X509v3 Key Usage:
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage:
                TLS Web Server Authentication
            X509v3 Subject Alternative Name:
                DNS:web1.example.com, DNS:web2.example.com
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        53:be:2b:3a:ae:ca:be:70:69:6d:b8:ab:a3:5f:a9:ec:fc:bd:
        70:bc:93:40:9c:a2:bc:3a:b0:f2:ff:71:2f:f1:fa:57:ed:17:
        7b:18:b4:d8:13:ff:85:83:56:4e:7c:3b:ab:1d:5d:0b:0b:51:
        c8:ab:71:10:fc:70:1d:d4:08:8a:93:69:37:b8:2a:14:97:b8:
        fd:5b:70:8c:70:e5:73:aa:3a:45:39:fe:3b:f0:92:1f:8f:aa:
        74:45:29:28:fb:e5:52:28:f7:09:2c:68:33:c3:73:19:a2:9c:
        4a:53:cf:a9:7b:e8:3c:41:5a:53:87:1d:60:fc:84:ea:a0:f9:
        d4:d6:26:00:be:88:df:e7:1e:8b:7f:b2:91:f5:63:af:9f:8f:
        1a:9d:9f:53:55:2a:94:e4:90:51:1a:f3:03:2e:58:c8:4b:f2:
        cf:cf:95:be:ca:14:a8:d4:a2:65:a7:e1:db:6a:95:bc:aa:8c:
        2c:70:5f:a9:f5:bb:63:a6:d6:cf:e1:c3:00:ac:de:b8:72:67:
        f4:c1:ce:7f:b9:7b:0b:68:49:7b:ad:04:c7:2b:36:f4:54:e0:
        e2:1c:4b:1c:de:59:70:e5:11:fe:30:38:9c:15:34:4c:25:6b:
        c9:cb:29:6d:9e:97:15:fc:0c:22:2a:0a:8d:f3:a0:e1:1d:db:
        5f:f8:c7:6b
-----BEGIN CERTIFICATE-----
MIID6zCCAtOgAwIBAgICAQEwDQYJKoZIhvcNAQELBQAwUjELMAkGA1UEBhMCSlAx
FTATBgNVBAoTDEV4YW1wbGUgQ29ycDERMA8GA1UECxMIVGVzdCBsYWIxGTAXBgNV
BAMTEFRlc3QgbGFiIHJvb3QgQ0EwHhcNMjUxMjA1MDQyNjM5WhcNMjYxMjMwMDQy
NjM5WjBPMQswCQYDVQQGEwJKUDEVMBMGA1UEChMMRXhhbXBsZSBDb3JwMREwDwYD
VQQLEwhUZXN0IGxhYjEWMBQGA1UEAxQNKi5leGFtcGxlLmNvbTCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBAMQLXqLbDhngL88QSfIeBCONrA+GdhRD9J64
B/VSj8VTGOBrDNZPbL2Z72ufzvZozbNTPn+zYt6SDlNZExuj5yMZM9FHG5ICJliv
KvtQ/W6pWvcJSji1D8Z2Cd4lV1c77H+P8zw17dpDyNmyK6fOhtGzmEE9B/DTxw0B
QZRZxoGvSu27AF/1U1TErG8fUnhCB5bJMzTDA2Th4NTsjDloEToUojSkPb+yMSSs
MoDGDen7nfIFTRqqAoB1J17c+RHLoDJOixNPKAJI+niLQccHUZI8FkqU2Em6jRD6
oJKjKz4PsmOPA0Ka9f8QRtmvffdor7nYqyG9wH1YqRcZ/P8TpjECAwEAAaOBzTCB
yjAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBD
ZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUFSG8IxpCBU/Jrjoi4f+NO8XZfdowHwYDVR0j
BBgwFoAUod8GhyCUK67PXhPzfmNBDixq/T4wCwYDVR0PBAQDAgWgMBMGA1UdJQQM
MAoGCCsGAQUFBwMBMC0GA1UdEQQmMCSCEHdlYjEuZXhhbXBsZS5jb22CEHdlYjIu
ZXhhbXBsZS5jb20wDQYJKoZIhvcNAQELBQADggEBAFO+Kzquyr5waW24q6Nfqez8
vXC8k0Ccorw6sPL/cS/x+lftF3sYtNgT/4WDVk58O6sdXQsLUcircRD8cB3UCIqT
aTe4KhSXuP1bcIxw5XOqOkU5/jvwkh+PqnRFKSj75VIo9wksaDPDcxminEpTz6l7
6DxBWlOHHWD8hOqg+dTWJgC+iN/nHot/spH1Y6+fjxqdn1NVKpTkkFEa8wMuWMhL
8s/Plb7KFKjUomWn4dtqlbyqjCxwX6n1u2Om1s/hwwCs3rhyZ/TBzn+5ewtoSXut
BMcrNvRU4OIcSxzeWXDlEf4wOJwVNEwla8nLKW2elxX8DCIqCo3zoOEd21/4x2s=
-----END CERTIFICATE-----
aktosa@DESKTOP-J0O1K31:~/CA_root$

証明書失効

FilesにあるcertRevoke.shをファイルとして保存し、Shell scriptに実行権限を付与します。

chmod +x certRevoke.sh

certRevoke.shをオプションなしで実行すると、使い方が表示されます。

aktosa@DESKTOP-J0O1K31:~/CA_root$ ./certRevoke.sh
usage: ./certRevoke.sh <cert name>
aktosa@DESKTOP-J0O1K31:~/CA_root$
Option 説明
<cert name> 証明書の名前
certGen.shで作成したcertsディレクトリ配下のディレクトリ名

以下の実行例は、server という名称で作成した証明書を失効させた場合のものです。

aktosa@DESKTOP-J0O1K31:~/CA_root$ ./certRevoke.sh server
#########################
### revoke certifiate ###
#########################
Using configuration from ca.cnf
Revoking Certificate 0101.
Database updated
####################
### Generate CRL ###
####################
Using configuration from ca.cnf
Certificate Revocation List (CRL):
        Version 2 (0x1)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = JP, O = Example Corp, OU = Test lab, CN = Test lab root CA
        Last Update: Dec  8 02:11:08 2025 GMT
        Next Update: Jan  7 02:11:08 2026 GMT
        CRL extensions:
            X509v3 CRL Number:
                1
Revoked Certificates:
    Serial Number: 0101
        Revocation Date: Dec  8 02:11:08 2025 GMT
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        b9:e5:85:98:4d:cb:b1:f0:32:a2:1f:64:c5:a7:9e:35:00:e8:
        6d:b5:20:92:24:05:49:fe:3b:52:03:4e:ba:e0:b9:62:0d:61:
        c7:61:26:8d:64:c7:0f:d3:75:d5:1a:75:d1:bc:92:3c:db:ed:
        88:2e:d1:a5:ee:c1:3a:b7:e1:e5:6e:1c:22:f1:02:1f:61:67:
        00:63:40:a0:a0:f4:7b:18:36:08:e8:0e:75:a4:6a:05:e2:cc:
        1c:71:3e:03:a4:1d:4f:be:0c:71:86:2e:f4:d3:a6:c5:bc:4d:
        b6:1f:18:78:6f:8f:50:24:96:43:fe:d7:8d:ee:ea:8b:c1:16:
        38:12:50:c3:b0:6f:c9:17:50:62:04:fa:32:7d:94:c9:c2:04:
        da:f2:b7:9d:b0:69:e8:ce:de:c6:e3:eb:c3:88:79:f6:ce:5d:
        df:cb:c8:bd:14:4c:4a:53:00:61:fa:7d:e0:86:7a:44:f0:6b:
        a8:37:f4:0f:fa:c0:d8:98:b2:ee:17:26:11:61:83:b4:fe:66:
        1b:2a:9c:ac:95:29:34:0d:5d:d5:0a:e7:43:d4:3c:ea:5e:d7:
        c3:96:ad:46:03:7a:11:cc:9b:7a:93:88:f2:1b:d8:71:24:40:
        6c:ce:40:35:f3:43:ea:21:72:22:1c:e4:bd:aa:e8:ae:a6:d3:
        1d:2e:e7:b9
-----BEGIN X509 CRL-----
MIIBwjCBqwIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJKUDEVMBMGA1UE
ChMMRXhhbXBsZSBDb3JwMREwDwYDVQQLEwhUZXN0IGxhYjEZMBcGA1UEAxMQVGVz
dCBsYWIgcm9vdCBDQRcNMjUxMjA4MDIxMTA4WhcNMjYwMTA3MDIxMTA4WjAVMBMC
AgEBFw0yNTEyMDgwMjExMDhaoA4wDDAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQsF
AAOCAQEAueWFmE3LsfAyoh9kxaeeNQDobbUgkiQFSf47UgNOuuC5Yg1hx2EmjWTH
D9N11Rp10bySPNvtiC7Rpe7BOrfh5W4cIvECH2FnAGNAoKD0exg2COgOdaRqBeLM
HHE+A6QdT74McYYu9NOmxbxNth8YeG+PUCSWQ/7Xje7qi8EWOBJQw7BvyRdQYgT6
Mn2UycIE2vK3nbBp6M7exuPrw4h59s5d38vIvRRMSlMAYfp94IZ6RPBrqDf0D/rA
2Jiy7hcmEWGDtP5mGyqcrJUpNA1d1QrnQ9Q86l7Xw5atRgN6EcybepOI8hvYcSRA
bM5ANfND6iFyIhzkvarorqbTHS7nuQ==
-----END X509 CRL-----
aktosa@DESKTOP-J0O1K31:~/CA_root$

index.txtを確認すると、Serial = 0101 の証明書に対し、行先頭の当該証明書のステータスを示す文字が R になり、失効状態 (Revoked) になっていることがわかります。

aktosa@DESKTOP-J0O1K31:~/CA_root$ cat index.txt
V       261228003141Z           0100    unknown /C=JP/O=Example Corp/OU=Test lab/CN=client/emailAddress=client@example.com
R       261230042639Z   251208021108Z   0101    unknown /C=JP/O=Example Corp/OU=Test lab/CN=*.example.com
aktosa@DESKTOP-J0O1K31:~/CA_root$

作成されたCRLファイルはWebサーバで公開しますが、RFCでDER形式のファイルとすることが規定されていますので、crl/crl.der のファイルを利用します。

Files

CA_root というディレクトリの中で各Shell scriptを動作させた場合のファイル構造は以下のようになります。
certGen.shで生成した証明書は、certsディレクトリに保存されます。

CA_root
.
|-- ca.cnf        : -config オプションで読み込むOpenSSLの設定ファイル
|-- cacert.pem    : initca.shを実行して生成されるCA証明書
|-- certGen.sh    : 証明書作成のShell script
|-- certRevoke.sh : 証明書失効のShell script
|-- certs
|   `-- server : "server"という名称で証明書を発行した場合のファイル保管場所
|       |-- extensions.txt    : 証明書発行時のX.509各種属性指定内容
|       |-- passphrase.txt    : 暗号化された秘密鍵 (XXX_keyenc.pem)、PKCS12 (XXX_cert.p12, XXX _cert.pfx)に設定されたパスフレーズ
|       |-- server_csr.pem    : PEM形式のCSR
|       |-- server_key.pem    : PEM形式の秘密鍵 (暗号化なし)
|       |-- server_keyenc.pem : PEM形式の秘密鍵 (暗号化あり)
|       |-- server_cert.cer   : DER形式の署名済み証明書 (Binary)
|       |-- server_cert.pem   : PEM形式の署名済み証明書 (Text)
|       |-- server_cert.pfx   : PFX形式の署名済み証明書 + 秘密鍵 (Binary)
|       `-- server_cert.p12   : Base64形式の署名済み証明書 + 秘密鍵 (Text)
|-- crl : 証明書失効を行なった場合のCRL情報格納場所
|   |-- crl.der       : DER形式のCRL
|   |-- crl.pem       : PEM形式のCRL
|   |-- crlnumber
|   `-- crlnumber.old
|-- index.txt
|-- index.txt.attr
|-- index.txt.old
|-- initca.sh : CA局を初期化するShell script
|-- newcerts  : 発行されたPEM形式の証明書 (<Serial>.pemの形式で保存、CAが署名したすべての証明書を保持)
|   `-- 0100.pem
|-- private
|   `-- privkey.pem : initca.shを実行して生成される秘密鍵 (暗号化なし)
|-- serial
`-- serial.old

initca.sh

initca.sh
#! /bin/bash
mkdir certs crl newcerts private > /dev/null 2>&1
rm cacert.pem index.txt*  newcerts/*  serial* crl/* > /dev/null 2>&1
rm -r certs/* > /dev/null 2>&1
touch index.txt
echo '0100' > serial
echo '00' > crl/crlnumber

openssl rand -out .rnd
openssl genrsa -out private/privkey.pem 2048

echo '#############################################'
echo '### generate self-signed root certificate ###'
echo '#############################################'
openssl req -config ca.cnf -x509 -key private/privkey.pem -sha256 -out cacert.pem -days 3650

openssl ca -config ca.cnf -gencrl -out crl/crl.pem
openssl crl -inform PEM -outform DER -in crl/crl.pem -out crl/crl.der

ca.cnf

ca.cnf
HOME                    = .
RANDFILE                = .rnd

[ ca ]
default_ca      = CA_default            # The default ca section

[ CA_default ]
dir             = $HOME         # Where everything is kept
certs           = $dir/certs            # Where the issued certs are kept
crl_dir         = $dir/crl              # Where the issued crl are kept
database        = $dir/index.txt        # database index file.
new_certs_dir   = $dir/newcerts         # default place for new certs.
certificate     = $dir/cacert.pem       # The CA certificate
serial          = $dir/serial           # The current serial number
crlnumber       = $crl_dir/crlnumber    # the current crl number
                                        # must be commented out to leave a V1 CRL
crl             = $crl_dir/crl.pem              # The current CRL
private_key     = $dir/private/privkey.pem      # The private key
RANDFILE        = $dir/private/.rand    # private random number file
default_days    = 390                   # how long to certify for
default_crl_days= 30                    # how long before next CRL
default_md      = sha256                        # which md to use.
preserve        = no                    # keep passed DN ordering
policy          = policy_anything

[ policy_anything ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

####################################################################
[ req ]
default_bits            = 2048
default_keyfile         = $HOME/private/privkey.pem
distinguished_name      = req_distinguished_name
x509_extensions = v3_ca # The extentions to add to the self signed cert
string_mask = nombstr

[ req_distinguished_name ]
countryName                     = Country Name (2 letter code)
countryName_default             = JP
countryName_min                 = 2
countryName_max                 = 2
0.organizationName              = Organization Name (eg, company)
0.organizationName_default      = Example Corp
organizationalUnitName          = Organizational Unit Name (eg, section)
organizationalUnitName_default  = Test lab
commonName                      = Common Name (e.g. server FQDN or YOUR name)
commonName_max                  = 64
emailAddress                    = Email Address
emailAddress_max                = 64

[ v3_ca ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
basicConstraints = CA:true
keyUsage = cRLSign, keyCertSign

certGen.sh

certGen.sh
#! /bin/bash

generation_failed() {
        echo ""
        echo "Certificate generation failed..."
        echo ""
        exit 1
}
usage_exit() {
    echo "usage: $0 <-s|-c|-i|-o> [-a <SAN>] <cert name>"
    echo "  -s: Generate server certificate"
    echo "  -c: Generate client certificate"
    echo "  -i: Generate IPsec authentication certificate"
    echo "  -o: Generate OCSP signing certificate"
    echo "  -a: Add subject alternative name. ex) IP:1.1.1.1,IP:10.0.0.1,DNS:host.example.com,UPN:user@example.com (do not include white space)"
    echo "  <cert name>: dir and file name to be creatd under certs dir"
    exit 1
}

while getopts scioa:h OPT
do
  case $OPT in
    s)
      SERVER=1
      ;;
    c)
      CLIENT=1
      ;;
    i)
      IPSEC=1
      ;;
    o)
      OCSPSIGN=1
      ;;
    a)
      SAN_VALUE=`echo $OPTARG | sed s/UPN:/otherName:1.3.6.1.4.1.311.20.2.3\;UTF8:/g`
      ;;
    h)
      usage_exit
      ;;
    \?)
      usage_exit
      ;;
  esac
done
shift $((OPTIND - 1))

if [ ! $SERVER ] && [ ! $CLIENT ] && [ ! $IPSEC ] && [ ! $OCSPSIGN ]; then
  echo "-s or -c or -i or -o is mandatory option!!"
  echo ""
  usage_exit
fi

if [ $# -lt 1 ]; then
  usage_exit
fi

if [ -d certs/$1 ]; then
  echo "certs/"$1" already exists"
  exit 1
fi

mkdir certs/$1

PASSPHRASE=`openssl rand -base64 50 | tr -dc '[:alnum:]' | head -c 12`
PASSFILE="certs/$1/passphrase.txt"
echo 'Passphrase for encrypted private key, .p12 and .pfx: '$PASSPHRASE > $PASSFILE

EXTFILE="certs/$1/extensions.txt"
echo "[ issued_ext ]
basicConstraints=CA:FALSE
nsComment = "OpenSSL Generated Certificate"
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
" >> $EXTFILE

if [ $SERVER ]; then
  echo "
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
" >> $EXTFILE
fi
if [ $CLIENT ]; then
  echo "
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth
" >> $EXTFILE
fi
if [ $IPSEC ]; then
  echo "
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = 1.3.6.1.5.5.8.2.2
" >> $EXTFILE
fi
if [ $OCSPSIGN ]; then
  echo "
keyUsage = digitalSignature
extendedKeyUsage = OCSPSigning
" >> $EXTFILE
fi

if [ $SAN_VALUE ]; then
  echo "subjectAltName="$SAN_VALUE >> $EXTFILE
fi

PATHKEY=certs/$1/$1_key.pem
PATHENCKEY=certs/$1/$1_keyenc.pem
PATHCSR=certs/$1/$1_csr.pem
PATHPEM=certs/$1/$1_cert.pem
PATHDER=certs/$1/$1_cert.cer
PATHPFX=certs/$1/$1_cert.pfx
PATHP12=certs/$1/$1_cert.p12

echo '############################'
echo '### generate Private key ###'
echo '############################'
openssl genrsa -des3 -passout pass:$PASSPHRASE -out $PATHENCKEY 2048
openssl rsa -in $PATHENCKEY -passin pass:$PASSPHRASE -out $PATHKEY

echo ''
echo '####################'
echo '### generate CSR ###'
echo '####################'
openssl req -config ca.cnf -new -key $PATHKEY -out $PATHCSR

if [ ! -f $PATHCSR ]; then
        rm -rf certs/$1
    generation_failed
fi

echo ''
echo '###############################'
echo '### Sign to the certificate ###'
echo '###############################'

openssl ca -config ca.cnf -batch -extensions issued_ext -extfile $EXTFILE -in $PATHCSR -notext -out $PATHPEM

if [ ! -f $PATHPEM ]; then
        rm -rf certs/$1
    generation_failed
fi

openssl x509 -in $PATHPEM -outform DER -out $PATHDER

echo ''
echo '#########################################################'
echo '### generate PKCS12 (binary format - PFX) certificate ###'
echo '#########################################################'
openssl pkcs12 -export -in $PATHPEM -inkey $PATHKEY -out $PATHPFX -passout pass:$PASSPHRASE

if [ ! -f $PATHPFX ]; then
    generation_failed
fi

echo ''
echo '################################################'
echo '### generate PKCS12 (PEM format) certificate ###'
echo '################################################'
#openssl pkcs12 -in $PATHPFX -out $PATHP12
echo '-----BEGIN PKCS12-----' > $PATHP12
base64 -w 64 -i $PATHPFX >> $PATHP12
echo '-----END PKCS12-----' >> $PATHP12

if [ ! -f $PATHP12 ]; then
    generation_failed
fi

certRevoke.sh

certRevoke.sh
if [ $# -lt 1 ]; then
  echo "usage: $0 <cert name>"
  exit 1
fi

if [ ! -d certs/$1 ]; then
  echo "certs/"$1" doesn't exist"
  exit 1
fi

echo '#########################'
echo '### revoke certifiate ###'
echo '#########################'
openssl ca -config ca.cnf -revoke certs/$1/$1_cert.pem

echo '####################'
echo '### Generate CRL ###'
echo '####################'
openssl ca -config ca.cnf -gencrl -out crl/crl.pem
openssl crl -inform PEM -outform DER -in crl/crl.pem -out crl/crl.der
openssl crl -in crl/crl.pem -text
rm -r certs/$1

動作確認環境

以下の組み合わせで動作確認を行い、問題なく動作することと確認しています。

OS OpenSSL
Windows WSL Ubuntu 24.04 3.0.13
MacOS 26.1 3.6.0
Almalinux 8.10 1.1.1k

おわりに

この記事では、OpenSSLのそれぞれのコマンドやConfigファイルの解説はしていませんが、これらの内容を理解することで、さらに理解が深まると思います。
ここで紹介した使い方は一つの例に過ぎませんので、他の使い方や証明書の内容を変更してみるなど、アレンジも是非試してみてください!

免責事項

本サイトおよび対応するコメントにおいて表明される意見は、投稿者本人の個人的意見であり、シスコの意見ではありません。本サイトの内容は、情報の提供のみを目的として掲載されており、シスコや他の関係者による推奨や表明を目的としたものではありません。各利用者は、本Webサイトへの掲載により、投稿、リンクその他の方法でアップロードした全ての情報の内容に対して全責任を負い、本Web サイトの利用に関するあらゆる責任からシスコを免責することに同意したものとします。

22
5
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
22
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?