🎓 レベル:標準 | 重要度:A(必須) 📎 前提:情報セキュリティとは(CIAとAAA)
要点(BLUF)
- 対称鍵暗号は送受信で同じ鍵を共有して暗号化・復号する方式。速い(AES)。弱点は鍵をどう安全に渡すか(鍵配送問題)。
- ハッシュは任意長の入力を固定長の指紋に潰す一方向関数。完全性の確認に使う。逆算は事実上不可能。
- 機密性だけでなく完全性も同時に守るには、暗号化と認証を組み合わせた **AEAD(AES-GCM など)**を使う。
概念:2つの道具、別々の目的
暗号の基礎には目的の違う2つの道具があります。混同しないことが第一歩です。
- 対称鍵暗号:機密性を守る。鍵を持つ者だけが中身を読める。可逆(暗号化⇔復号)。
- ハッシュ:完全性を確かめる。中身が変わっていないかを指紋で照合する。不可逆(一方向)。
「暗号化したから安全」は誤解で、暗号化だけでは改ざんを検知できません。守る側は機密性=暗号、完全性=ハッシュ/MACと役割を分けて理解します。
仕組み:対称鍵暗号(AES)
対称鍵暗号は1つの共有鍵 K で暗号化と復号を行います。代表は AES(鍵長 128/192/256 bit)。長所は高速で、大量データの暗号化に向きます。短所は鍵配送問題――通信前に K を安全に共有せねばならず、そこを盗まれると全部読まれます。この問題を解くのが次節の公開鍵暗号(公開鍵暗号)です。
利用モードも重要です。単純なブロック暗号の使い方(ECB など)はパターンが漏れるため避け、認証付き暗号(AEAD) の GCM などを使うのが現代の既定です。AEAD は機密性に加えて改ざん検知(完全性)も同時に提供します。
仕組み:ハッシュ(SHA)と3つの性質
暗号学的ハッシュ H は任意長の入力を固定長(SHA-256 なら 256 bit)に写します。守る側が頼るのは次の3性質です。
- 一方向性(preimage resistance):ダイジェストから元の入力を求めるのは事実上不可能。
- なだれ効果:入力が1ビット違うと出力は大きく変わる。
- 衝突困難性(collision resistance):同じダイジェストになる別入力を見つけるのが困難。MD5・SHA-1 はここが崩れたため非推奨。SHA-256 以上を使う。
メッセージに鍵を絡めて認証する HMAC を使えば、「正しい鍵を持つ者が作った/改ざんされていない」ことを確認できます(完全性+真正性)。
図解:暗号は機密性、ハッシュは完全性
flowchart LR
P["平文"] -->|"AESで暗号化(鍵K)"| C["暗号文(読めない)"]
C -->|"AESで復号(鍵K)"| P2["平文に戻る"]
M["メッセージ"] -->|"SHA-256(一方向)"| D["ダイジェスト(指紋)"]
D -. "元には戻せない" .-> M
防御側の使い方/設定
- AES は AEAD モードで:AES-GCM(または ChaCha20-Poly1305)を使い、ECB は使わない。nonce/IV は毎回新規でユニーク(再利用厳禁)。
- ハッシュは SHA-256 以上:MD5・SHA-1 は完全性検証・署名用途では使わない。
- 完全性が要るなら HMAC/AEAD:単なる暗号化や生ハッシュではなく、鍵付きの認証を使う。
- パスワード保存にハッシュを直接使わない:SHA-256 は速すぎる。専用の低速 KDF(認証の基礎(パスワード保存とMFA))を使う。
なぜ安全か:一方向性と認証タグ
ハッシュが完全性に効くのは、なだれ効果と一方向性のおかげで「少しの改ざんが指紋を大きく変え、かつ望む指紋に合わせる入力を作れない」からです。AEAD が改ざんに強いのは、暗号文に認証タグが付き、1バイトでも変わればタグ検証が失敗するからです。
下のデモは、(1) 1文字違いで SHA-256 が大きく変わること、(2) AES-GCM が改ざんを検知することを実際に示します。
security-study/labs/hash_oneway_demo.py の実行結果(抜粋):
sha256('password') = 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
sha256('Password') = e7cf3ef4f17c3999a94f2c6f612e8a888e5b1026878e4e19398b23bd38ec221a
変化したビット数 = 140 / 256 bit
同一平文でも一致しない(ソルト) -> True
先頭1文字を変えただけで 256 bit 中およそ半分(140 bit)が反転しています。これがなだれ効果です。
security-study/labs/symmetric_aead_demo.py の実行結果(抜粋):
復号結果 = transfer 100 to alice
改ざん検知 OK -> InvalidTag
AAD不一致検知 OK -> InvalidTag
暗号文を1バイト改ざんすると InvalidTag で復号が拒否されます。暗号化と完全性が同時に守られていることが分かります。
仕組みの直観
対称鍵暗号は南京錠を1個だけ複製して相手に渡すイメージ。同じ鍵で閉めて開ける。問題はその鍵の合鍵をどうやって安全に渡すか。ハッシュはシュレッダーで、紙を細断して指紋(細断パターン)は取れるが、指紋から元の紙は復元できない。指紋が違えば中身が変わった証拠になります。
⚠️ よくある誤解・設定ミス
- 「暗号化=改ざん防止」だと思う:暗号化は機密性のみ。完全性は AEAD か HMAC で別に確保する。
- ECB モードを使う:同じ平文ブロックが同じ暗号文になり、パターンが漏れる。AEAD を使う。
- nonce/IV を使い回す:GCM では nonce 再利用が致命的。毎回ユニークにする。
- MD5/SHA-1 を完全性・署名に使う:衝突が見つかっている。SHA-256 以上へ。
- パスワードを SHA-256 で保存:高速すぎて総当たりに弱い。低速 KDF を使う(認証の基礎(パスワード保存とMFA))。
対応 lab
security-study/labs/hash_oneway_demo.py— 一方向性・なだれ効果・ソルトsecurity-study/labs/symmetric_aead_demo.py— AES-GCM の改ざん検知(AEAD)
関連
- 鍵配送問題を解く → 公開鍵暗号
- 完全性+真正性を公開鍵で → デジタル署名と証明書(PKI)
- パスワード保存の低速ハッシュ → 認証の基礎(パスワード保存とMFA)