本文へスキップ
ecdsa.com
firebase/php-jwt 7.x (PHP)PHP

エラーメッセージ

Provided key is too short

別の表記

  • DomainException: Provided key is too short

`JWT::encode` と `JWT::decode` の両方でスローされます。php-jwt 6.x 以前は短い鍵を受け付けていたため、このエラーは通常 7.x にアップグレードした直後に発生します。

firebase/php-jwt 7.x (PHP) — DomainException from JWT::encode / JWT::decode

このエラーの意味

php-jwt 7 は、署名や検証の前に鍵長をチェックします。HMAC シークレットにはハッシュの出力以上のビット数(HS256 では 32 バイト、HS384 では 48 バイト、HS512 では 64 バイト)が、RSA 鍵には 2048 ビット以上が、EC 鍵にはそのアルゴリズムが前提とするサイズ以上が必要です。これより短い鍵が拒否されるのは、その鍵で保護されたトークンを偽造できるからです。短い HMAC シークレットはオフラインの総当たりで破られ、1024 ビットの RSA は現在の最小要件を下回っています。

発生する理由

修正方法

  1. 1.

    新しいランダムなシークレットを生成する

    `random_bytes` または `openssl rand` を使い、シークレットはシークレットストアに保管してください。シークレットをローテーションすると既存のトークンが無効になるため、必要に応じて新旧のシークレットを短期間併用できるよう計画してください。

    bash
    # HS256 needs >= 32 bytes, HS512 >= 64; generate and store as base64
    php -r 'echo base64_encode(random_bytes(64)), PHP_EOL;'
  2. 2.

    base64 でエンコードして保存し、デコードしたバイト列を使う

    起動時に一度だけ長さを検証してください。そうすれば、弱いシークレットは最初のリクエストではなくデプロイの段階で失敗します。

    php
    $secret = base64_decode(getenv('JWT_SECRET_B64'), true);
    if ($secret === false || strlen($secret) < 32) {
        throw new RuntimeException('JWT_SECRET_B64 must decode to at least 32 bytes');
    }
    $token = JWT::encode($claims, $secret, 'HS256');
    $decoded = JWT::decode($token, new Key($secret, 'HS256'));
  3. 3.

    短い RSA 鍵を置き換える

    2048 ビット以上の RSA 鍵を生成するか、P-256 鍵を使う ES256 に切り替えてください。いずれの場合も、新しい鍵で署名を始める前に、新しい公開鍵を公開しておいてください。

    bash
    openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out rs256-private.pem

関連するエラー

署名エラーデータベースをすべて見る