Security ツール
ハッシュ、パスワードのエントロピー、JWTのクレーム、CSPの記述、共有前のマスキング——Web開発で繰り返し発生するセキュリティ実務について、各プリミティブが何を保証し何を保証しないかを整理し、用途別のツールの使い分けと典型的な落とし穴をまとめる。
11 ツール
Webセキュリティの「日常業務」層
通常の開発で発生するセキュリティ作業の多くは攻防ではない。ダイジェストを選び、 認証情報を生成し、認証失敗の理由をトークンから読み、CSPを書き、共有前にキャプチャ から機密を削る。機械的だが事故はここから始まる。原因は技術力ではなく習慣だ。
区別すべきは3つ。エンコード(Base64、Punycode)は可逆で鍵を使わず、機密性を
生まない。ハッシュ(SHA-256)は一方向だがこれも鍵を使わず、同一性しか示さない。
鍵を使う操作(HMAC、JWT署名、TLS)だけが「誰が作ったか」を証明でき、それも鍵が
秘密の間だけだ。生のダイジェストもデコード済みJWTも、裏付けのない主張にすぎない。
もう一つの軸は方向だ。出力するもの(CSP、ヘッダー)は配信中のレスポンスで確認する まで正しさが確定せず、検査するもの(トークン、HAR)ではリスクが中身に移る。機密の 典型的な流出経路はバグ報告に添付されたHARだ。
各プリミティブが保証するもの
| プリミティブ | 証明できること | できないこと | よくある誤用 |
|---|---|---|---|
| Base64 / URLエンコード | テキスト経路での運搬 | 機密性(誰でも復元可) | APIキーの「隠蔽」 |
SHA-256 / SHA-512 | 完全性(同入力=同結果) | 秘匿性、総当たり耐性 | パスワードの保存 |
SHA-1 | 旧チェックサム互換のみ | 衝突耐性(実用的に破綻) | 署名 |
| HMAC(ハッシュ+鍵) | 鍵が秘密な間の真正性 | 機密性(本文は読める) | 鍵をブラウザへ配布 |
| Argon2id / bcrypt / scrypt | ソルト付きの低速な保存 | 速度(遅いことが機能) | 高速ハッシュへの差し替え |
JWT署名(HS256/RS256) | 発行者(検証後のみ) | デコードだけでは何も | デコード結果を信頼 |
Content-Security-Policy | 読み込み許可リストの強制 | 注入自体の修正 | 'unsafe-inline'の残置 |
TLS + Strict-Transport-Security | 経路の機密性、httpへの降格防止 | アプリのロジックの正しさ | 鍵アイコンを「安全」と読む |
エントロピーはどれだけ必要か
エントロピーは長さ × log2(プールサイズ)。プール選択は長さと同じだけ効く。
| 文字プール | 1文字 | 8文字 | 14文字 | 20文字 |
|---|---|---|---|---|
a–z(26) | 4.70 | 38 | 66 | 94 |
a–z0–9(36) | 5.17 | 41 | 72 | 103 |
a–zA–Z0–9(62) | 5.95 | 48 | 83 | 119 |
| 4種すべて(87) | 6.44 | 52 | 90 | 129 |
40bit未満は破綻、重要アカウントの下限は80bit、112bit以上で安心(UUID v4は122bit分)。
用途別の使い分け
フィンガープリントはハッシュ生成(Web Cryptoで4種同時、
shasum -a 256と一致、MD5は非実装)。秘密情報は「誰が持つか」で選び、人や
パスワードマネージャーならパスワード生成、機械向けの不透明ID
ならUUIDジェネレーター。どちらもCSPRNG由来で、前者は
crypto.getRandomValues、後者はcrypto.randomUUID()を使う(Math.randomではない)。
JWTデコーダーはheader.payload.signatureを分解し
iat/exp/nbfをISO 8601と失効判定で表示する。断片だけなら
Base64で、Base64urlの-/_は+//に直す。
記述と検証は分ける。CSPジェネレーターが14ディレクティブと
堅い初期値(default-src 'self'、frame-ancestors 'none'等)からヘッダーを組み、
詳細はCSPハブ。実際に乗っているかは
HTTPヘッダーで見る(サーバー側取得=生ヘッダー)。CDNは
書き換えるし、<meta>ではframe-ancestorsを指定できない。
共有前はHARビューアーで読み、外へ出すコピーは
HARサニタイザーへ(cookie等を[REDACTED]化、本文を空に、
トークン風パラメータをマスク)。URL1本ならURLパーサー、類似
ドメインはIDN変換。
HTTPヘッダーチェッカー以外はブラウザ内完結で、同ツールのみ入力URLを
api.sitekits.devへ送る。関連は職種別セットと
プライバシーハブ。
実際に事故になる落とし穴
デコードは検証ではない
分かるのはBase64urlとして妥当かだけだ。検証には鍵と固定したアルゴリズム、サーバー側
のexp/nbf/audチェックが要る。algヘッダー任せはalg: noneやRS256→HS256混同
を踏む。
高速ハッシュはパスワード保存ではない
生のSHA-256はGPUベンチマークで、ソルトが無ければ1つのレインボーテーブルで全
ユーザーが破られる。ファイル比較なら逆に高速ダイジェストが正解だ。
'unsafe-inline'はCSPの大半を無効化する
CSPが止めるべきインラインスクリプトを許可し直すため、ポリシーが文書に成り下がる。
nonceかハッシュを使う。ワイルドカードのconnect-srcも同じ穴だ。
マスキングはパターン一致にすぎない
対象は固定のヘッダー名とtoken/key/secret/password/passwd/pwd/auth/session/sig/signatureを含むパラメータ名だけで、
パスセグメント内やtのような名前は残る。置換0件は検出漏れのサインだ。
エントロピーは生成方法の性質であって、文字列の性質ではない
式が成り立つのは全文字をランダムに選んだ場合だけだ。P@ssw0rd!2024は13文字で4種
すべてを含むが、どのクラック用辞書にも載っている。メーターの点数に意味があるかを
決めるのは、その文字列がどう生成されたかだけだ。