こんにちは。現場の最前線でコードと格闘し、時にインシデントの火消しに奔走しているエンジニアの皆さん、お疲れ様です。
今日は、Webアプリ開発の現場で避けては通れない「JWT(JSON Web Token)」の、特に「署名アルゴリズム」の話をしましょう。
「RS256? HS256? どっちを使えばいいの? そもそも何が違うの?」と悩んだことはありませんか? ネットで調べると専門用語の羅列ばかりで、頭が痛くなりますよね。今日は、難しい数学の話は一旦置いておいて、身近な「家の鍵」に例えて、この2つの違いを紐解いていきましょう。
—
1. JWTは「身分証明書」のようなもの
JWTは、Webサイトでログインした時にサーバーから渡される「通行手形」のようなものです。これを持っていれば、わざわざ毎回IDとパスワードを入力しなくても、「私はログイン済みですよ」と証明できます。
でも、もし誰かがこの通行手形を偽造して、「私は管理者です!」と書き換えたら大変ですよね。だからこそ、JWTには「改ざんされていないこと」を証明するための「署名」が必要なんです。
2. 共通鍵(HS256)は「合鍵」の関係
まず、HS256から見ていきましょう。これは「共通鍵暗号」という仕組みです。
【例え話】
あなたと友達が、同じ「秘密の合鍵」を1つずつ持っている状態です。あなたが手紙(JWT)にその鍵で封印をすると、同じ鍵を持っている友達だけが「あ、これは本物だ」と開けることができます。
- メリット: シンプルで計算が速い。
- デメリット: 「鍵」そのものが漏れたら終わりです。もしサーバーが複数あって、すべてのサーバーでこの鍵を共有していると、どれか一つから鍵が盗まれた瞬間に、全ての通行手形が偽造可能になります。
3. 公開鍵(RS256)は「金庫と鍵」の関係
次に、RS256です。こちらは「公開鍵暗号」という仕組みを使います。
【例え話】
あなたは「封印するための専用の鍵(秘密鍵)」を厳重に金庫に隠し持ち、誰でもコピーできる「確認用のスタンプ(公開鍵)」を玄関に置いておきます。
通行手形(JWT)には、あなたが隠し持っている鍵で封印をします。確認する側は、玄関にあるスタンプを使って「この封印は正しいか?」をチェックするだけです。
- メリット: 万が一、確認用のスタンプ(公開鍵)が盗まれても、手形を偽造するための「秘密鍵」はあなたの金庫の中なので、安全は守られます。
- デメリット: 仕組みが少し複雑で、処理速度はHS256よりわずかに遅くなります。
—
4. どっちを選べばいいの?
結論から言うと、「基本はRS256、小規模な単一サーバーならHS256もアリ」です。
- RS256を選ぶべき時:
- マイクロサービスなど、複数のサーバーで認証を行う場合。
- セキュリティレベルを高く保ちたい場合(秘密鍵が外部に漏れるリスクを最小化できるため)。
- HS256を選ぶべき時:
- サーバーが1台だけで完結している小規模なサービス。
- とにかく処理のオーバーヘッドを減らしたい場合。
—
5. 実装で気をつけるべき「盲点」
最後に、開発者が一番やりがちなミスを一つだけお伝えします。それは「アルゴリズムの固定」です。
JWTのヘッダーには `alg` という項目があり、ここを書き換えて攻撃してくる輩がいます。コードを書く時は、以下のように「使うアルゴリズムを厳格に指定」してください。
// ライブラリで検証する際、アルゴリズムを決め打ちにするのが鉄則!
const jwt = require(‘jsonwebtoken’);
// 悪い例:受け取ったJWTのヘッダーにあるアルゴリズムをそのまま信用してしまう
// jwt.verify(token, secret);
// 良い例:サーバー側で「RS256しか認めない!」と明示する
jwt.verify(token, publicKey, { algorithms: [‘RS256’] }, (err, decoded) => {
if (err) {
// 署名が不正、あるいはアルゴリズムがRS256以外ならここで弾く
console.error(“不正なトークンです”);
return;
}
// 正常処理
});
この「algorithms」というオプション、意外と忘れがちですが、ここを制限するだけで攻撃者の「アルゴリズムをHS256にすり替えて、鍵を推測しやすくする」という手口を無効化できます。
—
まとめ:一歩ずつ安全な開発を
セキュリティは「完璧」を目指すと疲れてしまいますが、まずは「RS256で鍵を分ける」「アルゴリズムを決め打ちで検証する」といった基本的な作法を守るだけで、あなたのアプリケーションはグッと強固になります。
「鍵」をどう守るか、という意識を持つこと。それがホワイトハッカーへの第一歩です。また何か分からないことがあれば、いつでも聞きに来てくださいね。一緒に安全なコードを書いていきましょう!

コメント