AES暗号化完全ガイド:仕組み、モード、実践的な使い方

HTTPS通信、スマートフォンのストレージ、Wi-Fiパスワード、暗号化ZIPファイル——現代の暗号化シーンの中心にあるのはすべて同じアルゴリズムです:AES(Advanced Encryption Standard)。2001年にNISTが標準化したこの対称暗号は、今日においても破られていない実用的な暗号化の基盤です。AESの仕組みと正しい使い方は、開発者とセキュリティエンジニアに欠かせない知識です。

1. AESの成り立ち

1997年、NISTはDES(Data Encryption Standard)の後継を選ぶ公開コンペを開始しました。DESの56ビット鍵は1999年に22時間で解読されており、時代遅れになっていました。5年間にわたる世界中の暗号学者による公開審査を経て、2001年にNISTはベルギーの暗号学者Joan DaemenとVincent Rijmenが設計したRijndaelアルゴリズムを選定し、AES(FIPS PUB 197)として発布しました。

対称暗号 vs. 非対称暗号
AESは対称暗号:暗号化と復号に同じ鍵を使います。RSAは非対称暗号:公開鍵で暗号化し、秘密鍵で復号します。HTTPSはその組み合わせです——RSA/ECDHでAESセッション鍵を安全に交換し、実際のデータ転送はAESで行います。

2. 鍵長

AESは3種類の鍵長をサポートしています:

鍵長ラウンド数セキュリティレベル主な用途
AES-12810128ビット一般アプリ、TLS
AES-19212192ビットほとんど使われない
AES-25614256ビット政府機密、高セキュリティ要件

AES-128はほぼすべてのアプリケーションで十分です——総当たり攻撃には2¹²⁸通りの試行が必要で、現在の計算能力では事実上不可能です。AES-256は量子コンピュータに対する防衛(Groverアルゴリズムにより有効鍵長が半減するため、256ビット→128ビットで依然安全)や規制要件(米国政府のTOP SECRET)に使われます。

3. AESの動作原理

AESは128ビット(16バイト)のブロック単位でデータを処理します。鍵長によってラウンド数が決まり、各ラウンドで4つの変換が4×4バイトの状態行列に適用されます:

  1. SubBytes(バイト置換):各バイトを固定のS-Boxで置換し、非線形性を提供
  2. ShiftRows(行シフト):各行を異なるバイト数だけ循環左シフトし、列をまたいでデータを拡散
  3. MixColumns(列混合):各列にGF(2⁸)の乗算を適用し、バイト間の依存性を生成(最終ラウンドは省略)
  4. AddRoundKey(ラウンド鍵の加算):状態とマスター鍵から派生したラウンド鍵をXOR

4. 暗号化モード:最も重要な選択

AES自体は128ビットのブロックを1つ暗号化する方法を定義するだけです。任意長のデータには「暗号化モード」が必要です。この選択は鍵長よりも重要です。

4.1 ECB(電子符号表モード)— 絶対に使ってはいけない

ECBは各ブロックを独立して暗号化します。致命的な欠陥:同じ平文ブロックは同じ暗号文ブロックを生成するため、元データのパターンが保持されます。

ECBペンギン問題
ECBでペンギンの画像を暗号化しても、同じ色のピクセル領域が同じ暗号文を生成するため、暗号化後もペンギンの輪郭が見えます。ECBは機密性が必要な場面では絶対に使ってはいけません。

4.2 CBC(暗号文ブロック連鎖モード)— レガシー標準

CBCは各平文ブロックを暗号化前に直前の暗号文ブロックとXORし、最初のブロックにはランダム生成のIV(初期化ベクトル)を使います。パディングが必要で、完全性検証は提供しません。Padding Oracle攻撃に脆弱です。

4.3 GCM(ガロア/カウンターモード)— 現代の標準

GCM = CTR暗号化 + GHASH認証。Authentication Tag(認証タグ)を自動生成し、改ざんを検出します。

  • AEAD(認証付き暗号化):機密性と完全性を1回の操作で保証
  • パディング不要、完全な並列処理可能
  • TLS 1.3でAES-256-GCMが主要暗号スイートとして使用
モードパディング完全性検証並列処理推奨度
ECB必要なし❌ 絶対に使わない
CBC必要なし復号のみ⚠️ レガシー互換のみ
CTR不要なし✅ MAC併用で使用可
GCM不要✅ 内蔵✅✅ 現代の第一選択

5. IVとNonce:絶対に使い回さない

  • 暗号化のたびに異なるIV/Nonceを使う必要があります——使い回しはセキュリティを著しく損ないます
  • IV/Nonceは秘密にする必要はなく、暗号文と一緒に平文で送信できます
  • GCMのNonce使い回しは壊滅的:攻撃者が認証鍵を復元し、暗号化スキーム全体を破れます

6. コード例

# PHP(OpenSSL、AES-256-GCM)
$key = random_bytes(32);
$nonce = random_bytes(12);
$ciphertext = openssl_encrypt(
    $plaintext, 'aes-256-gcm', $key,
    OPENSSL_RAW_DATA, $nonce, $tag
);

# Python(cryptographyライブラリ、AES-256-GCM)
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os
key = os.urandom(32)
nonce = os.urandom(12)
aesgcm = AESGCM(key)
ciphertext = aesgcm.encrypt(nonce, plaintext, None)

# Node.js(組み込みcrypto、AES-256-GCM)
const crypto = require('crypto')
const key = crypto.randomBytes(32)
const nonce = crypto.randomBytes(12)
const cipher = crypto.createCipheriv('aes-256-gcm', key, nonce)
const encrypted = Buffer.concat([cipher.update(plaintext), cipher.final()])
const tag = cipher.getAuthTag()

7. まとめ

AESは現代暗号学の基盤です:20年以上の公開審査を経ても破られていません。しかしアルゴリズム自体はほんの一部——正しい使い方こそが実際のセキュリティを提供します。GCMモードを使い(ECBや裸のCBCは避ける)、毎回ランダムなNonceを生成し、KDFで鍵を派生させる(パスワードをそのまま使わない)。この3つを守れば、AESはあなたのアプリケーションに工業グレードの暗号化保護を提供します。