はじめに
この記事はシスコの有志による 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.shとca.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.com、web2.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
#! /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
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
#! /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
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 サイトの利用に関するあらゆる責任からシスコを免責することに同意したものとします。