対称暗号とは
対称暗号(Symmetric Encryption)は、暗号化と復号化に同じ鍵(秘密鍵)を使用する暗号方式です。「共通鍵暗号」とも呼ばれ、非対称暗号(公開鍵暗号)と比較して高速な処理が可能です。
代表的な対称暗号アルゴリズム:
- AES:現代の標準(128/192/256ビット鍵)
- ChaCha20:ソフトウェア実装で高速
- 3DES:DESの後継(現在は非推奨)
- Blowfish/Twofish:bcryptの基盤
対称暗号の種類
ブロック暗号
固定長のブロック単位でデータを処理。AES(128ビットブロック)が代表例。長いデータは暗号モード(CBC、CTR、GCM)で処理します。
ストリーム暗号
1ビットまたは1バイト単位で連続処理。ChaCha20やRC4(非推奨)が該当。リアルタイム通信に適しています。
仕組み・詳細解説
対称暗号がなぜ「同じ鍵で暗号化も復号もできる」のか、その内部構造を段階的に見ていきます。仕組みを理解しておくと、モード選択や鍵長選定を誤らずに済みます。
1. 鍵とアルゴリズムの基本原理
対称暗号の暗号化処理は、平文と鍵から一意に暗号文を導く関数E(key, plaintext) = ciphertextと、その逆関数D(key, ciphertext) = plaintextのペアで構成されます。同じ鍵を使うため暗号化・復号の計算コストは対称であり、非対称暗号のような剰余べき乗計算(RSA)や楕円曲線上の点演算(ECC)を伴わない分、CPU負荷が小さく済みます。設計上の要件は「鍵を知らない第三者には、暗号文から平文や鍵の情報が実用的な時間内で一切推測できないこと(計算量的安全性)」であり、これを満たすためにビット単位の攪拌(拡散: diffusion)と置換(混乱: confusion)をシャノンが1949年に提唱した設計原理に基づいて何度も繰り返します。
2. ブロック暗号の内部構造(SPN構造とラウンド処理)
AESはSPN(Substitution-Permutation Network)構造を採用しており、鍵長に応じてラウンド数が変わります。AES-128は10ラウンド、AES-192は12ラウンド、AES-256は14ラウンドの処理を行い、各ラウンドで次の4つの変換を実行します。
- SubBytes:S-BOXと呼ばれる非線形の置換表で1バイトずつ変換し、線形攻撃・差分攻撃への耐性を持たせる
- ShiftRows:状態(4×4バイトの行列)の各行を巡回シフトし、バイト間の位置関係を拡散させる
- MixColumns:ガロア体GF(2^8)上の行列演算で各列のバイトを混合し、拡散をさらに強化(最終ラウンドのみ省略)
- AddRoundKey:鍵スケジュール(Key Schedule)で元の鍵から派生させたラウンド鍵をXORで加算
対して旧世代のDESやBlowfishはFeistel構造を採用しており、データを左右に分割して一方だけを関数に通し、もう一方とXORするという処理をラウンドごとに交互に行います。Feistel構造は暗号化関数と復号関数がほぼ同一の回路で実装できる利点がありますが、AESのSPN構造の方が並列処理・ハードウェア実装との親和性が高く、現在の主流になっています。
3. ストリーム暗号とChaCha20の仕組み
ChaCha20は256ビット鍵・96ビットnonce(IETF版)・32ビットカウンタを初期状態として16個の32ビットワード(4×4行列)に配置し、ARX演算(Addition・Rotation・XOR)のみで構成される「クォーターラウンド」を20ラウンド(10回のダブルラウンド)繰り返してキーストリームを生成します。生成されたキーストリームを平文とXORするだけで暗号化・復号が完了する仕組みのため、S-BOXのようなメモリ参照を伴わずソフトウェア実装でもタイミング攻撃に強く、AES-NIのないモバイルCPUやIoT機器でも高速に動作します。ポイントは「同じ鍵とnonceの組み合わせを二度と使わないこと」で、これが破られるとキーストリームが再利用され、2つの暗号文をXORするだけで平文の差分が漏洩します(鍵ストリーム再利用攻撃)。
4. 暗号利用モードと認証付き暗号(AEAD)
ブロック暗号は1ブロック(AESは16バイト)ずつしか処理できないため、任意長のデータを扱うには「モード」で連結方法を定義する必要があります。ECBモードは各ブロックを独立に暗号化するため同一平文ブロックが同一暗号文になり、画像のパターンが透けて見えるなどの脆弱性があり実運用では使用禁止とされています。CBCモードは前のブロックの暗号文をXORしてから暗号化することで規則性を排除しますが、パディングオラクル攻撃(POODLE等)の対象になった経緯があります。CTRモードはカウンタを暗号化してキーストリーム化し平文とXORするためストリーム暗号的に扱え並列化しやすい一方、それ単体では改ざん検知(完全性)の機能がありません。GCMモードはCTRモードにGHASH関数によるガロア体上の認証タグ生成を組み合わせたAEADで、暗号化と改ざん検知を同時に行うため、NIST SP 800-38Dで標準化され、TLS 1.3・IPsec・SSHなど現代のプロトコルの事実上の標準になっています。
AIエンジニアとしての実体験
機械学習パイプラインでは学習データやモデルファイルの暗号化に対称暗号を用いるのが実務上の定石です:
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os
# Fernet(AES-128-CBC + HMAC)
key = Fernet.generate_key()
f = Fernet(key)
encrypted = f.encrypt(b"secret data")
decrypted = f.decrypt(encrypted)
# AES-256-GCM(推奨)
key = AESGCM.generate_key(bit_length=256)
aesgcm = AESGCM(key)
nonce = os.urandom(12)
ct = aesgcm.encrypt(nonce, b"secret data", b"associated data")
メリット・デメリット(注意点)
対称暗号を採用する際は、速度面の恩恵と鍵管理の負担をセットで理解しておく必要があります。
メリット
- 処理速度が速い:AES-NI等のハードウェアアクセラレーションを使えば1バイトあたり数クロックで暗号化でき、非対称暗号(RSA-2048等)と比べて桁違いに高速
- 実装がシンプル:剰余べき乗や楕円曲線演算のような大数演算が不要で、組み込み機器でも実装しやすい
- 大量データ向き:ディスク暗号化(LUKS、BitLocker)やTLSのセッション通信本体など、大容量データのリアルタイム暗号化に適している
- 枯れた標準がある:AESはFIPS 197として1998年のAES選定コンペ以来20年以上の暗号解析にさらされても実用的な破り方が見つかっていない
デメリット・注意点
- 鍵配送問題:暗号化する前に、送信者と受信者が同じ鍵を安全に共有していなければならない。ネットワーク越しに鍵そのものを平文で送ることはできない
- 鍵の本数が爆発的に増える:N人が1対1で通信する場合、必要な鍵ペアの数はN(N-1)/2通りになり、当事者が増えるほど鍵管理コストが跳ね上がる
- 否認防止ができない:同じ鍵を双方が保持しているため、「相手が暗号化したのか自分が暗号化したのか」を暗号文だけから区別できず、電子署名のような否認防止機能は非対称暗号側の役割になる
- 実装ミスが致命傷になりやすい:nonce(初期化ベクトル)の再利用、脆弱なモード(ECB)の選択、鍵の使い回しなど、暗号理論自体は安全でも運用上のミスで安全性が崩れるケースが最も多い
この鍵配送問題を解決する実務上の定番が、非対称暗号で対称鍵(セッション鍵)だけを安全に交換し、実際のデータ本体は対称暗号で暗号化する「ハイブリッド暗号」です。TLSのハンドシェイクはまさにこの構成で、鍵交換にECDHE(楕円曲線Diffie-Hellman)、データ通信本体にAES-GCMやChaCha20-Poly1305を使い分けています。
対称暗号 vs 非対称暗号
| 項目 | 対称暗号 | 非対称暗号 |
|---|---|---|
| 速度 | ✅ 高速 | 遅い |
| 鍵配送 | 困難 | ✅ 容易 |
| 用途 | 大量データ暗号化 | 鍵交換、署名 |
混同されやすい用語・類似技術との違い
ハッシュ関数との違い
SHA-256などのハッシュ関数は「一方向性」が本質で、元のデータに戻すこと(復号)を前提としていません。対称暗号は鍵さえあれば必ず平文に復元できる「可逆」な変換である点が根本的に異なります。パスワードの保管にAESで「暗号化」して保存する設計をよく見かけますが、パスワードは検証できればよく復元する必要がないため、本来はbcryptやArgon2のような鍵導出関数(ハッシュ関数の一種)を使うべきで、対称暗号を使うのは目的のミスマッチです。
MAC・HMACとの違い
HMACは秘密鍵とハッシュ関数を組み合わせて「メッセージが改ざんされていないこと」を検証するための固定長タグを生成する仕組みで、暗号化(秘匿)は行いません。対称暗号は「読めなくすること」、HMACは「変わっていないことを証明すること」が目的であり、両者は補完関係にあります。実務では、暗号化とMACを別々に組み合わせる(Encrypt-then-MAC)よりも、GCMやChaCha20-Poly1305のようにアルゴリズムレベルで両方を一体化したAEADを使う方が、実装ミス(例えばMACの検証を暗号化より後に間違った順序で行うなど)のリスクを避けられます。
公開鍵基盤(PKI)・電子証明書との違い
PKIやTLS証明書は非対称暗号(RSAやECDSA)を使って「通信相手の身元を保証する」ための仕組みであり、対称暗号そのものとは別のレイヤーです。ただしTLS通信では、証明書による身元確認とECDHEによる鍵交換が完了した後、実際の通信データはAES-GCM等の対称暗号で暗号化されるため、両者は1つのプロトコルの中で連携して動いています。「対称暗号=古い」「証明書=新しい」という誤解がありますが、役割が違うだけで両方とも現役の技術です。
エンコーディング(Base64等)との違い
Base64やURLエンコードは「データ形式の変換」であり、鍵を使わず誰でも即座に元に戻せるため暗号化ではありません。設定ファイルにBase64でエンコードした秘密情報を「暗号化した」と誤記しているケースを見かけますが、セキュリティ上は平文と同等に扱う必要があります。対称暗号は鍵を持つ者だけが復号できる点が本質的な違いです。
トラブル事例と対策
⚠️ 鍵の安全な配送
課題:対称暗号では鍵を安全に共有する必要がある
対策:非対称暗号で鍵を交換し、その後対称暗号でデータを暗号化(ハイブリッド暗号)。
⚠️ nonce(IV)の再利用
課題:GCMやChaCha20-Poly1305で同じ鍵と同じnonceの組み合わせを再利用すると、キーストリームが再利用され平文の差分が漏洩し、GCMの場合は認証鍵まで復元されて任意の偽造暗号文が作成できてしまう
対策:GCMのnonce(96ビット)は暗号ライブラリのos.urandom(12)等で毎回ランダム生成するか、カウンタ方式で厳密に一意性を管理する。1つの鍵で暗号化する回数が多い場合(同一鍵で2^32回以上)はXChaCha20-Poly1305のような拡張nonce(192ビット)方式への切り替えを検討する。
⚠️ 廃止済み・非推奨アルゴリズムの使い回し
課題:古いシステムでDES・3DES・RC4・ECBモードがそのまま残っており、監査で指摘されるケースが多い。NIST SP 800-131A rev.2では3DESは2023年末で使用不可(disallowed)と位置づけられている
対策:暗号棚卸し(crypto inventory)を行い、AES-256-GCMまたはChaCha20-Poly1305への計画的な移行と、TLS設定・VPN設定・バックアップ暗号化ツールの暗号スイート一覧を定期的に確認する運用を組み込む。
2025-2026年の最新動向
鍵長の推奨基準:NIST SP 800-57 Part 1では、対称鍵の「セキュリティ強度(security strength)」をビット数で評価しており、AES-128は128ビット強度、AES-192は192ビット強度、AES-256は256ビット強度に相当するとされています。2030年以降は112ビット未満の強度(旧2-key 3DES等)の使用が認められない方向で整理が進んでおり、新規システムでは鍵長128ビット以上、長期保存データや高機密データにはAES-256の採用が一般に推奨されています。
ポスト量子時代を見据えた鍵長選定:Groverのアルゴリズムにより量子コンピュータは対称鍵の総当たり探索を理論上高速化できますが、その効果は鍵長を半分にする程度(AES-256なら実効128ビット相当)にとどまり、Shorのアルゴリズムで根本的に崩れるRSA・ECCの非対称暗号とは影響の質が異なります。この違いから、対称暗号アルゴリズム自体の置き換えは急務ではないものの、長期保存が必要なデータについてはAES-256の採用が保守的な選択とされています。米NSAが示すCNSA 2.0(Commercial National Security Algorithm Suite)でも、対称暗号についてはAES-256を継続採用する方針が示されています。
AEAD(Authenticated Encryption with Associated Data)がデフォルトとなっています。AES-GCM、ChaCha20-Poly1305のようなAEAD暗号は、暗号化と認証を同時に行い、パディングオラクル攻撃等を根本的に防止します。TLS 1.3(RFC 8446)ではAEAD暗号のみがサポートされ、CBCモードのような非AEADの暗号スイートは仕様上廃止されています。
ハードウェアアクセラレーションが一般化し、Intel AES-NI、ARMのAES拡張命令がほぼすべてのモダンCPU・スマートフォンSoCに搭載されています。これにより、AES暗号化/復号化のパフォーマンスオーバーヘッドはほぼゼロに近づいており、「ChaCha20の方が常に速い」という以前の前提は、AES-NI搭載環境では当てはまらなくなっています。
鍵管理の集中化も進んでいます。AWS KMS、Google Cloud KMS、HashiCorp Vaultのようなマネージド鍵管理サービスやHSM(ハードウェアセキュリティモジュール)を使い、対称鍵そのものをアプリケーションコードに直接持たせず、エンベロープ暗号化(データ暗号鍵をKMSのマスター鍵でさらに暗号化するパターン)を採用する構成が実務のデファクトになりつつあります。
関連用語
- AES - 最も広く使われる共通鍵暗号
- 非対称暗号 - 公開鍵暗号方式
- 暗号モード - ECB, CBC, CTR, GCMなどの動作モード
- CBC/CTR/GCM - 代表的な暗号利用モードの詳細比較
- ChaCha20-Poly1305 - AEAD構成のストリーム暗号
- ChaCha20 - AESの代替となる高速ストリーム暗号
- AEAD - 認証付き暗号化の枠組み
- Diffie-Hellman鍵交換 - 共通鍵を安全に共有する代表的な方法
- 鍵長 - 暗号強度を左右する鍵のビット数
- 鍵管理 - 暗号鍵のライフサイクル管理
- HMAC - 対称鍵を用いたメッセージ認証コード
- Nonce - 暗号利用モードで一度だけ使う値
- 耐量子暗号 - 量子コンピュータ時代の暗号技術
外部リンク・参考資料
- NIST FIPS 197 - Advanced Encryption Standard (AES) - AESの正式な標準規格文書
- NIST SP 800-38D - GCM/GMACの仕様 - AES-GCMモードの技術仕様
- RFC 8439 - ChaCha20 and Poly1305 for IETF Protocols - ChaCha20-Poly1305の標準仕様
- NIST SP 800-57 Part 1 Rev.5 - 鍵管理に関する推奨事項 - 鍵長とセキュリティ強度の対応表
よくある質問(FAQ)
Q. 共通鍵暗号とは?
暗号化と復号化に同一の鍵を使用する暗号方式です。AES-256が最も広く使われ、高速な処理が特徴です。鍵の安全な共有が課題となります。
Q. AES-128とAES-256はどちらを使うべき?
2025年現在、AES-128も十分安全ですが、将来の量子コンピュータ対策としてAES-256の使用が推奨されています。性能差はハードウェアアクセラレーションにより無視できるレベルです。
Q. AEADとは?
AEAD(認証付き暗号化)は暗号化と認証を同時に行う方式です。AES-GCM、ChaCha20-Poly1305が代表的で、TLS 1.3のデフォルトとなっています。
Q. 対称暗号とハッシュ関数は何が違いますか?
対称暗号は鍵があれば元のデータに復号できる「可逆」な変換です。一方ハッシュ関数(SHA-256等)は元に戻すことを想定しない「一方向」の変換で、パスワードの保管やデータの完全性確認に使われます。パスワードを「暗号化して保存」するのは目的のミスマッチで、本来はArgon2やbcryptのような鍵導出関数を使うべきです。
Q. nonce(初期化ベクトル)を使い回すと何が起きますか?
GCMやChaCha20-Poly1305で同じ鍵・同じnonceの組み合わせを再利用すると、キーストリームが再利用され平文の差分が漏洩します。GCMの場合はさらに認証鍵まで復元され、任意の暗号文を偽造できてしまう深刻な脆弱性につながります。nonceは暗号ライブラリの乱数生成関数で毎回新しく生成するか、厳密なカウンタ管理で一意性を担保する必要があります。
