マイ備忘録

あくまで個人の意見、メモです。

証明書とか

とある事情で使っていたクライアント証明書の期限が切れたので、発行手順まとめとく(あくまで何をやってるかだけ)。 この辺あんまわかってないから整理も兼ねて。

構成は認証用のproxyサーバとしてnginxを前段に立てていて、認証成功したらバックエンドのサーバにproxyしてる。 で、このproxyサーバがオレオレサーバ。そこで発行したクライアント証明書をクライアント端末にインストールする形となる。


HTTPSでの通信の流れ(主にSSL/TLSハンドシェイク)

作業とは関係ないけどメモがてら。

0. 最初
  • ブラウザでhttps://xxxxにアクセスすると、Webサーバの443ポートにTCPで接続する
    • TCPの3wayハンドシェイクのあと、SSL/TLSハンドシェイク開始
1. クライアント -> サーバ
  • 3wayハンドシェイク後に続けてクライアントからClientHelloを送る
    • 対応している暗号スイートや鍵交換アルゴリズム、鍵生成に使用する乱数など、必要な情報をサーバに送る
2. サーバ -> クライアント
  • ClientHelloを受信後に問題なければServerHelloを送る
    • SSL/TLSプロトコルばーじょんや、合意した暗号スイートやサーバ側の乱数などをクライアントに送る
  • 続けてサーバ側の証明書を送る(ServerCertificate)
  • Diffie-Hellmanであればサーバ側からサーバ鍵交換メッセージを送る(ServerKeyExchange)
  • 必要であればサーバからクライアント証明書のリクエスト(CertificateRequest)
  • ServerHelloDoneを送る
    • サーバ側のHelloが終わったことを示すメッセージ。これを送った後、サーバはクライアントからのリクエストを待つ。
3. クライアント -> サーバ
  • クライアント証明書を送る(ClientCertificate)
    • サーバからの要求があれば送る
  • クライアント側で生成したmaster secret or pre master secretをサーバに送る(ClienetKeyExchange) -クライアント証明書を送っていれば、その証明書に対する署名データを送る(CertificateVerify)
  • 以降の通信が暗号化されることを通知(ChangeCipherSpec)
    • 実際にはTLSハンドシェイクメッセージではなく、独立した TLS プロトコルコンテンツ種別
    • ハンドシェイクレコードの中のメッセージではない
  • クライアントがサーバ認証に成功し、共通鍵を共有できたことを通知する(Finished)
4. サーバ -> クライアント
  • クライアントからのChange Cipher Spec を受信したサーバも、以降の通信が暗号かされることを通知(ChangeCipherSpec)
  • クライアントに共通鍵を共有できたことを通知する(Finished)

以上でハンドシェイク完了

参考

TLS Protocol Version 1.2

サンプル トランザクションおよびパケット交換による SSL の概要 - Cisco

HTTPSコネクションの最初の数ミリ秒

SSLのはなし|Wireless・のおと|サイレックス・テクノロジー株式会社

https://www.digicert.co.jp/welcome/pdf/wp_ssl_negotiation.pdf



クライアント証明書作成


0. サーバ側の秘密鍵、公開鍵、証明書署名要求(CSR)準備

すでに用意してあった。 ちなみに、CSRはサーバ側の公開鍵と秘密鍵のハッシュが含まれている。証明書署名要求はこの情報を認証局に送る作業。

1. プライベート認証局の証明書作成

オレオレサーバなのでサーバが認証局も兼ねている。 サーバと同様に認証局秘密鍵(cakey.pem)と公開鍵&証明書(cacert.pem)を作成する(openssl.confの設定は済んでた)

2. プライベート認証局の署名入りサーバ証明書作成

認証局秘密鍵CSRを使って署名入りのサーバ証明書を作成。 ちなみに、署名とは改ざんを防ぐためにサーバからもらったダイジェスト(ハッシュ値)に対して認証局秘密鍵を使って暗号化を行うこと。

3. クライアント証明書の作成

クライアント証明書用の秘密鍵CSRを作成

4. プライベート認証局の署名入りクライアント証明書作成

認証局秘密鍵CSRを使って署名入りのクライアント証明書を作成。 作成した証明書をPKCS#12形式にフォーマットに変換する。

あとは作成した鍵やら証明書やらを所定のディレクトリに配置して作業完了。

proxyサーバの設定

以下のような設定

ssl on;
ssl_certificate 'サーバ証明書のパス';
ssl_certificate_key 'サーバ証明書(中に含まれている公開鍵)の秘密鍵';
ssl_client_certificate 'クライアント証明書用のCA証明書のパス';
ssl_session_timeout 'SSLセッションキャッシュのタイムアウト設定'; 
ssl_verify_client on;  //  クライアント証明書を要求する(ハンドシェイク時にサーバからCertificateRequestが送られる)
ssl_verify_depth '証明書のチェーンを何階層までたどるかを設定';
ssl_protocols '対応SSLプロトコルバージョン';
ssl_ciphers '対応/非対応の暗号化スイート';
ssl_prefer_server_ciphers on; // サーバ側の暗号化スイートの設定を優先する



その他