メインコンテンツへスキップ

VillageSQL is a drop-in replacement for MySQL with extensions.

All examples on this page work on VillageSQL. Install Now →
対称暗号化は、暗号化と復号に同じ鍵を使います。機密データを保存し、後で元の値を取り出す必要がある場合に適したツールです。一方向であるハッシュ化とは異なります。MySQL には AES_ENCRYPT() が組み込まれていますが、デフォルトでは安全でないモードになります。このガイドでは、トレードオフ、MySQL で AES を正しく使う方法、および SQL とアプリケーション層のどちらで暗号化すべきかを扱います。

MySQL での AES 暗号化の仕組み

MySQL の AES_ENCRYPT(data, key) は、鍵文字列から導出した鍵で 128 ビット AES を使います。デフォルトのモードは ECB(Electronic Codebook)で、16 バイトの各ブロックが独立して暗号化されます。ECB は決定的です。同じ 16 バイトの入力は、常に同じ 16 バイトの出力を生成します。そのため、暗号文にパターンが現れます。
CBC モード(Cipher Block Chaining)は、暗号化の前に各ブロックを直前の暗号文と XOR し、最初のブロックにはランダムな初期化ベクトル(IV)を使うことでこれを解決します。同じ平文でも、呼び出しのたびに異なる暗号文が生成されます。 MySQL は CBC をサポートしますが、block_encryption_mode を変更し、IV を自分で管理することでオプトインする必要があります。

VillageSQL の場合: 自動的な CBC と IV の処理

VillageSQL の vsql_crypto 拡張機能は encrypt() と decrypt() を提供します。これらは、呼び出しごとに生成されるランダムな IV を使った AES-CBC を使います。IV は暗号文の先頭に付加されます。追加の列も、追加のパラメータも不要です。

AES の鍵サイズ

鍵長は鍵文字列のバイト数で強制されます。暗号が要求するより短い鍵は、ゼロでパディングされるのではなく ERROR 3200: VDF error in function 'encrypt': key too short for <cipher>: need N bytes, got M を発生させます。長い鍵は、必要な長さまで黙って切り詰められます。予想外の動作が起きる場合は LENGTH(@key) を確認してください。

暗号化したデータの保存

encrypt() は VARBINARY を返します。保存される値には、暗号文の先頭に付加された 16 バイトの IV が含まれます。それに合わせて列のサイズを決めてください。

MySQL と VillageSQL の比較

SQL とアプリケーション層のどちらで暗号化するか

SQL での暗号化は便利ですが、トレードオフがあります。 SQL 層の暗号化は、アプリケーションは信頼できるがデータベースレベルのアクセス(バックアップ、リードレプリカ、漏洩した DB 認証情報)が心配な場合に、保存データを保護するのに役立ちます。アプリケーション層の暗号化は、鍵をより細かく制御でき、SQL のログの近くに平文を置かずに済みます。 列レベルのパターンとスキーマ設計については、MySQL での列の暗号化を参照してください。

よくある質問

対称暗号化と非対称暗号化の違いは何ですか?

対称暗号化(AES)は、暗号化と復号に同じ鍵を使います。高速で、大量のデータに適しています。非対称暗号化(RSA)は、暗号化に公開鍵、復号に秘密鍵を使います。鍵交換には便利ですが、大量のデータには遅すぎます。機密性の高い列データの保存には、対称の AES が正しい選択です。

暗号化された列を検索できますか?

直接はできません。暗号化された値で行を見つけるには、すべての行を復号する必要があり、フルテーブルスキャンになります。一般的な回避策は、等価検索のために、平文の鍵付きハッシュ(HMAC)を別のインデックス付きの列に保存することです。これは、2 つの行が同じ値を持つことは漏らしますが、その値が何かは漏らしません。

暗号鍵をローテーションするには?

すべての行を読み、古い鍵で復号し、新しい鍵で再暗号化し、書き戻します。大きなテーブルではバッチで行ってください。これが SQL 層の暗号化の主な運用コストです。エンベロープ暗号化(データ鍵をマスター鍵で暗号化する)を使えば、データに触れずにマスター鍵をローテーションできます。

AES 暗号化は SQL インジェクションから保護しますか?

いいえ。暗号化は保存された値を保護します。SQL インジェクションは入力検証の問題です。任意の SQL を実行できる攻撃者は、decrypt() を直接呼び出せます。

トラブルシューティング

関連項目