やりたいこと
「サイトA」で作成したメッセージを、POSTで「サイトB」に渡して、ツイッターに投稿するプログラムを作りたい。
問題点
・サイトBで受け取ったメッセージをそのままツイートしてしまうと、適当なメッセージを投げられて、ツイートの踏み台にされてしまう。
・サイトAのメッセージを改ざんされると、そのままその文言を投稿してしまう。
解決策
公開鍵暗号方式で電子署名を作成する。
サイトAにメッセージと、それを秘密鍵で暗号化したトークンを用意する。
サイトBでメッセージとトークンを受け取り、トークンを公開鍵で複合化する。
メッセージと複合化で得られたテキストが一致すれば、サイトAに表示されていたメッセージだとわかる。
※秘密鍵で暗号化して、公開鍵で複合化すれば電子署名になる。
公開鍵で暗号化して、秘密鍵で複合化すれば暗号通信になる。
実践編
鍵の作成
//秘密鍵作成(用途によって2048にする)
openssl genrsa 1024 > private-key.pem
//秘密鍵からペアの公開鍵を作成する。
openssl rsa -pubout -in private-key.pem -out public-key.pem
※「-pubout」オプションで秘密鍵から公開鍵を作成するらしい。
コーディング
//秘密鍵で暗号化
$data="ツイート文字列";
$keyPath = 'private-key.pem';
$key = file_get_contents($keyPath);
openssl_private_encrypt($data, $crypted, $key);
print('<p class="item invisible" data-token='.base64_encode($crypted).'>'.$data.'</p>');
//ツイートするプログラムでトークンを検証
$data = $_POST['data'];
$token = $_POST['token'];
//トークンを公開鍵で複合化
$decodeToken = base64_decode($token);
$keyPath = 'public-key.pem';
$key = file_get_contents($keyPath);
openssl_public_decrypt($decodeToken, $decrypted, $key);
//data(ツイートワード)と複合化したトークンが違っていればエラー
if($data <> $decrypted){
throw new Exception('バリデートエラー');
}
ちなみに公開鍵での暗号化秘密鍵での複合化は下記関数で同じようにできる。
openssl_public_encrypt(公開鍵で暗号化)
openssl_private_decrypt(秘密鍵で複合化)