JWT 署名アルゴリズム比較: HS256、RS256、ES256、EdDSA
2026 年に重要となる 4 つの JWT 署名アルゴリズムのトレードオフ、それぞれが鍵配布にとって何を意味するか、そして実システムに今なお現れるアルゴリズム混同攻撃を整理します。
JWT のヘッダーは alg フィールドを持ち、そこで宣言される選択が、
トークンがどう署名されるか、受信者がどう検証するか、その検証を可能
にするためにどんなインフラが必要かを左右します。IANA レジストリには
数十のアルゴリズムがありますが、実際には 4 つが現実のシステムの
約 99% を占めます。本稿ではその 4 つをたどり、運用上の帰結を説明し、
本番コードに今なお現れるアルゴリズム混同攻撃で締めくくります。
重要な 4 つ
| アルゴリズム | ファミリー | 鍵の種類 | 署名サイズ | どこで見かけるか |
|---|---|---|---|---|
| HS256 | HMAC-SHA256 | 対称 (共有シークレット) | 32 バイト | 内部サービス、シンプルな SaaS API |
| RS256 | RSA-PKCS1-SHA256 | 非対称 (RSA 2048+) | 256 バイト | Auth0、AWS Cognito のデフォルト、OIDC ID トークン |
| ES256 | ECDSA-P256-SHA256 | 非対称 (P-256) | 64 バイト | Apple、Google のサービス、モダンな IdP |
| EdDSA | Ed25519 | 非対称 (Curve25519) | 64 バイト | OAuth GNAP、Solid ポッド、より新しいプロトコル |
古いシステムにはさらに 2 つのアルゴリズムが現れます。HS512 (SHA-512 を用いる HMAC で、出力サイズが倍になる点を除けば HS256 とトレード オフは同一) と RS512 (RS256 と同じ注意点) です。IANA レジストリには PS256 (RSA-PSS) も載っており、暗号学的には PKCS1 より望ましいものの、 運用上の利点が小さく、エコシステムのサポートがまばらなため、実際には ほとんど選ばれません。
HS256: 対称鍵が理にかなうとき
HS256 は 1 つの共有シークレットでトークンを署名します。トークンを 検証できる者は、新しいトークンを偽造することもできます。この制約は、 発行者と検証者が同じサービスである場合 ── 例えば 1 つのバイナリが セッションを発行し、リクエストごとに検証する内部 API トークン署名 ── では問題ありませんが、トークンを発行する能力は持たずに検証だけする 必要のある第三者が登場した瞬間に破綻します。
HS256 の運用上の魅力は単純さです。鍵はシークレットマネージャーから 取り出したランダムな文字列 1 つで、ローテーションはシークレットを 1 回更新するだけ、検証の計算はハッシュ 2 回と定数時間比較です。 トークンは小さく (32 バイトの署名)、処理も速い (コモディティ ハードウェアで 1 ミリ秒未満) です。
トレードオフは鍵の配布です。トークンを検証する必要のあるすべての サービスが署名の権限を握ることになります。単一サービスならこれで 問題ありません。セッショントークンを検証できるべきだが発行できるのは そのうち 1 つだけであるべき、というマイクロサービスが 5 つある場合、 HS256 は誤った選択です ── 残りの 4 つもシークレットを持つことになり、 そのいずれかが侵害されれば発行そのものが侵害されます。
RS256: 公開鍵のデフォルト
RS256 は発行と検証を分離します。発行者は RSA の秘密鍵を握り、対応 する公開鍵を持つ者は誰でも、トークンを発行することはできずに検証 できます。これが OIDC を成立させました ── ID プロバイダー (IdP) は well-known な JWKS URL に公開鍵を公開し、任意の証明書利用者 (relying party) が事前の調整なしに ID トークンを検証します。
その柔軟さには運用上の複雑さが伴います。鍵は 2048 ビット以上が必要 です (AWS、Auth0、主要な IdP のほとんどが 2048 または 4096 をデフォルト にしています)。署名は 256 バイト ── HS256 の 8 倍 ── で、検証は明確 に遅くなります (マイクロ秒ではなく 1 桁ミリ秒)。50,000 RPS を処理する サービスでは、RSA 検証の CPU コストがフレームグラフ上で観察できます。
鍵のローテーションも難しくなります。重複期間のあいだ、古い公開鍵と 新しい公開鍵の両方を載せた JWKS エンドポイントを公開し、新しい トークンは新しい鍵で署名し、最も寿命の長い未失効トークンが期限切れ になってから古い鍵を削除します。ほとんどの JWT ライブラリはデフォルト で複数鍵の JWKS を読めますが、無視できない割合の実装が JWKS を積極的 にキャッシュし、ローテーションを取りこぼします。
ES256: より短い鍵、より小さい署名、同じモデル
ES256 は P-256 楕円曲線上の ECDSA を使います。暗号学的な性質は RS256 と同等かそれ以上で、256 ビットの ECC はおおよそ 3072 ビットの RSA に 相当する安全性を提供します。運用上の利点は大きく、鍵は 256 ビット (32 バイト)、署名は 64 バイトで RS256 の 4 分の 1 です。検証はより速く、 署名も速いものの、IdP では規模が大きくなると検証側こそが重要になります。
難点はエコシステムのレベルにあります。ECDSA の実装は歴史的に RSA の 実装より微妙なバグが多く (ソニー PS3 の ECDSA におけるノンス再利用、 Java 15 の EC_KEY パーサーの CVE)、緩和には慎重なライブラリ選択が 必要です。TLS 終端装置や HSM での P-256 のハードウェアサポートは、 モダンなインフラでは普遍的ですが、古いアプライアンスではまばらです。 署名そのものは決定的ではありません ── ランダムなノンスが変わるため、 検証側は同じペイロードに対して異なる署名が出ることを許容しなければ なりません。
新しいサービスで非対称アルゴリズムを選んでいて、プラットフォームが サポートしているなら、ES256 がモダンなデフォルトです。
EdDSA: 最も新しい選択肢
Ed25519 を用いる EdDSA は最も新しい追加です。決定的で (同じ ペイロード → 同じ署名、ノンス依存なし)、ハードウェアアクセラレーション のないコモディティ CPU でも速く、ECDSA が定数時間実装で防ぐ必要の あるいくつかのサイドチャネル攻撃に対して免疫があります。RFC 8037 が 2017 年に EdDSA を JOSE に追加しました。
ライブラリのサポートは追いついてきましたが、まだ普遍的ではありません。 node-jose、PyJWT、そして jose (最も普及している JavaScript の JWT ライブラリ) はいずれもサポートしていますが、一部のエンタープライズ IdP や SDK は対応していません。モダンなスタックを狙う新規設計には EdDSA が推奨される選択肢で、より広いエコシステムとの相互運用性の ためには ES256 が依然としてより安全な選択です。
アルゴリズム混同攻撃
実システムにおける最も深刻な JWT の脆弱性は、どのアルゴリズムにある
のでもなく、alg ヘッダーを信頼する実装にあります。2 つの攻撃の形が
監査で今なお現れます。
1 つ目は alg=none です。JWS は空の署名を持つトークンを生成する
「none」アルゴリズムを規定しており、署名が不要なユースケースを想定
したものです。ヘッダーをデコードし、アルゴリズムを調べ、「none」が
許容されるか確認せずに検証器へ渡す実装は、偽造されたトークンを平気
で検証してしまいます。対策は、検証側でアルゴリズムの許可リスト
(allow-list) を明示的に維持し、none を意図的に除外することです。
2 つ目は RS256 → HS256 の混同です。RS256 トークンを受け入れるよう
構成された検証器は、発行者の RSA 公開鍵を握っています。攻撃者は
alg: HS256 を主張する新しいトークンを作り、その公開鍵を共有
シークレットであるかのように使って署名します。素朴な実装は、ヘッダー
で宣言されたアルゴリズムに対して手元にある鍵をそのまま使い、RSA
公開鍵を HMAC 鍵として扱って偽造を受け入れてしまいます。対策はやはり
許可リストです ── 検証器の構成時に、アルゴリズムと鍵の種類の両方を
固定 (pin) してください。
JWT ライブラリを統合するとき問うべきは「RS256 をサポートしているか」
ではなく「検証器が、渡す前に alg フィールドを自分の許可リストと
照合して検証するか」です。主要なライブラリ (jose、jsonwebtoken、
PyJWT、node-jose) は、検証呼び出しでアルゴリズムを明示的に固定する
よう進化してきましたが、古いコードパスや自前の実装は今も時折これを
省きます。
新しいサービスのための選択
発行者と検証者が同じバイナリである内部専用 API なら、HS256 で十分で あり、最も単純な選択です。第三者による検証が必要なものには非対称が 必須です ── プラットフォームがきれいにサポートするなら ES256、新規の モダンなスタックなら EdDSA、レガシーシステムとの最大の相互運用性を 求めるなら RS256 です。
何を選ぶにせよ、検証側でアルゴリズムを固定し、まともなキャッシュ ヘッダーを付けた安定した JWKS URL に公開鍵の素材を公開し、必要になる 前に鍵ローテーションの訓練のための余裕を見込んでください。現場で トークンを調べるには、JWT Decoder が検証を試みず にヘッダーとペイロードを表示します ── 検証器のシークレットを手元に 用意せずに認証フローをデバッグするときに便利です。