SSLのサーバー証明書をVERIFYする(Windows)
例によって覚え書き。
前フリ
Windows上でOpenSSLを使ったクライアントアプリを作ったんだが、サーバーからもらった証明書をOpenSSLでVERIFYすると、X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY ってなエラーが出てしまう。
要するにOpenSSLでVERIFYする際にまともな証明書ストアを用意していないのが悪くて、ルート証明書の確認が出来ないよってことらしい。
アプローチとしては
のどちらか。前者は準備が面倒だし、おもしろくないので後者を採用。
本題
おもしろくないからっていう理由についてのツッコミはさておき、WindowsのCrypto APIの出番である。これ、めんどいんだよなー。
OpenSSLのリファレンスとかMSDNをちょろちょろ見ると、
- OpenSSLのSSL_CTX_set_cert_verify_callback()で自前VERIFY関数を登録。
- VERIFY関数に渡ってきたX509_STORE_CTXコンテキストを使って、i2d_X509()でサーバー証明書のバイナリデータ(DER)を抽出。
- CertCreateCertificateContext()でサーバー証明書を読み込む。
- CertGetCertificateChain()でサーバー証明書のチェインを列挙して、
- CertVerifyCertificateChainPolicy()でシステムの証明書ストアからVERIFY実行。
という流れ。1番目のi2d_X509()ってのはOpenSSLの関数。初めて使った。。
CertなにがしのAPIにいれる構造体がわけわからんのでうんざりしてたんだけど、Googleさんに聞いてみたら、でてきたよ。。→ 「Add peer certificate verification on windows」
なるほど。自己署名のはじき方ものってるな。よし。ってことで、完成!
Crypto APIはやっぱり面倒だった。
というお話でした。おわり。