質問: PHPに限った話ではないですが、復号可能なデータをデータベースに安全に保管する方法について考えています。 仮に会員名簿のメールアドレスを暗号化して保存するとします。 暗号化方式には一般的と思われる「AES-128-CBC」を使います。 暗号化に必要な初期化ベクトル(IV)はランダムな16バイトのデータを用います。 複合したデータを閲覧可能なのは管理者だけなので暗号化の際のパスワードは全員共通か、それぞれにランダムなパスワードを生成しても良さそうです。 いろいろなサイトを見る限りではIVの値は先頭につけて「IV + 暗号化したデータ」の形で保存しているようでした。 パスワードが全員共通ならコンフィグファイル書いておいたパスワードで暗号化すれば良さそうですが、パスワードを全員ランダムにするならそのパスワードもデータベースに保存しておかなければいけません。 先程の流れで行くと「IV + パスワード + 暗号化したデータ」とし、区切り文字で区別するかパスワードの文字数を固定して文字数で切り出せば取り出せそうです。 ここでデータベースの内容が外部に流出したケースを想定します。 まず不正入手者は暗号化方式はありふれた「AES-128-CBC」だと仮定し、IV の長さは16文字だと推測します。 次にデータベースの内容を見て先頭16文字がIVで残りが暗号文と考えます。パスワードが全員共通でコンフィグファイルに書かれている場合はパスワードは不明なのでランダムなパスワードを総当りで試し一人成功すれば全員分のデータを復号できます。 パスワードが一人ひとり分かれておりデータベースに「IV + パスワード + 暗号化したデータ」の形で保存されているなら総当りする必要もなく簡単に復号できます。これはかえって危険なようにも見えます。データベースにはパスワードそのものではなくソルトをもたせ、コンフィグの全員共通のパスワードと合わせることで正しく復号できるようにするなら少しは時間が稼げそうです。 どちらも完全には安全といえないように思えますが何か間違っているでしょうか? あるいはもっと根本的に異なる安全な保管の仕方があるのでしょうか? よろしくお願いします。
回答: > > パスワードが一人ひとり分かれておりデータベースに「IV + パスワード + 暗号化したデータ」の形で保存されているなら総当りする必要もなく簡単に復号できます。これはかえって危険なようにも見えます > > > その通りです。なのでパスワード(暗号鍵)はDBには保存せずに、共通の暗号鍵を安全な方法で保存するという方法が一般的かと思います。