[PHP]hash_hkdf関数完全解説:安全な鍵導出のためのベストプラクティス

PHP

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段階のプロセスを持ちます:

  1. 抽出(Extract): 初期キーマテリアルとソルトから擬似ランダム鍵(PRK)を生成
  2. 拡張(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を使うメリット

  1. 標準化: RFC 5869で定義された標準的な方法
  2. セキュリティ: 暗号学的に安全な鍵導出
  3. 柔軟性: 一つのマスターキーから複数の独立した鍵を導出可能
  4. コンテキスト分離: 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)
    ];
}

安全な使用のためのベストプラクティス

  1. 強力なアルゴリズム: 少なくともSHA-256以上のハッシュアルゴリズムを使用する
  2. 適切な長さ: 用途に合わせた十分な長さの鍵を生成する(通常32バイト以上)
  3. ランダムなソルト: 可能な限り暗号学的にランダムなソルトを使用する
  4. 具体的なinfo値: 鍵の用途を明確に示す具体的なinfo値を使用する
  5. マスターキーの保護: 元となるマスターキーは厳重に保護する

hash_hmacとの違い

hash_hmachash_hkdfは関連していますが、目的が異なります:

関数主な目的用途
hash_hmacメッセージ認証データの整合性と認証の検証
hash_hkdf鍵導出一つのマスターキーから複数の暗号鍵を導出

まとめ

hash_hkdf関数は、PHPアプリケーションにおいて安全な鍵管理を実装するための強力なツールです。暗号化、認証、トークン生成など、さまざまなセキュリティ用途に適用できます。適切な方法で使用することで、アプリケーションのセキュリティレベルを大幅に向上させることができます。

特に複数のサービスや機能が同じシステム内で動作する現代のウェブアプリケーションでは、一つのマスターキーから複数の独立した鍵を安全に導出できるhash_hkdfの価値は非常に高いものと言えるでしょう。セキュアなアプリケーション開発の基本ツールとして、ぜひ活用してみてください。

タイトルとURLをコピーしました