広告が嫌いですか? 行く 広告なし 今日

開発者向けのAES暗号化 必要になる場面とその仕組み

掲載日
開発者向けのAES暗号化:必要なタイミングとその仕組み 1

センシティブなデータ(ユーザーの個人情報、APIキー、財務記録)を保存している場合、AES暗号化が最も適した選択肢です。これは、静止中の対称暗号化において業界標準として採用されているもので、高速で信頼性があり、主要な言語でネイティブサポートされています。

AESを誤って使用すると、無意味よりも悪化します。ECBモードではパターンが漏洩します。GCMでIVを再使用することは、そのセキュリティ保証を完全に破壊します。また、鍵を暗号化データの隣に保存することは、その目的を無効にします。

以下が、生産環境でAESを正しく使用するために必要な内容です。

AESとは何か?

AES(高度暗号化標準)は、対称ブロック暗号です。対称とは、同じ鍵で暗号化と復号が行われることを意味し、ブロック暗号とは、128ビットの固定サイズのデータブロックに対して動作することを意味します。

2001年にDESに置き換えられ、現在ではTLS、ディスク暗号、パスワードマネージャ、データベースフィールド暗号など、あらゆる場面で使用されています。非対称暗号(RSA、ECDH)とは異なり、AESは大量のデータをリアルタイムで暗号化できるほど高速です。代償として、双方が同じ鍵を共有しなければなりませんので、鍵の配布が課題になります。

AES-128とAES-256:どの鍵サイズが適しているか?

AESは128ビット、192ビット、256ビットの3つの鍵サイズがあります。実際の使用では、128ビットと256ビットの間で選択します。

AES-128AES-256
鍵長128ビット256ビット
回数1014
パフォーマンス速い約40%遅い
安全強い——実用的な攻撃が存在しないより強い——未来の量子コンピュータに対しても耐性がある
判定ほとんどのアプリケーションに適している高感度データまたは長期保存が必要な場合に使用

AES-128は破綻していません。実用的な攻撃は存在しません。ただし、20年以上データを安全に保持する必要がある、または量子コンピュータを含む脅威モデルがある場合、AES-256は意味のある余裕を提供します。現在のデータベースフィールドの暗号化においては、AES-128が十分です。不安な場合はAES-256を使用してください。パフォーマンスの損失は、通常のワークロードではほとんど影響しません。

動作モード:なぜGCMを使うのか?ECBではない

AESだけでは128ビットのブロックだけを暗号化できます。実際のデータを扱うには、複数のブロックを正しくシーケンス化できる動作モードが必要です。この選択は非常に重要です。

モード認証付きIVが必要判定
関連データとともに認証タグを生成し、改ざんがすぐに検出できるようにしますいいえいいえ決して使用しない——同じ明文は同じ暗号文を生成し、パターンを漏らす
CBCいいえはい古く、認証機能がなく、パディングオーラクル攻撃に脆弱
GCMはい(AEAD)はい(ノンス)これを使用——1回のパスで暗号化と認証を実行

GCM(Galois/Counterモード)を使用します。GCMは、認証付き暗号(AEAD)です。2つのことを同時に行います。

  1. データを鍵なしでは読めないよう暗号化
  2. 認証タグを生成するため、改ざんがすぐに検出可能になる

認証がなければ、攻撃者は暗号文内のビットを変更でき、その結果、復号化されたデータが破壊されてもそのことに気づかないことになります。GCMを使用すれば、暗号文が改ざんされた場合、暗号化前に復号化が失敗し、そのことによってすぐに検知できます。

IV/ノンス:ランダムで再使用しない

GCMは初期化ベクター(IV)もしくはノンス(「一度使われた数値」とも)を必要とします。IVは秘密でなくても、次の条件を満たさなければなりません。

  • ランダム — キーベースのセキュアなランダム生成器で生成される
  • 個性的 — 同じ鍵と再使用されない

同じ鍵でIVを再使用することは、災害的です。同じ鍵とIVで暗号化された2つの暗号文が攻撃者に見える場合、それらをXORして両方の明文を回復できます。これは理論的ではありません——実際に生産環境で発生しています。

1回の暗号化操作ごとに96ビット(12バイト)のランダムなIVを使用します。復号化のために必要なので、暗号文と共に保存してください。暗号文の前にIVを付けるのが標準的なフォーマットです。

実際のコード:AES-256-GCM

以下は、生産環境で使用できるスニペットです。暗号文にIVと認証タグを保存することで、復号化は自立して実行できます。

Node.js

const crypto = require('crypto');

const ALGORITHM = 'aes-256-gcm';
const KEY_LENGTH = 32; // 256 bits
const IV_LENGTH  = 12; // 96 bits — recommended for GCM
const TAG_LENGTH = 16; // 128-bit auth tag

function encrypt(plaintext, key) {
  const iv = crypto.randomBytes(IV_LENGTH);
  const cipher = crypto.createCipheriv(ALGORITHM, key, iv);

  const encrypted = Buffer.concat([
    cipher.update(plaintext, 'utf8'),
    cipher.final(),
  ]);
  const tag = cipher.getAuthTag();

  // Layout: [iv (12)] + [tag (16)] + [ciphertext]
  return Buffer.concat([iv, tag, encrypted]).toString('base64');
}

