PHP 7.1で追加された hash_hkdf() は出鱈目なシグニチャを持っています。バイナリキーを使うことを想定して、わざわざ既存のハッシュ関数とは異なり、バイナリハッシュ値だけを返せるようになっています。
暗号化がプログラム内で完結する、といった極一部の例外を除きhash_hkdf()でわざわざバイナリキーを使う意味はありません。
CSRFキーを守る、URLを守る、APIキーを守る、といったWebアプリケーションで最も頻繁に使われる鍵導出ではバイナリキー/バイナリSaltは、遅いのでむしろ有害と言えます。わざわざバイナリを使う必要はありません。
参考: HMACハッシュの使い方のまとめ – HAMCですが、HKDFはHMAC based Key Derivation Functionです。多くがHKDFで置き換えられます。HKDFが使える場合、hash_hkdf()を使った方が速くなるでしょう。これはPHPの関数呼び出しのオーバーヘッドが比較的大きいことに起因します。
テストコード
<?php $key = bin2hex(random_bytes(32)); $salt = bin2hex(random_bytes(32)); $lim = 1000000; $start = microtime(true); for($i=0; $i<$lim; $i++) { hash_hkdf('sha256', $key, 0, null, $salt); } echo 'HEX: '. (microtime(true) - $start) . PHP_EOL; $start = microtime(true); for($i=0; $i<$lim; $i++) { hash_hkdf('sha256', hex2bin($key), 0, null, hex2bin($salt)); } echo 'BIN: '. (microtime(true) - $start) . PHP_EOL;
このテストコードでは、最初にHEX、次にバイナリのキー/Saltを使っています。ハッシュ関数の特性として”同じエントロピー”ならハッシュのサイズと同じキーとSalt”を使うと最も性能的に有利かつ最大限の安全性を得られます。(つまり、バイナリの方がハッシュ関数の仕組みとして有利)
C言語ならバイナリのキー/Saltを使った方が速くなる可能性が高いです。しかし、言語が変わると”関数呼び出しオーバーヘッド”が加わります。
テスト結果
[yohgaki@dev 201703]$ php test.php HEX: 3.8135788440704 BIN: 4.2421109676361
PHPの場合、HEX値のキー/Saltの方が速いです。
まとめ
コードや設定ファイルにバイナリ値のキーを保存することは出来ません。(できますが、お薦めできません)テキストインターフェースが中心のWebではSaltをバイナリで渡す事もできません。キーやSaltは普通、”テキスト”です。
hash_hkdf()を使う場合、わざわざバイナリ値のキー/Saltを使わずに普通にHEX値を使いましょう。hash_hmac()も同様です。
API設計として一から十までダメなhash_hkdf()ですが、便利な関数なので活用しましょう。