暗号と鍵の管理
OWASP の Cryptographic Storage Cheat Sheet を取得して読み、 理解した内容を自分の言葉で書いたもの。
OWASP Top 10 の A04 Cryptographic Failures に対応する。 秘密情報の管理が資格情報の置き場所の話なら、 こちらは暗号そのものの選び方と鍵のライフサイクル。
大原則
自作しない。 原典の言い方も端的で、独自アルゴリズムについては「やるな」の一言。
十分に検証された確立されたライブラリを使う。
アルゴリズムの選択
共通鍵暗号
AES。鍵長は最低128ビット、256ビットが望ましい
規制要件(FIPS 140-2、PCI DSS など)がある場合はそれを満たす鍵長にする
モードの選択が本体。
| 優先度 | モード | 得られるもの |
|---|---|---|
| 最優先 | GCM または CCM | 完全性・真正性・機密性のすべて(認証付き暗号) |
| 次善 | CTR または CBC + 別途の認証 | Encrypt-then-MAC で完全性を足す |
| 使わない | ECB | 極めて稀な状況を除いて使わない |
認証なしの暗号化は、改ざんを検知できない。 「暗号化してあるから安全」が成り立つのは、認証付きモードを使っているときだけ。
公開鍵暗号
楕円曲線暗号(ECC)、Curve25519 を優先する
RSA を使う必要があるなら最低2048ビット
RSA には必ずランダムパディング(OAEP / PKCS#1)を有効にする
パディングが要るのは、既知平文攻撃への防御のため。
ハッシュとパスワード
パスワードは可逆な暗号化で保存しない。 安全なハッシュアルゴリズムを使う。
具体的なアルゴリズムは Password Storage Cheat Sheet に分離されている。 認証と認可も参照。
乱数
用途によって使い分ける。ここを間違えると暗号全体が無意味になる。
| 種類 | 用途 |
|---|---|
| PRNG(疑似乱数) | 速いがセキュリティ用途には使えない |
| CSPRNG(暗号論的に安全な疑似乱数) | 暗号鍵、IV、セッションID、CSRFトークン、パスワードリセットのトークン |
言語ごとの安全な関数。
Java SecureRandom
Python secrets
Go crypto/rand
Node.js crypto.randomBytes()
PHP random_bytes()
.NET RandomNumberGenerator
Math.random() や rand() の類をセッションIDに使わない、が最も頻出する誤り。
鍵の管理
データと鍵を分離する
暗号鍵は暗号化されたデータと別の場所に置く。 例えばデータはデータベース、鍵はファイルシステム。 理想は物理的に別のシステムへ分離すること。
同じデータベースに両方あるなら、そのデータベースが抜かれた時点で暗号化の意味がない。
2階層の鍵
DEK (Data Encryption Key) 実際のデータを暗号化する
KEK (Key Encryption Key) DEK を暗号化する。別の場所に保管する
これでDEK のローテーションが、データ全体の再暗号化なしにできるようになる。
保管場所(安全な順)
1. HSM(ハードウェアセキュリティモジュール)または相当の仮想製品
2. クラウドの鍵管理サービス(AWS KMS、Azure Key Vault)
3. 外部の秘密情報管理(HashiCorp Vault、Conjur)
4. OS やフレームワークの API(.NET の ProtectedData など)
5. 権限を絞った設定ファイル(最後の手段)
避けるもの。
ソースコードへのハードコード
バージョン管理への格納
環境変数
phpinfo() や /proc/self/environ から露出しうる
環境変数が「避ける」側に入っているのは見落としやすい。 秘密情報の管理で挙げた 「CI/CD が秘密情報に触れない」構成が、ここでも効く。
ローテーションの引き金
侵害の疑い、または確認
暗号利用期間(cryptoperiod)の満了。脅威モデルによる。NIST SP 800-57 を参照
データ量の閾値を超えたとき(64ビット鍵なら 2^35 バイト)
アルゴリズムの脆弱性が判明したとき
ローテーションの手順は、必要になる前にテストしておく。 緊急時に初めて実行するものにしない。
古い鍵は一時的に保持する。 過去のバックアップを復号する必要があるため。
何を暗号化するか
まず、機微なデータの保存自体を最小にする。 特にクレジットカード情報は PCI DSS の要求が厳しいので、持たない判断が最も効く。
暗号化が必要な場合は、脅威モデルに応じて層を選ぶ。
アプリケーション層 / データベース層 / ファイルシステム層 / ハードウェア層
URL パラメータの暗号化だけに頼らない。 アクセス制御を独立して強制する(認証と認可)。
既存の記述との対応
| 既にある | ここでの位置づけ |
|---|---|
| 秘密情報の管理 の AES-256-GCM 推奨 | 認証付きモードの選択 |
| 同「鍵は暗号化されたデータと別の場所に保管する」 | データと鍵の分離 |
| 同 ローテーションの自動化 | ローテーションの引き金と手順 |
| API 設計 | 転送時の保護 |
| 認証と認可 | パスワードの保管 |
関連
- OWASP Top 10 — A04
- 秘密情報の管理 — 資格情報の置き場所とライフサイクル
- 認証と認可 — パスワードの扱い