2015/05/15

[PHP] PHPでopensslコマンドと相互運用できる暗号を作成する

Linuxコンソールで復号可能な暗号を生成する場合、よく使うのはopensslコマンドだと思いますが、コンソールで生成した暗号をPHPで復号化できないものかとmcryptは使わない方向で色々試行錯誤してみました。




暗号化を構成する要素の関係性を理解する

まずは簡単に暗号化の手順や内部のロジックを図解してくれているサイトがあったので、そちらでサラっと概要を確認します。 → 図説:PKCS#5秘密鍵をパスワード保護する共通鍵とIVの作り方(記事修正)

相互運用できるAES-256-CBC形式暗号の作成

色々やってみた結果、思ったのは、opensslの暗号は脆い、という事です。
どの部分が脆いかと言うと、コード内にもコメントを残しておりますが、「key、iv」のセットを作成する際のハッシュ化を1回しか回していない部分ですね。
なので、実際の運用においては、コマンドラインからも暗号化、復号化できるツールも合わせて作成した方が暗号強度も上がるし、自由度も上がるかと思います。

今回使った暗号形式は「AES-256-CBC」という今現在強度的にも問題ないだろうと言われている形式「AES-256」とCBCというモードで暗号化するやり方です。

最終的な暗号化を行う部分は、openssl_encrypt関数で問題ないですが、php.netにはろくな情報が載っていないので、正直困りました。

キモになるのは、「key、iv」のセットを作成する部分をopensslコマンド相当の実装で用意する部分になります。
/**
 * @param string $password 任意の文字列
 * @param string $salt 16進数に変換可能な文字列(暗号形式によって長さは異なる)
 */
function create_key_iv($password, $salt){
 $salt_bin = hex2bin($salt);
 $hash_str = $hash = '';
 // opensslはハッシュを1回しかしないが、セキュリティの事を考えると複数回ハッシュ化させた方がよい
 for ($i=0; $i<1; $i++){
  $hash = md5($hash. $password. $salt_bin, true);
  $hash_str .= $hash;
 }
 // 取り急ぎ AES-256-CBCに寄せておく
 $key = substr($hash_str, 0, 32);
 $iv = substr($hash_str, 32, 16);
 
 return array($key, $iv);
}

list($key, $iv) = create_key_iv("hogehoge", "12345678");

md5でハッシュ生成している辺りが気になりますが、openssl標準のやり方はこのようになっているみたいです。

チューニングのポイントはハッシュ回数とハッシュ形式でしょうか。
回数は数千回回しても不安が残る人たちからすると、1回なんてありえないでしょうね。
ハッシュ形式も、今はsha256なども選べますし、ミックスする事もできますね。


0 件のコメント:

コメントを投稿