function decrypt(ciphertextB64, key) {
  const data      = Buffer.from(ciphertextB64, 'base64');
  const iv        = data.subarray(0, IV_LENGTH);
  const tag       = data.subarray(IV_LENGTH, IV_LENGTH + TAG_LENGTH);
  const encrypted = data.subarray(IV_LENGTH + TAG_LENGTH);

  const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
  decipher.setAuthTag(tag);

  return Buffer.concat([decipher.update(encrypted), decipher.final()]).toString('utf8');
}

// Usage
const key        = crypto.randomBytes(KEY_LENGTH); // store this securely
const ciphertext = encrypt('sensitive data here', key);
const plaintext  = decrypt(ciphertext, key);

パイソン

import os, base64
from cryptography.hazmat.primitives.ciphers.aead import AESGCM

IV_LENGTH = 12  # 96 bits

def encrypt(plaintext: str, key: bytes) -> str:
    iv = os.urandom(IV_LENGTH)
    aesgcm = AESGCM(key)
    # encrypt() appends the 16-byte auth tag automatically
    ciphertext = aesgcm.encrypt(iv, plaintext.encode(), None)
    return base64.b64encode(iv + ciphertext).decode()

def decrypt(ciphertext_b64: str, key: bytes) -> str:
    data       = base64.b64decode(ciphertext_b64)
    iv         = data[:IV_LENGTH]
    ciphertext = data[IV_LENGTH:]
    aesgcm = AESGCM(key)
    return aesgcm.decrypt(iv, ciphertext, None).decode()

# Usage
key        = AESGCM.generate_key(bit_length=256)  # store this securely
ciphertext = encrypt('sensitive data here', key)
plaintext  = decrypt(ciphertext, key)

依存関係をインストールします: pip install cryptography

AESの暗号化と復号化をインタラクティブにテストできるように、設定なしで使用できます。 IO Tools AES暗号化/復号化ツール.

鍵管理:難しい部分

あなたの暗号化の強さは、鍵管理に依存します。最も一般的な誤りは次の通りです:

  • 鍵を暗号化データと同じデータベースに保存 — 攻撃者がデータベースダンプを取得すれば、鍵も取得できる。
  • 鍵をソースコントロールにコミット — たとえgitignoreされている場合でも .env、回転が困難になり、履歴が残ります。
  • ログに鍵が表示される — アプリケーションログは集約システムに送られます。鍵は決してその場で表示すべきではありません。

実際に鍵をどこに保存すべきか:

  • AWS KMS / Google Cloud KMS / Azure Key Vault — 管理された鍵ストアで、監査履歴と自動回転が提供されます
  • HashiCorp Vault — 自社ホスティング、複数クラウド環境に適しています
  • 環境変数 — 感度が低いワークロードで、露出面が限られている場合に適しています

データベースフィールドの暗号化では、エンベロープ暗号化が標準的なパターンです。1レコードまたは1カラムごとにデータ暗号化鍵(DEK)を生成し、そのDEKをKMSに保存されたマスター鍵で暗号化します。データベースには、暗号化されたDEKと暗号文のみが保存され、マスター鍵はデータベースに一度も触れません。

AESを使用するべきタイミングと使用しないべきタイミング

AESは次の場面で適しています:

  • データベース内のフィールドを暗号化 — SSN、カード番号、健康記録
  • 静止中のファイルを暗号化 クラウドストレージに保存する前に
  • サービス間での秘密共有 事前に共有鍵を持っている場合

AESは次の場面では適していません:

  • ネットワークを介してデータを送信する場合 — TLSを使用してください。自作のトランスポート層は避けてください。
  • 非対称暗号が必要な場合 — 送信元と受信元が事前に鍵を共有できない場合、RSAまたはECDHを使用して鍵交換を行ってください。
  • パスワードを保存する場合 — bcrypt、scrypt、またはArgon2を使用してください。暗号化されたパスワードは復号可能ですが、適切にハッシュされたパスワードは復号できません。
  • 管理されたソリューションが適している — AWS Secrets Manager、Vault、または類似のサービスは、自動回転、アクセス制御、監査ログを提供しており、必要に応じてその機能を活用してください。AESを手動で実装するより優先してください。

開発者が最もよく間違えるのは、AESを完全なセキュリティソリューションとして扱うことです。AESは基本的な暗号化手段であり、構成要素です。認証モード(GCM)、各操作ごとにユニークなIV、そして適切な鍵管理を組み合わせることで非常に効果的になります。これらの要素のいずれかを省略すれば、見た目は安全に見えますが、実際には安全ではありません。

広告なしで楽しみたいですか? 今すぐ広告なしで

拡張機能をインストールする

お気に入りのブラウザにIOツールを追加して、すぐにアクセスし、検索を高速化します。

に追加 Chrome拡張機能 に追加 エッジ拡張 に追加 Firefox 拡張機能 に追加 Opera 拡張機能

スコアボードが到着しました!

スコアボード ゲームを追跡する楽しい方法です。すべてのデータはブラウザに保存されます。さらに多くの機能がまもなく登場します!

ニュースコーナー 技術ハイライト付き

参加する

価値ある無料ツールの提供を継続するためにご協力ください

コーヒーを買って