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

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

All examples on this page work on VillageSQL. Install Now →
MySQL には AES_ENCRYPT() が組み込まれています。問題は、そのデフォルトのモードである aes-128-ecb が安全でないことです。ECB 暗号化は決定的です。同じ平文を同じ鍵で暗号化すると、常に同じ暗号文が生成されます。暗号化された列を見た攻撃者は、鍵を知らなくても繰り返される値を見つけられます。VillageSQL の encrypt() はランダムな IV を使った CBC モードを自動的に使うため、同一の入力でも毎回異なる出力が生成されます。

MySQL のデフォルト: ECB モード

MySQL の AES_ENCRYPT(data, key) は、デフォルトで aes-128-ecb(block_encryption_mode)です。ECB(Electronic Codebook)は、ランダム性なしに各ブロックを独立して暗号化します。同じ値を持つ 2 つの行は同じ暗号文を生成します。
MySQL 8.0 では block_encryption_mode を変更して CBC を使えますが、その場合は IV を自分で管理しなければなりません。生成し、暗号文と並べて格納し、毎回 AES_DECRYPT() に渡し直す必要があります。

標準的な回避策: AES-CBC での手動 IV

MySQL で CBC モードを正しく使うには、IV を明示的に格納して渡す必要があります。
これは正しいのですが冗長です。すべてのテーブルに追加の IV 列が必要で、暗号化されたデータに触れるすべてのクエリが IV を渡さなければなりません。

VillageSQL の場合: 自動的な IV 管理

VillageSQL の vsql_crypto 拡張機能は、IV を自動的に処理する encrypt() と decrypt() を追加します。IV は呼び出しごとに新しく生成され、格納される値の中で暗号文の前に付加されます。decrypt() は、利用者が意識しなくてもそれを取り出します。
IV 列も、クエリ内の IV パラメータも不要です。同じ SSN を持つ 2 つの行は異なる暗号文を生成し、パターンの漏洩はありません。

鍵のサイズ

暗号が必要とする長さより短い鍵は、ERROR 3200: VDF error in function 'encrypt': key too short for <cipher>: need N bytes, got M を発生させます。ゼロで埋められることはありません。長い鍵は黙って切り詰められます。ちょうど 16、24、または 32 バイトを使ってください。

何を格納するか

VARBINARY 列は、暗号文と、その前に付加された IV(16 バイト)を保持します。PKCS7 パディングは、平文の長さがすでに 16 のちょうど倍数であるとき、常に完全な AES ブロック 1 つ分(16 バイト)を追加します。パディングが 0 バイトになることはありません。したがって安全な計算式は、平文の長さ + 合計 32 バイト(IV に 16、パディングに最大 16)です。余裕を持って列のサイズを決めてください。

これがカバーしないもの

SQL での列レベルの暗号化は、データベースへのアクセス権はあるが鍵を持たない人物から、保存されているデータを保護します。次のものからは保護しません。
  • 鍵を保持し、復号したデータをクエリするアプリケーションコード。アプリを侵害した攻撃者は両方を手に入れます
  • 暗号化された列でフィルタまたはソートするクエリ(復号せずに WHERE ssn = ? はできません)
検索可能な暗号化や、エンベロープ鍵管理(すべてのデータを再暗号化せずに鍵をローテーションする)には、アプリケーション層に追加の基盤が必要です。

よくある質問

暗号鍵はどこに保管すべきですか?

データベースの中ではありません。鍵は、シークレットマネージャ(AWS Secrets Manager、HashiCorp Vault、GCP Secret Manager)または環境変数に置き、アプリケーションが実行時に読み込みます。暗号化対象と同じデータベースに保管された鍵は、何の保護にもなりません。

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

直接はできません。一致を見つけるためにすべての行を復号するのはフルテーブルスキャンです。よくあるパターンは、等価検索のために値の決定的なハッシュを暗号化された列と並べて格納する(SSN 検索のための sha256(ssn))か、アプリケーション層で復号して暗号化された検索インデックスを構築することです。

鍵を失うとどうなりますか?

データは復元できません。鍵はデータベースとは別にバックアップしてください。エンベロープ暗号化(データ鍵をマスター鍵で包む)を検討してください。すべてを再暗号化せずにマスター鍵をローテーションできます。

DEFAULT 式で列を暗号化できますか?

現在はできません。非決定的な関数(ランダムな IV のため、encrypt() はそうです)は DEFAULT 式で使えません。暗号化された値は各 INSERT で生成してください。

トラブルシューティング

関連項目