ECDH通信をPHPで実装する
はじめに
現在、さまざまな通信において安全性や機密性を確保するために暗合化が行われています。
その中でもECDH(Elliptic-Curve Diffie–Hellman:楕円曲線ディフィー・ヘルマン鍵共有)は楕円曲線暗合のアルゴリズムの一つで、ポストRSA暗合として利用が広がっています。身近なところだとBluetoothの機器同士の通信に用いられていたり、銀行におけるSSL/TLSサーバの暗号アルゴリズムとして採用されていたりします。
今回、ECDHをphpで実装しようとしたきっかけは、プッシュ通知をサードパーティのサービスを利用せずにphpで実装したいと考えたためです。
プッシュ通知ではプッシュ通知送出元サーバーとServiceWorkerとの通信の暗号化にECDHが使われています。
ざっくりな概念
アリスとボブの2人が楕円曲線上で秘密鍵と公開鍵を生成し、お互いの公開鍵を交換したとする。
その上で自身の秘密鍵と相手の公開鍵の積をとると、アリス・ボブの双方が同一の楕円曲線上のx座標を得るので、これを共有鍵として復号に利用する。
〜詳細:wikipedia〜
アリスがボブとの間に共通鍵を構築したいが、2人の通信には第三者に盗聴される危険がある回線しかないものとする。まず、2人の間で使用する楕円曲線(つまり、有限体K、曲線を決定する3次式、ベースポイントG、その位数nなどのパラメータ)を決めておく。そして、両者はこの楕円曲線上で、秘密鍵のd ([1,n-1]からランダムに選んだ整数)と公開鍵のQ(Q=dG、つまり楕円曲線上での掛け算を行う)からなる鍵対を生成しておく。ここで、アリスの鍵対を(dA,QA)、ボブのものを(dB,QB)とする。それから、公開鍵を互いに交換する。
次に、アリスは(xk,yk)=dAQBという計算を、ボブは(xk,yk)=dBQAという計算を行う。
dAQB = dAdBG = dBdAG = dBQAであるので、アリスもボブも同じxk(楕円曲線上のx座標)を得ることができるので、これを共有する秘密とする。ECDHを元にしたほとんどの規格化プロトコルでは、この秘密を元に、ハッシュ関数などを利用して共通鍵を生成する。
〜〜
PHPで実装できるか
調べるとNode.jsではChromeの開発チームがライブラリを出しており、簡単にECDHを用いたプッシュ通知が実装できます。
ECDHが使われ始めたのは2000年代初頭。
それに対しPHPは1990年代生まれの比較的古参のプログラミング言語なので、もしかしたらECDHのアルゴリズムを実現するライブラリは無いのかも…と感じ始めていましたが
ついにphpeccという使えそうなライブラリを発見しました!!
Matyas DanterさんというVMwareのエンジニア様が開発したようです\(^^)/ この世にはすごい人がいるものです。
これを用いると鍵交換から共有鍵を取得するところの実装が可能です。
1 2 3 4 5 6 | $alicePriv = $pemPriv->parse(file_get_contents(__DIR__ . '/../tests/data/openssl-secp256r1.pem')); $bobPub = $pemPub->parse(file_get_contents(__DIR__ . '/../tests/data/openssl-secp256r1.1.pub.pem')); $exchange = $alicePriv->createExchange($bobPub); $shared = $exchange->calculateSharedKey(); echo "Shared secret: " . gmp_strval($shared, 10).PHP_EOL; |
これでPHPでもプッシュ通知の実装ができそうです。(firebaseを使え!とか言わないでくださいね^^;)
所感
PythonやGoなど新しいプログラミング言語が人気のなか、Web制作においてPHPが未だ広く使われているのは、このようなライブラリを作成してくれるPHPerの有志のおかげだな〜と実感しました。
Author Profile
スターフィールド編集部
SHARE