HKDF(HMAC-based Key Derivation Function)はセキュリティにおいて非常に重要な役割を果たす技術です。PHPのhash_hkdf
関数を使えば、この強力な鍵導出機能を簡単に実装できます。今回は、この関数の使い方から実践的な応用例まで詳しく解説します。
hash_hkdf関数とは?
hash_hkdf
関数は、暗号学的に安全な方法で、あるキーマテリアル(初期秘密情報)から一つ以上の強力な鍵を導出するために使用されます。RFC 5869で定義されたHKDFアルゴリズムを実装しており、PHP 7.1.2以降で利用可能です。
基本構文
string hash_hkdf(string $algo, string $key, int $length = 0, string $info = '', string $salt = '')
パラメータ
$algo
: 使用するハッシュアルゴリズム(sha256, sha512など)$key
: 鍵導出の元になる初期キーマテリアル$length
: 出力鍵の長さ(バイト単位、0の場合はアルゴリズムの出力サイズ)$info
: アプリケーション固有の情報(コンテキスト情報)$salt
: オプションのソルト値(ランダムな非秘密値)
戻り値
- 導出された鍵(バイナリ文字列)
HKDFの仕組み
HKDFは2段階のプロセスを持ちます:
- 抽出(Extract): 初期キーマテリアルとソルトから擬似ランダム鍵(PRK)を生成
- 拡張(Expand): PRKとinfoからアプリケーション固有の出力鍵材料を生成
このプロセスは、弱いキーマテリアルから強力な暗号鍵を安全に派生させることができます。
実践的な使用例
例1:基本的な使用法
// 基本的な鍵導出
$masterKey = 'original-secret-key';
$derivedKey = hash_hkdf('sha256', $masterKey, 32, 'encryption-context', 'random-salt');
// バイナリキーを16進表記に変換して表示
echo "導出された鍵: " . bin2hex($derivedKey);
例2:複数の異なる鍵の導出
$masterSecret = 'master-application-secret';
$salt = random_bytes(16); // ランダムなソルト生成
// 暗号化用の鍵
$encryptionKey = hash_hkdf(
'sha256',
$masterSecret,
32,
'encryption-key-purpose',
$salt
);
// 認証用の鍵
$authenticationKey = hash_hkdf(
'sha256',
$masterSecret,
32,
'authentication-key-purpose',
$salt
);
echo "暗号化鍵: " . bin2hex($encryptionKey) . "\n";
echo "認証鍵: " . bin2hex($authenticationKey) . "\n";
例3:セッション管理での実装例
function generateSessionToken($userId) {
$masterKey = getApplicationSecret(); // アプリケーションのマスターシークレット
$salt = random_bytes(16);
// ユーザーIDと現在時刻を情報として含める
$info = "session-token:{$userId}:" . time();
$sessionKey = hash_hkdf('sha256', $masterKey, 32, $info, $salt);
// セッションストレージに保存
$_SESSION['token_salt'] = bin2hex($salt);
return bin2hex($sessionKey);
}
function verifySessionToken($userId, $providedToken) {
$masterKey = getApplicationSecret();
$salt = hex2bin($_SESSION['token_salt']);
// 同じ情報を使用して鍵を再生成
$info = "session-token:{$userId}:" . time();
$expectedToken = hash_hkdf('sha256', $masterKey, 32, $info, $salt);
return hash_equals(hex2bin($providedToken), $expectedToken);
}
hash_hkdfを使うメリット
- 標準化: RFC 5869で定義された標準的な方法
- セキュリティ: 暗号学的に安全な鍵導出
- 柔軟性: 一つのマスターキーから複数の独立した鍵を導出可能
- コンテキスト分離:
info
パラメータにより、同じマスターキーから異なる目的の鍵を安全に分離
ユースケース
パスワードハッシュからの鍵導出
function deriveEncryptionKeyFromPassword($password, $username) {
// パスワードハッシュを入力として使用
$passwordHash = password_hash($password, PASSWORD_ARGON2ID);
// ユーザー名をソルトとして使用(理想的にはより強いソルトを使用)
$salt = hash('sha256', $username, true);
// 32バイト(256ビット)の暗号化鍵を導出
$encryptionKey = hash_hkdf(
'sha256',
$passwordHash,
32,
'data-encryption-key',
$salt
);
return $encryptionKey;
}
APIキー生成
function generateApiKeys($accountId) {
$masterSecret = getSystemMasterKey();
$accountSalt = getAccountSpecificSalt($accountId);
// 公開APIキー
$publicKey = hash_hkdf(
'sha256',
$masterSecret,
16,
"api-public-key:{$accountId}",
$accountSalt
);
// 秘密APIキー
$privateKey = hash_hkdf(
'sha256',
$masterSecret,
32,
"api-private-key:{$accountId}",
$accountSalt
);
return [
'public_key' => bin2hex($publicKey),
'private_key' => bin2hex($privateKey)
];
}
安全な使用のためのベストプラクティス
- 強力なアルゴリズム: 少なくともSHA-256以上のハッシュアルゴリズムを使用する
- 適切な長さ: 用途に合わせた十分な長さの鍵を生成する(通常32バイト以上)
- ランダムなソルト: 可能な限り暗号学的にランダムなソルトを使用する
- 具体的なinfo値: 鍵の用途を明確に示す具体的なinfo値を使用する
- マスターキーの保護: 元となるマスターキーは厳重に保護する
hash_hmacとの違い
hash_hmac
とhash_hkdf
は関連していますが、目的が異なります:
関数 | 主な目的 | 用途 |
---|---|---|
hash_hmac | メッセージ認証 | データの整合性と認証の検証 |
hash_hkdf | 鍵導出 | 一つのマスターキーから複数の暗号鍵を導出 |
まとめ
hash_hkdf
関数は、PHPアプリケーションにおいて安全な鍵管理を実装するための強力なツールです。暗号化、認証、トークン生成など、さまざまなセキュリティ用途に適用できます。適切な方法で使用することで、アプリケーションのセキュリティレベルを大幅に向上させることができます。
特に複数のサービスや機能が同じシステム内で動作する現代のウェブアプリケーションでは、一つのマスターキーから複数の独立した鍵を安全に導出できるhash_hkdf
の価値は非常に高いものと言えるでしょう。セキュアなアプリケーション開発の基本ツールとして、ぜひ活用してみてください。