こんばんは。今週はクライアント認証について勉強をしていたので、学んだことを記事にまとめておこうと思います。
Contents
クライアント証明書とは
- クライアント証明書とは、クライアントである個人や組織を認証するために発行される、電子証明書
- サーバ証明書がサーバにインストールされるのに対して、クライアント証明書はクライアント(接続元のデバイス)にインストールされる
- 現在、TLSの規格ではサーバ証明書は必須なのに対して、クライアント証明書は任意の扱い
なお、以下のサイトが漫画でとても分かりやすく解説してくれていました!
https://jp.globalsign.com/lp/epki/
クライアント証明書 認証とは
- クライアント証明書 認証とは、クライアントからサーバへアクセスを行う際に、サーバ側でクライアント証明書を検査して認証を行う方法
- クライアントからサーバへアクセスする際のアクセス制御で一般的なものとしては、ユーザ名とパスワードによる認証がある
- しかしながらこの方法では、ユーザ名とパスワードが漏洩すると、サーバへアクセスできてしまう
- こうしたリスクに対処するためにクライアント証明書 認証が登場した
- クライアント証明書 認証を利用することで、ユーザ名・パスワードによるアクセス制限よりも不正アクセスのリスクを軽減できる。また、ユーザ名・パスワードによる認証を不要にでき、ユーザの利便性も向上する
クライアント認証のフロー
こちらのサイトが分かりやすく解説してくれていました。
https://milestone-of-se.nesuke.com/sv-advanced/digicert/client-cert/
以下が要点です。
- 通信相手の認証を行うためには、事前に相手方の証明書のルート証明書を「信頼するルート証明書」としてインストールしている必要がある
- つまり、クライアント証明書認証の場合、認証を行うサーバ側で、クライアント証明書のルート証明書がインストールされている必要がある
- TCP 3Way Handshake、TLS Session確立の後、クライアントがサーバにクライアント証明書を要求して行われる
サーバ側からのクライアント証明書要求以降のフローは別サイトとなりますが、以下で分かりやすく図解してくれていましたので引用させていただきます。(3以降)
クライアント証明書を作成してみる
それでは、理解を深めるためにクライアント証明書を実際に作ってみようと思います!
クライアント証明書は、OpenSSLというオープンソースツールを利用して作成することができます。
手順については、こちらのブログを参考にさせていただきました。
OpenSSLを端末にインストールする
今回、OpenSSLを利用する環境として、ローカルのWindows端末を利用することにします。
Windows端末へのOpenSSLのインストールは、以下サイトで解説があるように、インストーラを配布しているWebサイト経由で行う方が簡単そうです。
https://atmarkit.itmedia.co.jp/ait/articles/1601/29/news043.html
2021年9月時点では、OpenSSL v3.0.0が最新なのでWin64 Open SSL v3.0.0のExeをダウンロード&インストールします。
インストール後、OpenSSLのbinがあるディレクトリに環境変数のPATHを通します。(私の場合、C:\Program Files\OpenSSL-Win64\bin)
パスを通し終わったら、コマンドプロンプトからOpenSSLコマンドを実行してみます。
openssl version
OpenSSLのセットアップが終わったところで、本題のクライアント証明書の作成に進みます。
秘密鍵の作成
最初に秘密鍵を作成します。
コマンド:
openssl genrsa -out client.key 1024
コマンドの解説:
https://www.openssl.org/docs/man1.0.2/man1/genrsa.html
・genrsa:RSA秘密鍵を作成します
・1024:numbitsという引数で、秘密鍵のビットサイズ。規定は2048
作成した秘密鍵の中身のサンプル:
-----BEGIN PRIVATE KEY-----
MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAM0tnW0pb+RurfYl
・・・・・
CF8qsm+ZG8h8md4C3ej8+wB3C8aP3gLngMplEWZb6NlEILe4LMTado/lU45UAX1p
QszD0XTe2Gv/7S2K
-----END PRIVATE KEY-----
X509証明書発行要求(CSR)の作成
次に、上で作成した秘密鍵を利用して、公開鍵証明書の発行要求を作成します。.csrファイルは、証明書発行要求ファイルの拡張子です。
コマンド:
openssl req -new -key client.key -out client.csr
コマンドの解説:
https://www.openssl.org/docs/man1.0.2/man1/openssl-req.html
・req:主にPKCS#10 formatの証明書リクエストを作成・処理するために利用される。また、ルートCAなどとして利用する自己署名証明書を作成することもできる。
・PKCS#10 format :Wikipediaに解説がありました。PKCSとは、Public-Key Cryptography Standardsの略で、公開鍵暗号標準です。このPKCSには、#1~#15まであり、それぞれが独立した暗号標準を定めています。#10は、自己署名要求のフォーマットを定めるための標準、ということのようです。また、この標準はRFC2986で定義されており(2000年に定められているのですね)、具体的にはASN.1という記法に従うようです。
https://ja.wikipedia.org/wiki/PKCS#10
作成した証明書発行要求ファイルの中身のサンプル:
-----BEGIN CERTIFICATE REQUEST-----
MIIBmjCCAQMCAQAwQDELMAkGA1UEBhMCSlAxDjAMBgNVBAgMBVRva3lvMSEwHwYD
・・・・
KfsuMJDvmSAp0oW+oDrflpRe8lUbj1q3WDTqwmZn
-----END CERTIFICATE REQUEST-----
余談ですが、この証明書要求ファイルの中身は以下のコマンドで解析することができるようです。ASN.1の記法は全くの所見でわからないですが、先ほど入力した申請者の情報が含まれたデータ構造になっていることはなんとなくわかりました。
https://ja.wikipedia.org/wiki/%E8%A8%BC%E6%98%8E%E6%9B%B8%E7%BD%B2%E5%90%8D%E8%A6%81%E6%B1%82
openssl asn1parse -in client.csr
0:d=0 hl=4 l= 410 cons: SEQUENCE
4:d=1 hl=4 l= 259 cons: SEQUENCE
8:d=2 hl=2 l= 1 prim: INTEGER :00
11:d=2 hl=2 l= 64 cons: SEQUENCE
13:d=3 hl=2 l= 11 cons: SET
15:d=4 hl=2 l= 9 cons: SEQUENCE
17:d=5 hl=2 l= 3 prim: OBJECT :countryName
22:d=5 hl=2 l= 2 prim: PRINTABLESTRING :JP
26:d=3 hl=2 l= 14 cons: SET
28:d=4 hl=2 l= 12 cons: SEQUENCE
30:d=5 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
35:d=5 hl=2 l= 5 prim: UTF8STRING :Tokyo
42:d=3 hl=2 l= 33 cons: SET
44:d=4 hl=2 l= 31 cons: SEQUENCE
46:d=5 hl=2 l= 3 prim: OBJECT :organizationName
51:d=5 hl=2 l= 24 prim: UTF8STRING :Internet Widgits Pty Ltd
77:d=2 hl=3 l= 159 cons: SEQUENCE
80:d=3 hl=2 l= 13 cons: SEQUENCE
82:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
93:d=4 hl=2 l= 0 prim: NULL
95:d=3 hl=3 l= 141 prim: BIT STRING
239:d=2 hl=2 l= 26 cons: cont [ 0 ]
241:d=3 hl=2 l= 24 cons: SEQUENCE
243:d=4 hl=2 l= 9 prim: OBJECT :challengePassword
254:d=4 hl=2 l= 11 cons: SET
256:d=5 hl=2 l= 9 prim: UTF8STRING :XXXXX
267:d=1 hl=2 l= 13 cons: SEQUENCE
269:d=2 hl=2 l= 9 prim: OBJECT :sha256WithRSAEncryption
280:d=2 hl=2 l= 0 prim: NULL
282:d=1 hl=3 l= 129 prim: BIT STRING
CSRにCAが署名して公開鍵証明書を発行
次に、CSRから公開鍵証明書を作成します。
コマンド:
openssl x509 -in client.csr -out client-ca.crt -req -signkey client.key -days 3650
コマンドの解説:
https://www.openssl.org/docs/man1.0.2/man1/x509.html
・X509:multi purpose certificate utilityとのこと。というわけで、その後に指定するオプションが重要そうです。
・-signkey filename:これが今回のコマンドのキモです。指定した秘密鍵を利用して、inputファイルをself sign(自己署名)します。inputが証明書と証明書発行要求の場合で動作が異なるようですが、後者の場合は自己署名証明書が作成されるようです。
作成したクライアント証明書(公開鍵証明書)の中身のサンプル:
-----BEGIN CERTIFICATE-----
MIICAjCCAWsCFHbLTzrYn8W3Jct241vsxRkifB2kMA0GCSqGSIb3DQEBCwUAMEAx
・・・・
DaCbNv1eEzDcsNsHCuyGirB9ewPk7wcRw3IPKWmzthWRtA491Ws=
-----END CERTIFICATE-----
秘密鍵と公開鍵証明書のペアをpkcs12でexportする
最後に、秘密鍵と公開鍵証明書(クライアント証明書)をペアとしてExportします。
openssl pkcs12 -export -inkey client.key -in client-ca.crt -out client.p12 -name "friendlyname"
ちなみに、.pfx形式でエクスポートしたい場合も、同じコマンドが使えます。
openssl pkcs12 -export -inkey client.key -in client-ca.crt -out client.pfx -name "friendlyname"
コマンドの解説:
https://www.openssl.org/docs/man1.0.2/man1/pkcs12.html
pkcs12:こちらも様々な用途があるようですが、pkcs12ファイルを作成するために使うようです。
-name friendlyname:”This name is typically displayed in list boxes by software importing the file.”
.p12ファイルの中身のサンプル:
うお・・・これはメモ帳では開けなかった・・・
p12ファイルは、クライアント証明書をはじめ様々な情報を含みます。openSSLのコマンドを使うとp12ファイルからそれらの情報を抽出できます。
こちらのブログが分かりやすかったです。
クライアント証明書を抜き出す:
https://www.openssl.org/docs/man1.0.2/man1/pkcs12.html
pkcs12 -in client.p12 -out client.cer(pem等も可) -clcerts
ここで取り出したクライアント証明書の中身を見てみます。
前半のBEGIN CERTIFICATE ~ END CERTIFICATEは、前のステップで作成した公開鍵証明書(client-ca.crt)と同一内容です。
Bag Attributes
friendlyName: keypair
localKeyID: 05 FE xxx
subject=C = JP, ST = Tokyo, O = Internet Widgits Pty Ltd
issuer=C = JP, ST = Tokyo, O = Internet Widgits Pty Ltd
-----BEGIN CERTIFICATE-----
MIICAjCCAWsCFHVVI4I20bXUUL930QtlURl6FA/5MA0GCSqGSIb3DQEBCwUAMEAx
CzAJBgNVBAYTAkpQMQ4wDAYDVQQIDAVUb2t5bzEhMB8GA1UECgwYSW50ZXJuZXQg
V2lkZ2l0cyBQdHkgTHRkMB4XDTIxMDkyMzE1MDAxM1oXDTMxMDkyMTE1MDAxM1ow
・・・・
BQADgYEAP2DDsTc0LulCf8Kok95lC9THph5Im+DcJC81bxui+t81tHbOUlbqGoGD
oG04ivdISJRAzx/LVbLTK5Kcwj6xcWwWwN5LuGJ4CTrnrxWI/VVIHw0j/U6L4iK/
FWkncT3o7JQOr1XbxvAel87wsqLiryfpJP0ulYndBNGtBaZXOLI=
-----END CERTIFICATE-----
Bag Attributes
friendlyName: keypair
localKeyID: 05 FE xxx
Key Attributes: <No Attributes>
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIC3TBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIkWAi4dG3px4CAggA
MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBDcFAVdYyzWUqtHKd6icEJOBIIC
gH+Z6d49oZVFPvUp0uueqmdu3B6sQkpoS2MC7l9pyJPxn4IWYSAd30iUn0wlG404
・・・・
WS8OrJjJ7ZYjUWjGGgCBvaxR+OtcfyRVEAbFuHgq/V+1r3xRtgfOB5mV5z26qetI
eXKogoYAgmaQjzyw0EZPFbM=
-----END ENCRYPTED PRIVATE KEY-----
クライアント証明書のインストール
最後に、作成した証明書をクライアントデバイスにインストールしてみたいと思います。pfxまたはpkcs12ファイルをクリックすると、以下のようにインポートウィザードが現れます。
この過程で、秘密鍵作成時のパスワードも必要になります。
証明書のインポートが完了すると、Windowsの証明書ストア(「ユーザ証明書の管理」>個人>証明書)から、該当の証明書が確認できるかと思います。
ここまでのステップで、実際にクライアント証明書を作成し、デバイスにインストールしてみることができました。
次の記事では、このクライアント証明書を利用して、クライアント証明書 認証を実装してみたいと思います。
本日も最後までご覧いただきありがとうございました。この記事が少しでもお役に立ちましたら、いいねボタンをぽちっていただけると励みになります・・!
つづく
pkcs12ファイルとは、個人情報交換構文の標準ということのようです。秘密鍵と、それに関連する公開鍵証明書を保管するために一般に利用されるファイルフォーマットの形式、ということのようです。pfxはpkcs12の旧称らしい。
https://ja.wikipedia.org/wiki/PKCS#12
こちらにもわかりやすい解説がありました。
https://qiita.com/kunichiko/items/3e2ec27928a95630a73a