Bitcoinを決済に利用する際に、決済先との間の中間者攻撃やマルウェアなどに感染した環境で、本当の支払先でないアドレスに送金するといったことが起きないよう、送金先をPKIを使って検証する仕組みがBIP-70で定義されているPayment Protocol↓
techmedia-think.hatenablog.com
bitcoinrbでもこれらのプロトコルに対応しようと思って、動作検証する環境をまず作ってみた。
BIP-70自体にはTest Vectorは掲載されていないけど、BIP-70の著者の1人であるGavin AndresenがPayment Protocolのデモ環境を公開してたのでそれを使ってみる↓
(以前はbitcoincore.orgのサイトでこれがホストされてたっぽいけど、今はなくなってる。)
Payment Requestのテスト環境のセットアップ
↑では以下のツールが提供されてる。
まず以下のライブラリをインストールしておく。
- memcached
- openssl
テスト用の証明書とルート認証局の作成
BIP-70はPKIを利用して決済先の情報を検証するので、テスト用にルート認証局と、その認証局が発行した決済先用の証明書を作成する。
↑のリポジトリのca_in_a_box
にテスト用の認証局と証明書を作成するスクリプトが用意されてるのでそれを実行するだけ。
$ cd ca_in_a_box $ ./sh create_ca.sh CA: Creating self-signed root certificate authority (CA) certificate: Generating a 2048 bit RSA private key .....+++ ............+++ writing new private key to './private/cakey.pem' ----- MERCHANT: Creating merchant private key and certificate signing request (CSR): ..++++++ ...................++++++ CA: Issuing new merchant certificate Using configuration from openssl.cnf Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows commonName :ASN.1 12:'testmerchant.org' organizationName :ASN.1 12:'Payment Request Test Merchant' Certificate is to be certified until Mar 11 05:27:23 2028 GMT (3650 days) Write out database with 1 new entries Data Base Updated Done. Root CA certificate is certs/cacert.pem Merchant certificate is certs/demomerchant.pem , private (signing) key is private/demomerchantkey.pem
スクリプトの中身はopensslコマンドを使って、認証局とマーチャントの証明書のファイルを作ってるだけで、実行が完了するとcerts
ディレクトリができ、そこに認証局とマーチャントの証明書が作成され、private
ディレクトリに認証局とマーチャントの秘密鍵が格納される。
certs/cacert.pem
ルート認証局の証明書certs/demomerchant.pem
マーチャントの証明書private/demomerchantkey.pem
マーチャントの証明書の秘密鍵
ちなみに生成されたマーチャントの証明書が
X509v3 extensions: X509v3 Basic Constraints: CA:TRUE
とCAの証明書になってたりする。同じopenssl.cnf使ってるからそのオプションのせいっぽい。なのでこれで証明書作ららなくても自前で認証局とマーチャントの証明書作る方がいいかも。
PHPのデモサイト
依存ライブラリの関係でPHP5系でしか動作しないみたいなので、PHP7系でなくPHP5系の環境が必要。今回はphpenv使ってPHP5.6.34を入れる。何気にPHPの環境用意するのが一番面倒だった。。
最初にphpenvをインストール↓
参考:phpenvで最新版のPHPをインストールしてWebサイトで使用する - Qiita
PHP 5.6.34のインストール時にpearも欲しかったので以下のように--with-pear
を指定する。
$ CONFIGURE_OPTS="--with-pear" phpenv install 5.6.34
続いて、PHPでProtocol Bufferを扱うのに必要なProtobuf-PHPをインストールする。
$ pear channel-discover pear.pollinimini.net $ pear install drslump/Protobuf-beta
続いてmemcacheモジュールをインストールするんだけど、pearやpeclでは見つからなかったのでソースをダウンロードしてきてビルドした。
$ wget https://pecl.php.net/get/memcache-3.0.8.tgz $ tar xvfz memcache-3.0.8.tgz $ cd memcache-3.0.8 $ CFLAGS="-fgnu89-inline" ./configure $ make $ make install
./configureを実行する際にCFLAGS="-fgnu89-inline" しておかないと後でエラー吐く。
以上でセットアップは環境。
後は簡単で、paymentrequestをcloneしてdemo_websiteをrootに指定して実行し、
$ php -S localhost:8000 -t <clonしてきたパス>/paymentrequest/php/demo_website
http://localhost:8000/createpaymentrequest.php
にアクセスすると↓のような画面が表示される。
証明書とその秘密鍵のロケーションを変更
PaymentRequestsを作成する際に、PKIの署名データが付与されるんだけど、この署名を生成するのに証明書を作成する際に使用した秘密鍵が必要になる。
証明書と鍵のロケーションは/home/gavin/.certs/
以下のハードコードされてるので、
自分の環境に合わせて書き換える必要がある。
// 証明書 $leafCert = file_get_contents("使用するマーチャント証明書ファイルのパス"); ... // 鍵 $priv_key = file_get_contents("使用するマーチャント秘密鍵ファイルのパス");
書き換えたら、↑のURLにアクセスして、最低限アドレスと量(Amount)を入力して、「Create Payment Request」を押せばPayment Requestのメッセージがダウンロードできる。
データを確認すると、Payment Requestのsignature
には↑のマーチャントの秘密鍵を使って生成した署名データがセットされている。
Payment Requestのpki_data
には、仕様的には、まず必須なのが最初に↑のマーチャントの証明書がセットされ、それ以降は任意でその証明書からルート証明書までの証明書のチェーンが一式セットされるようになってる。PHPのデモコードではX.509証明書の拡張プロファイルのauthorityInfoAccess
に記載されているURIから親の証明書を辿る仕組みになってるんだけど、↑で生成した証明書にはこのプロファイルが入ってないので、親が辿れず↑のメッセージにはマーチャントの証明書しか入ってない。
なので、PHPのコードを書き換えて↑の認証局の証明書まで含めるようにするか、↑のテスト用の証明書をメッセージを受け取ったクライアント側のOSに仕込んで証明書チェーンを検証するかする必要がある。まぁ実際にルート証明書が入っていないケースも考慮すべきなので、後者の方法を取る方がいいかな。
と、一応動く検証環境はできたけど、環境周りや設定変更とか必要なので、検証終わったらSinatraで簡単なAPIとか作りたいなー。