9999 年間有効な SSL 証明書を作る
OpenSSL や GnuTLS を利用して、 任意の日時を有効期限に指定した自己署名証明書を生成するスクリプトを書きました。 だいぶニッチなスクリプトですが SSL のテストかなにかに使えるかもしれません。
さらにそれらを利用して、 有効期限がだいぶ長い (100 年間とか 9999 年間とか) SSL 証明書を作ろうとしてみました。
OpenSSL で 100 年間有効な証明書を作る
make-self-signed-cert-openssl.sh
は
OpenSSL のコマンドラインツールを使って自己署名証明書を生成するスクリプトです。
$ sudo apt-get install openssl
$ wget https://gist.githubusercontent.com/yaegashi/8004ca8677c5d03879bd/raw/a0c3ec4af0958ffaa85726b39ad8120c0f842f13/make-self-signed-cert-openssl.sh
$ chmod +x make-self-signed-cert-openssl.sh
$ ./make-self-signed-cert-openssl.sh
Usage: ./make-self-signed-cert-openssl.sh <common name> <output> [ca options ...]
<common name>
には Subject の名前 (通常は FQDN ホスト名) を指定します。
<output>
には出力ファイルパスを指定します。
パスフレーズなしの秘密鍵と証明書が PEM 形式で連結されて出力されます。
[ca options ...]
は署名を実行する
openssl ca コマンドにそのまま渡されます。
ca の -startdate
/-enddate
オプションを使用することで
証明書の有効期限に任意の時刻が指定できるので、
次のようにすれば 100 年間有効な SSL 証明書が作れます。
$ ./make-self-signed-cert-openssl.sh blog.keshi.org cert.pem -startdate 19500101000000Z -enddate 20491231235959Z
Generating a 2048 bit RSA private key
...+++
........................................+++
writing new private key to '/tmp/tmp.fjyu9QOhx8/key.pem'
-----
Using configuration from /tmp/tmp.fjyu9QOhx8/ssleay.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :PRINTABLE:'blog.keshi.org'
Certificate is to be certified until Dec 31 23:59:59 2049 GMT
Write out database with 1 new entries
Data Base Updated
生成した証明書ファイルの内容は openssl x509 コマンドで確認できます。
$ openssl x509 -in cert.pem -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 0 (0x0)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=blog.keshi.org
Validity
Not Before: Jan 1 00:00:00 1950 GMT
Not After : Dec 31 23:59:59 2049 GMT
Subject: CN=blog.keshi.org
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:e6:6a:3c:02:e5:9b:8a:2a:a5:43:61:fb:bc:26:
c2:94:7e:f4:10:a4:ff:d0:c3:10:e9:a9:26:88:85:
26:fb:8d:ec:94:d6:59:86:c9:e7:c5:b6:50:1b:4a:
9f:90:ba:c9:ea:62:b6:4e:ad:67:94:cf:18:cd:2c:
0c:03:30:38:ac:7a:30:6e:77:02:6d:ba:1c:d0:c6:
8d:00:5d:b2:4a:fd:7d:85:ae:9c:eb:1d:51:3b:c2:
a9:31:76:80:88:4b:ef:db:52:76:11:6a:da:85:96:
73:9c:2e:2a:3e:fc:f4:75:10:c4:cf:c1:b5:08:55:
3f:0a:56:dd:08:ec:98:70:5c:9c:09:d9:c5:91:81:
80:0b:ee:91:90:ed:41:69:17:46:36:2d:f0:04:2a:
6a:66:6d:b0:1e:2c:01:54:e6:8e:ae:4f:ef:28:51:
2a:38:81:f9:7c:8f:f9:bf:a2:d7:ee:0b:c4:13:bb:
1b:b1:54:4d:f6:81:d1:45:11:23:72:35:13:27:f8:
cd:06:ae:4e:a1:de:9e:9d:5b:67:bb:b8:fd:11:16:
8c:e0:7d:b7:1d:cc:94:73:59:3f:d4:44:1a:93:c2:
eb:35:63:10:5d:67:1b:b9:ec:60:41:8b:a8:49:1b:
6a:61:75:61:f0:69:78:04:05:1f:e0:a5:fe:68:8c:
af:9b
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Signature Algorithm: sha256WithRSAEncryption
d2:d6:ce:cf:fd:00:a6:f8:81:10:f7:6c:7c:43:75:46:3d:30:
db:82:51:6b:08:74:0a:7d:13:5e:1d:5b:e3:f4:e5:0f:b7:53:
cc:fa:87:ea:e8:a5:2b:c2:7e:40:3c:a6:73:6c:08:ff:65:be:
c2:8a:f1:11:6d:92:17:48:35:88:6b:53:24:76:b8:62:04:16:
cb:d6:df:d6:47:81:1e:db:3e:58:ab:31:3b:fb:f6:ba:57:4e:
71:33:30:0f:06:6d:1c:58:86:9e:b2:aa:72:76:ef:6a:63:cf:
f1:48:5e:8c:41:72:02:15:2c:81:f6:0a:47:6c:90:0f:74:4d:
14:32:a3:2d:c0:81:dd:b0:5e:96:8f:9d:6e:a5:3d:53:f7:dd:
04:12:81:75:81:08:b3:01:1a:6f:64:92:30:b9:7b:a2:85:84:
0b:6a:75:cc:99:38:21:81:a1:ce:58:08:1e:e9:bf:49:dc:d4:
6c:69:5b:4a:55:ee:ff:dc:0a:0a:fb:c8:6c:04:17:61:9a:39:
1b:3f:b4:1b:47:b4:7e:0b:a3:20:65:aa:af:40:c5:c5:b2:4d:
f7:87:fe:1f:3f:4f:7b:84:e9:f7:97:82:81:3c:d9:ae:66:c0:
a8:83:2c:fb:96:aa:13:bf:38:de:60:91:00:2c:ec:d4:85:36:
be:e8:85:1d
以下、スクリプトの説明:
自己署名証明書を生成するだけなら
openssl req コマンドで
-x509
オプションを使えば 1 行でできるのですが、
req では -days
オプションで有効期限の終わりを指定することしかできません。
それが不満でこのスクリプトを作りました。
有効期限の始まりと終わりに任意の時刻を指定可能にするには
-startdate
/-enddate
オプションを備える
openssl ca コマンド
を使う必要があります。
ca では事前に設定ファイルや出力用ディレクトリを準備する必要があるため
だいぶ面倒なスクリプトになりました。
すでにお気づきかと思いますが -startdate
/-enddate
オプションが受け付ける時刻は
西暦 2 桁の YYMMDDHHMMSSZ
の形式であるため、
1950年1月1日00:00:00+0000 から
2049年12月31日23:59:59+0000 までの 100 年有効な証明書しか作れません。
これは両オプションの引数が
ASN.1 の UTCTime
に準拠しているためです。
その一方で -days
オプションを使えば、
終了時刻が 2050年以降の証明書を作ることが可能です。
この場合は GeneralizedTime
が証明書に埋め込まれることになります。
GeneralizedTime を使えば西暦 1 年から 9999 年までの
9999 年間有効な証明書が作れるはずです。
しかしながら、そのような証明書を作ることは OpenSSL コマンドラインツールではどうやら無理そうです。 OpenSSL ライブラリ自体には問題はないようなので、 自分の好きな SSL 証明書を作りたければ もっとまともなフロントエンドツールないし別のソフトを使うべきということなのでしょう。
GnuTLS で 8030 年間有効な証明書を作る
そこで他のソフトに目を向けたところ GnuTLS では
certtool コマンドに
activation_date
/expiration_date
という設定が存在することがわかったので、
これを利用した
make-self-signed-cert-gnutls.sh
を書きました。
$ sudo apt-get install gnutls-bin
$ wget https://gist.githubusercontent.com/yaegashi/fafef425fc2080b2ced4/raw/7b56f2fb1b95d1e5049dfc0296e2f24e1f6739f3/make-self-signed-cert-gnutls.sh
$ chmod +x ./make-self-signed-cert-gnutls.sh
$ ./make-self-signed-cert-gnutls.sh
Usage: ./make-self-signed-cert-gnutls.sh <common name> <output> [<start> <end>]
certtool コマンドを利用しますので
Debian/Ubuntu では gnutls-bin パッケージを事前にインストールしてください。
ただし activation_date
/expiration_date
オプションが追加されたのは
GnuTLS 3.2.7 からなので、
Debian では jessie 以降、 Ubuntu では utopic 以降である必要があります。
make-self-signed-cert-openssl.sh
とは異なり
有効期限は <start>
引数と <end>
引数で直接指定します
(GNU date コマンドと同じ書式が使えます)。
ということで 9999 年間有効な SSL 証明書を作ろうとしてみたのですが…
$ ./make-self-signed-cert-gnutls.sh blog.keshi.org hoge.pem "0001-01-01 00:00:00 +0000" "9999-12-31 23:59:59 +0000"
Generating a 2432 bit RSA private key...
Generating a self signed certificate...
X.509 Certificate Information:
Version: 3
Serial Number (hex): 54cd3fd6
Validity:
Not Before: Thu Jan 01 00:00:00 UTC 1970
Not After: Fri Dec 31 23:59:59 UTC 9999
Subject: CN=blog.keshi.org
Subject Public Key Algorithm: RSA
Algorithm Security Level: Normal (2432 bits)
Modulus (bits 2432):
00:b5:3a:16:ba:b6:12:5b:29:0d:bd:63:db:c8:39:28
ce:f0:ca:b9:55:60:28:5a:d3:4e:f7:27:18:9d:f7:c6
31:e4:ca:e0:f6:96:ff:eb:35:f6:83:25:6f:7b:21:08
6d:a3:06:b6:9b:0e:67:60:bd:7e:49:a2:cc:1f:06:b0
71:ec:c1:37:2c:f8:b1:cc:a3:03:03:f2:b3:92:af:7d
66:37:c5:39:13:c8:c1:cb:0d:f1:f5:e8:5a:19:24:48
29:b5:de:1b:1c:bd:55:5b:92:03:5e:d0:66:a2:dc:81
49:a0:e6:b7:45:87:38:3d:8d:ba:51:e4:48:d9:87:b1
f8:ca:37:f5:0f:14:0c:c2:5f:be:10:c3:55:8d:f9:a3
b0:82:ad:df:81:af:53:ba:11:92:e0:b2:c2:bb:e1:9d
c4:aa:fa:44:69:bc:5b:c3:82:f5:2a:72:5a:38:dc:b0
cf:ee:20:e2:e6:c8:c5:40:90:ca:70:78:64:0b:d7:77
d2:9f:dd:d3:cc:3b:60:d8:c3:1a:45:bb:eb:3d:20:c4
5a:2c:15:b2:f4:71:42:c4:3b:b1:0d:3a:a0:a9:00:76
a2:bb:34:69:fa:d8:b1:f2:f3:46:24:b8:36:ec:3d:85
ce:4d:8b:67:82:08:36:2c:e5:55:d9:d3:d3:32:8d:78
86:cd:ea:32:f3:95:11:93:92:b1:97:60:62:9d:2e:90
5e:e8:4b:72:8e:b5:9e:44:a5:69:77:57:7e:59:ff:66
d1:57:9f:b5:f0:b9:ff:1d:0c:55:80:0b:46:52:6a:34
77
Exponent (bits 24):
01:00:01
Extensions:
Basic Constraints (critical):
Certificate Authority (CA): FALSE
Subject Key Identifier (not critical):
a2ca4ee377b0b38cf149e04494a16e33b2132a6a
Other Information:
Public Key ID:
a2ca4ee377b0b38cf149e04494a16e33b2132a6a
Public key's random art:
+--[ RSA 2432]----+
| oo |
| o. |
|. . |
|.. |
|o=o . S |
|+=o... . |
|= = oo |
|oE O+.. |
|o.*.=+ |
+-----------------+
Signing certificate...
残念ながら 1970年1月1日00:00:00+0000 (Unix エポック) 開始の証明書しか作れませんでした。
GnuTLS の API を見ると
gnutls_x509_crt_set_activation_time() や
gnutls_x509_crt_set_expiration_time()
などで time_t
を使って時刻をセットするようになっており、どうやらこれが仕様のようです。
ついでにいうと 32bit アーキテクチャでは time_t
が 32bit のため
2038 年までの証明書しかつくることができませんでした。
おわりに
OpenSSL と GnuTLS の標準フロントエンドツールで 9999 年間有効な証明書を作ろうとしたけど、結局駄目だったというお話でした。 今のところ最高で 1950 年開始の SSL 証明書しか作れていません。
OpenSSL ライブラリであればそれより前の開始時刻にも対応していると思うので 自分でツールを書けば作れるのでしょうが、 そんな時間もないのでここらで終わりにしたいと思います。
2015/02/01 07:51:00 JST