はじめに
プライベートなネットワークにおいてSSL/TLS証明書(以下、証明書)を発行するのが今回のゴール。
パブリックな環境であれば、Let's encryptで無料でSSL証明書発行してもらえばよいし、プライベートで利用するにしても、利用したいドメインを所有していればワイルドカード証明書を発行してもらうなりして、プライベートなネットワーク上で利用するという手もある。
とはいえ、そのドメインに対してLet's encrypt側から接続できる必要があるので、その準備ができない状況では上記の方法は難しい。
今回は、Windows ServerのActive Directory Certificate Services(AD CS)を利用して、プライベートなネットワーク上に認証機関を準備し、証明書を発行できるようにする。
証明書の発行に当たって、ルートCA・下位CAの構築を行い2段階の構成とする。その過程で、実際どんなファイルができて、どういう情報を持っているのかも見ていこうと思う。
なお、CA構築の細かい手順の説明はないし、PKI(Public Key Infrastructure/公開鍵基盤)それ自体についての説明もないのであしからず。
最終的な姿
どういう形になったか先に述べておくと以下のようになる。
ルートCA(CN=rootCA・スタンドアロンCA・ADDS構築なし)
|
下位CA(CN=subordinateCA・エンタープライズCA・ADDS構築あり)
|
サーバ証明書(CN=ssltest)
2
3
4
5
証明機関の準備
証明機関として、Windows Serverの機能として備わっている『Active Directory Certificat Services(AD CS)』を利用する。
Windows Serverは無償で利用できる評価版が用意されている。今回は本番運用が目的ではなく、180日以内で済む程度の検証なので評価版を利用する。
ちょいちょい継続的に利用するなら、AWS等でWindows Serverのインスタンスを利用するのもありかなと思う。
Windows Serverにおいて、証明機関の準備方法は大きく2種類ある。
- Enterprise CA(エンタープライズCA)
- Stand-alone CA(スタンドアロンCA)
前者は、Active Directory Domain Service(AD DS)を必要とし、後者は必要としない。 前者は、AD DSを利用することで証明書の管理を楽に行うことができる。
AD DSを利用して何かをする予定はないが、せっかくなのでどちらもも触っておこうと思う。
よって、以下のようにすることにした。
ルートCA:スタンドアロンCA(AD DS構築なし)
下位CA :エンタープライズCA(AD DS構築あり)
Root CA(ルートCA)の準備
ルートCAは、ネットワークに接続していないCAとして用意している体にして、AD DSは利用せず、スタンドアロンのCAとして構築した。
CAの構築手順自体は探せばいくらでも出てくるので割愛。
CRL(Certificate Revocation List/証明書失効リスト)の設定
ルートCAのCRLの設定を行っておく。
AD CSの場合、 certsrv
から以下のように進んで設定可能。
certsrv
> ルートCA
> Properties
> Extentions
> CRL Destribution Point(CDP)
> Authority Information Access(AIA)
2
3
4
5
6
以下のように設定する
- CDPには
.crl
ファイル(証明書失効リスト)のエンドポイント - AIAには
.crt
ファイル(証明書)のエンドポイント
AD DSを利用しない場合は、HTTPサーバを用意するなどしてクライアントがアクセスできる場所を指定しておく必要がある。
HTTPサーバを用意してCRLにアクセスできるようにする方法は後述。
CRLの役割
CRLは証明機関の発行した証明書を証明書の期限が来る前に失効させたい場合に利用される。
例えば、下位CAの秘密鍵の漏洩といった事実が判明した場合に、下位CAに対して発行した証明書を失効状態とする。そうすることで、当該のCAが発行した証明書の検証において、下位CAの証明書が失効している事実がわかれば証明書の検証を失敗させることができる。
Subordinate CA(下位CA)の準備
AD DSをインストールしてからEnterprise CAとして下位CAを用意した。
下位CAがドメインコントローラー(ないしはメンバサーバ)を兼ねていて、ルートCAの証明書の配布を行っているケースがあるようだった。形だけでもその形に寄せておこうかなということで、Enterprise CAとして下位CAを用意することにした。
ただ、今回はAD DSによる証明書の配布は行わない。
下位CAの証明書発行
下位CAのCSR(証明書署名要求)の作成
AD CSの場合、下位CAとしてセットアップすると最後の方に証明書署名要求についての選択がある。
ファイルに出力するものを選択すると、~.req
というファイルができる。
CSRの中を見る
テキストエディタで開くとこんな感じ。
文字列を見た感じBase64でエンコードされていると思われる。
-----BEGIN NEW CERTIFICATE REQUEST-----
MIIFKDCCAxACAQAwSDEVMBMGCgmSJomT8ixkARkWBWxvY2FsMRwwGgYKCZImiZPy
(省略)
NQvX7vSipXLQsYSGAJ5TIkqZfLDRlz7R4tcPNQ==
-----END NEW CERTIFICATE REQUEST-----
2
3
4
5
openssl
を使えば、情報を確認することができる。
$ openssl req -noout -text -in WIN-CHARAGAKI.kibidango.local_subordinateCA-WIN-CHARAGAKI-CA.req
Certificate Request:
Data:
Version: 1 (0x0)
Subject: DC = local, DC = kibidango, CN = subordinateCA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (4096 bit)
Modulus:
00:a2:a7:96:6f:d4:8c:72:14:3f:21:69:dc:3d:38:
(省略)
cb:08:51
Exponent: 65537 (0x10001)
Attributes:
1.3.6.1.4.1.311.13.2.3 :10.0.17763.2.
Requested Extensions:
1.3.6.1.4.1.311.21.1:
...
X509v3 Subject Key Identifier:
87:D3:47:E2:14:6D:88:F2:D3:C0:D4:E3:1D:A5:9D:10:84:3F:2E:83
1.3.6.1.4.1.311.20.2:
.
.S.u.b.C.A
X509v3 Key Usage:
Digital Signature, Certificate Sign, CRL Sign
X509v3 Basic Constraints: critical
CA:TRUE
Signature Algorithm: sha512WithRSAEncryption
6b:00:31:71:d7:dc:a3:40:f0:1a:5b:45:ff:0b:b6:2d:31:36:
(省略)
d1:97:3e:d1:e2:d7:0f:35
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
ルートCAでの下位CAの証明書発行
証明書署名要求ファイルをルートCAに取込み、発行を行う。
- 要求ファイルの取り込み
certsrv
> ルートCAで右クリック
> All Tasks
> Submit new request...
> (reqファイルの選択)
2
3
4
5
要求ファイルが取り込まれると、Pending Requests(保留中の要求)として扱われる。
- 証明書の発行
certsrv
> ルートCA
> Pending Requests
> 要求を右クリック
> Issue
2
3
4
5
ルートCAで発行した証明書を下位CAで取り込めるようにエクスポートする。
- ルートCAで証明書のエクスポート
certsrv
> ルートCA
> Issued Certificates
> 証明書を開く
> PKCS #7の形式でエクスポート
2
3
4
5
エクスポート自体は、証明書のDetail(詳細)タブからCopy to file(ファイルにコピー)より行える。
エクスポートする際には証明書チェーンに含まれる証明書を含むようにエクスポートする。
エクスポートすると *.p7b
というファイルが作成される。
PKCS#7のファイルを見る
PKCS #7については後述するとして、ファイルを少し見てみる。
*.p7b
ファイルを開くと、中に2つの証明書が入っていることがわかる。
Issued To(発行先) Issued By(発行者)
-----------------------------------------------
subordinateCA rootCA
rootCA rootCA
2
3
4
下位CAの証明書の取り込み
- 下位CAで証明書のインポート
certsrv
> 下位CA
> All Tasks
> Install CA Certifications...
2
3
4
下位CAの起動
インポートが完了したら、CAの起動を行う。
certsrv
> 下位CA
> All Tasks
> Start Service
2
3
4
CRL配布ポイントの準備
証明書の取り込みを行って下位CAを起動しようとすると以下のエラーに遭遇した。
The revocation function was unable to check revocation because the revocation server was offline. 0x80092013 (-2146885613 CRYPT_E_REVOCATION_OFFLINE)
メッセージの内容的に証明書に記載された『CRL Distribution Points(CRL配布ポイント)』からCRLを取得できないエラーのようである。
先に述べたように、CRLを取得可能な状態にしておく必要がありそうだ。
証明書に指定してある場所(=ルートCAの準備におけるCRL(証明書失効リスト)のエンドポイント)に下位CAがアクセスできるようにして、再度起動すると正常に起動できた。
サーバ証明書の発行
いよいよサーバ証明書の発行を行う。
手順は以下の2ステップ
- CSR(証明書署名要求)の作成
- 下位CAによる証明書の発行(署名要求への署名)
CSR(証明書署名要求)の作成
下位CAの時もそうだったが、証明書を発行するためにはまずCSRを作成する必要がある。商用CAであっても、自分でCSRを作成して、証明書の発行を依頼する流れとなるのが一般的だと思う。
CSRの生成自体は、opensslを利用したり、利用するHTTPサーバに同梱されているツールを利用したりといった方法がある。利用方法は探せばよいだけなので割愛する。
CSRの中を見る
作成した証明書署名要求のファイルをテキストエディタで開いてみる。
文字列を見た感じBase64でエンコードされていると思われる。
-----BEGIN CERTIFICATE REQUEST-----
MIICmjCCAYICAQAwVTELMAkGA1UEBhMCSlAxDjAMBgNVBAgTBVRva3lvMREwDwYD
(省略)
/iTVzlE26PGQ+4tQGrJZvF+4420iT5NSa69ZC0pqKhTFEXWEexeQ2kkQ548e9Q==
-----END CERTIFICATE REQUEST-----
2
3
4
5
ちなみに、デコードしてみるとバイナリファイルのようだった。(一部CN等々が確認できた)
openssl
を使えば、情報を確認することができる。
$ openssl req -noout -text -in ssltest.csr
Certificate Request:
Data:
Version: 1 (0x0)
Subject: C = JP, ST = Tokyo, O = CHARAGAKI, OU = KIBIDANGO, CN = SSLTEST01
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:c9:e5:52:38:1a:a3:40:4b:f1:c4:a1:98:4e:66:
(省略)
2a:d9
Exponent: 65537 (0x10001)
Attributes:
a0:00
Signature Algorithm: sha256WithRSAEncryption
21:f5:cb:24:50:c2:2d:60:cf:cf:2b:02:d9:d2:f5:aa:ec:6f:
(省略)
e7:8f:1e:f5
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
下位CAによる証明書の発行(署名要求への署名)
下位CAの証明書発行の流れをおさらいする。
- 下位CAが(自動で)証明書署名要求を作成
- ルートCAが署名要求を取り込む
- ルートCAが証明書を発行する
証明書を作成する観点でいえば、この「発行」とは「ルートCAの秘密鍵による署名」と言えるだろう。
今回もそれと同様である。
- 自前で証明書署名要求を作成
- 下位CAが署名要求を取り込む
- 下位CAが証明書を発行する
下位CAでの証明書の発行もルートCAで行ったのと同様で良い。はずではあるが、要求ファイルを送信(=署名要求の取り込み)しようとすると以下のエラーが発生した。
The request contains no certificate template information. 0x80094801 (-2146875391 CERTSRV_E_NO_CERT_TYPE) Denied by policy module 0x80094801, The request does not contain a certificate template extension or the Certificate Template request attribute.
テンプレート情報への対応
エンタープライズ CA では、証明書テンプレートを使用します。 証明書が発行されると、エンタープライズ CA は証明書テンプレートの情報を使用してその証明書の種類に適した属性を持つ証明書を生成します。
エンタープライズCAの場合、証明書署名要求ファイルにテンプレート情報が含まれている必要があるようだ。
IBMサポートが、この現象に対しての解決策を提示してくれていた。
[IBM]The request contains no certificate template information
Use the certreq command on the command line to specify the appropriate certificate template for your environment (in the example below, the "CA11-SUN-SSL-C3-1" template is specified)
さらに調べた結果、以下のコマンドを実行して解決した。
certreq -submit -attrib "CertificateTemplate:WebServer" ssltest.csr
WebServer
のテンプレートを利用して要求を送る動作になるようだ。
実行すると証明書の保存場所の指定を求められる。場所を指定すると証明書が保存されている。ここまでで証明書の発行が完了した。
証明書発行後の対応
証明書を利用するように設定を行う。
ルート証明書を自前で作っているので、クライアントにルート証明書を取り込まないと、検証時に「信頼できない」みたいなメッセージが出ることになる。
学習のためのメモ
証明書の中を見る
CSRの中を見たのと同様に、証明書についてもopensslで見ることができる。
RootCA
下位CAの証明書を取り出すときにPKCS #7形式でエクスポートしたファイルの中に、ルートCAの証明書が含まれている。
*.p7bファイルを開く
> (rootCAの証明書を右クリックでOpen)
> (Details タブ)
> (Copy to file...をクリック)
> 「Base-64 encoded X.509(.CER)」にチェックでエクスポート
2
3
4
5
まずは、保存したファイルをテキストエディタで開いてみる。
-----BEGIN CERTIFICATE-----
MIIE/TCCAuWgAwIBAgIQELaLBWqfZrVH3lK9yNrSSDANBgkqhkiG9w0BAQ0FADAR
(省略)
jLqY8Naz3xMG59/tMfGoq7eUDZ7DqCpXf+LHo9GBaFVd
-----END CERTIFICATE-----
2
3
4
5
opensslで確認する
$ openssl x509 -text -noout -in rootca.cer
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
10:b6:8b:05:6a:9f:66:b5:47:de:52:bd:c8:da:d2:48
Signature Algorithm: sha512WithRSAEncryption
Issuer: CN = rootCA
Validity
Not Before: May 2 08:27:47 2020 GMT
Not After : May 2 08:37:45 2030 GMT
Subject: CN = rootCA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (4096 bit)
Modulus:
00:cc:6c:f6:a9:55:8f:58:25:4f:4f:e7:42:0c:29:
(省略)
71:3b:b5
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage:
Digital Signature, Certificate Sign, CRL Sign
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Subject Key Identifier:
4C:02:E7:47:1D:2C:05:5F:37:3B:EB:F7:6E:F2:BB:D0:1A:02:29:08
1.3.6.1.4.1.311.21.1:
...
Signature Algorithm: sha512WithRSAEncryption
98:44:4b:68:e1:8f:f8:c8:9e:eb:c4:12:c6:43:6c:24:e6:e9:
(省略)
e2:c7:a3:d1:81:68:55:5d
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
『Issuer』も『Subject』も CN = rootCA
となっている。
要はルート証明書は自己署名証明書だということだ。
SubordinateCA
こちらもルートCAの手順と同様に証明書をエクスポートする。
-----BEGIN CERTIFICATE-----
MIIG0jCCBLqgAwIBAgITRAAAAAKXdsGsnww9owAAAAAAAjANBgkqhkiG9w0BAQ0F
(省略)
Ko8PNvxggcfAMt+Rzi30at5uihdf9A==
-----END CERTIFICATE-----
2
3
4
5
opensslで確認する
$ openssl x509 -text -noout -in subordinateca.cer
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
44:00:00:00:02:97:76:c1:ac:9f:0c:3d:a3:00:00:00:00:00:02
Signature Algorithm: sha512WithRSAEncryption
Issuer: CN = rootCA
Validity
Not Before: May 3 02:51:09 2020 GMT
Not After : May 3 03:01:09 2021 GMT
Subject: DC = local, DC = kibidango, CN = subordinateCA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (4096 bit)
Modulus:
00:a2:a7:96:6f:d4:8c:72:14:3f:21:69:dc:3d:38:
(省略)
cb:08:51
Exponent: 65537 (0x10001)
X509v3 extensions:
1.3.6.1.4.1.311.21.1:
...
X509v3 Subject Key Identifier:
87:D3:47:E2:14:6D:88:F2:D3:C0:D4:E3:1D:A5:9D:10:84:3F:2E:83
1.3.6.1.4.1.311.20.2:
.
.S.u.b.C.A
X509v3 Key Usage:
Digital Signature, Certificate Sign, CRL Sign
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Authority Key Identifier:
keyid:4C:02:E7:47:1D:2C:05:5F:37:3B:EB:F7:6E:F2:BB:D0:1A:02:29:08
X509v3 CRL Distribution Points:
Full Name:
URI:file:////WIN-CHARAGAKI/CertEnroll/rootCA.crl
URI:http://certificate-authority.local/cert-data/rootCA.crl
Authority Information Access:
CA Issuers - URI:file:////WIN-CHARAGAKI/CertEnroll/WIN-CHARAGAKI_rootCA.crt
CA Issuers - URI:http://certificate-authority.local/cert-data/rootCA.crt
Signature Algorithm: sha512WithRSAEncryption
23:28:dd:7b:1b:c2:99:03:b1:cc:be:02:b3:c6:4d:54:3f:41:
(省略)
f4:6a:de:6e:8a:17:5f:f4
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
『Issuer』が CN = rootCA
に対して『Subject』が DC = local, DC = kibidango, CN = subordinateCA
となっている。
ルートCAによって、下位CAに対する証明書が発行されていることがわかる。
また、『X509v3 CRL Distribution Points』 に http://certificate-authority.local/cert-data/rootCA.crl
が指定されており、CRLのエンドポイントの設定が反映されていることがわかる。
サーバ証明書
-----BEGIN CERTIFICATE-----
MIIGVDCCBDygAwIBAgITUQAAAAmEoeArifHhXgAAAAAACTANBgkqhkiG9w0BAQ0F
(省略)
uneAcCOeW4LVZy5p4qb1b3wI4tmZgg4/gQ0mxbMhD+Nfolv92HSNkw==
-----END CERTIFICATE-----
2
3
4
5
さらにopensslで確認する。
$ openssl x509 -text -noout -in ssltest.cer
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
51:00:00:00:09:84:a1:e0:2b:89:f1:e1:5e:00:00:00:00:00:09
Signature Algorithm: sha512WithRSAEncryption
Issuer: DC = local, DC = kibidango, CN = subordinateCA
Validity
Not Before: May 4 14:00:36 2020 GMT
Not After : May 3 03:01:09 2021 GMT
Subject: C = JP, ST = Tokyo, O = CHARAGAKI, OU = KIBIDANGO, CN = ssltest
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:c9:e5:52:38:1a:a3:40:4b:f1:c4:a1:98:4e:66:
(省略)
d5:22:2b:97:60:d0:86:a3:bd:b0:82:15:b0:e2:c7:
2a:d9
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
59:3A:49:27:A8:B6:E9:29:4B:96:1E:A1:E2:47:C9:73:27:A3:40:68
X509v3 Authority Key Identifier:
keyid:87:D3:47:E2:14:6D:88:F2:D3:C0:D4:E3:1D:A5:9D:10:84:3F:2E:83
X509v3 CRL Distribution Points:
Full Name:
URI:ldap:///CN=subordinateCA,CN=WIN-CHARAGAKI,CN=CDP,CN=Public%20Key%20Services,CN=Services,CN=Configuration,DC=kibidango,DC=local?certificateRevocationList?base?objectClass=cRLDistributionPoint
Authority Information Access:
CA Issuers - URI:ldap:///CN=subordinateCA,CN=AIA,CN=Public%20Key%20Services,CN=Services,CN=Configuration,DC=kibidango,DC=local?cACertificate?base?objectClass=certificationAuthority
1.3.6.1.4.1.311.20.2:
...W.e.b.S.e.r.v.e.r
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication
Signature Algorithm: sha512WithRSAEncryption
8d:e7:c0:9f:14:ea:a1:d9:dc:82:e7:58:7e:68:08:76:28:21:
(省略)
5f:a2:5b:fd:d8:74:8d:93
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
『X509v3 CRL Distribution Points』 の部分が、ldap:*
になってしまっている。
AD DSのドメイン環境下であればこれでも良いと思うが、ドメインの外側で利用する場合、クライアント証明書の失効状況を確認することができない。これもルートCAの設定同様、下位CAにおいてもCRLのエンドポイントの設定をしておいた方がよいと思われる。
HTTPサーバを用意してCRLを公開する
今回は、CRLの配布エンドポイントとして、nginxでWebサーバを立ててることにした。
以下、Windowsにおける簡単な手順
Windows用のnginxをダウンロードする。https://nginx.org/en/download.html
zipファイルを解凍、適当な箇所に配置
回答したフォルダを開き、
html
フォルダをルートフォルダとして公開したいcrlファイルを配置する (以下のURLで公開したい場合、html/root-ca/rootca.crl
となるようにファイルを配置する。 http://localhost/cert-data/root-ca/rootca.crl)nginx.exe をダブルクリック
PKCSについて
In cryptography, PKCS stands for "Public Key Cryptography Standards". These are a group of public-key cryptography standards devised and published by RSA Security LLC, starting in the early 1990s.
PKCSは、「Public Key Cryptography Standards」の頭文字らしく、RSAセキュリティ社によって考案され公開されている「公開鍵暗号標準」の一連のまとまりを示すもののようだ。
PKCSについては以下が参考になった。
[IBM Knowledge Center]証明書のフォーマット
PKCS #7
PKCS #7はPKCS規格のうちの一つのようである。
PKCS #7 バイナリー証明書パッケージ のドキュメントには以下のように記されている。
1 つ以上の証明書 (図 1 に描かれているチェーンなどの証明書チェーン全体) を配布するのに使用されるパッケージです。 ほとんどの民間の認証局は、証明書を別々に配布するのではなく、便利 な PKCS #7 フォーマットを使用して、要求された複数の証明書を戻します。
ルートCAから下位CAの証明書をPKCS7形式で証明書をエクスポートする際も、「証明書チェーンに含まれる証明書を含むようにエクスポート」するオプションがあったので、1つの証明書だけでなく、証明書チェーンに含まれる複数の証明書の情報を含めることができるようである。
複数の証明書を含ることができるので、中間証明書等も含め、商用CAから送付されるファイルとして利用されるのだろう。
なお、PKCS #7はRFCとして公開されている。
[RFC2315]PKCS #7: Cryptographic Message Syntax Version 1.5
PKCS #12
PKCS #12は秘密鍵も含めることができる。秘密鍵と秘密鍵一式をセットにできるので、ファイルさえあれば、SSLの設定もできるHTTPサーバもあるようだ。
単一の証明書の(自分の)誤解
PKCS#7の説明を見て、
「あれ?でも *.cer
ファイル単体をダブルクリックして開いた時って証明書の連なりを追えて、それぞれの証明書の情報見れるから、末端の証明書に全部含まれているのでは?」
と思った。が、証明書の中を見たことで誤解だということに気が付いた。
サーバ証明書の中を見た通り、証明書のファイルには自身のことしか書かれていない。
下位CAのOS上でサーバ証明書のファイルをダブルクリックして開くと、証明書の連なりを追えるが、別のPCにサーバ証明書を移して同様にファイルを開くと、証明書の連なりを追うことはできなかった。
単体の証明書のファイルには自身の情報しか保持していないということだ。
参考
[@IT]Active Directory証明書サービスでセキュアな公開鍵基盤を構築する