VillageSQL is a drop-in replacement for MySQL with extensions.
All examples on this page work on VillageSQL. Install Now →
AES_ENCRYPT() が組み込まれていますが、デフォルトでは安全でないモードになります。このガイドでは、トレードオフ、MySQL で AES を正しく使う方法、および SQL とアプリケーション層のどちらで暗号化すべきかを扱います。
MySQL での AES 暗号化の仕組み
MySQL のAES_ENCRYPT(data, key) は、鍵文字列から導出した鍵で 128 ビット AES を使います。デフォルトのモードは ECB(Electronic Codebook)で、16 バイトの各ブロックが独立して暗号化されます。ECB は決定的です。同じ 16 バイトの入力は、常に同じ 16 バイトの出力を生成します。そのため、暗号文にパターンが現れます。
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() を直接呼び出せます。
トラブルシューティング
関連項目
- MySQL での列の暗号化 — vsql_crypto で列レベルの暗号化を適用する
- MySQL でのデータのハッシュ化 — 復号が不要な場合の一方向の操作