はじめに
最近いろいろ個人情報保護の観点から、DBに保存する特定フィールドは暗号化して欲しいとのニーズが多くなってきている。
しかも AESアルゴリズム を使えとか。
幸い Laravelの Cryptファサード は AES-256-CBC アルゴリズムなので、モデル側のセッター、ゲッターに機能を実装して、通常のアルゴリズムからは透過的に、DB保存の暗号化・復号化を実現する。
実装方法(アクセサ・ミューテタを使う(laravel推奨))
- まずは通常のモデルを作成する。
- Model 側に Name フィールド用のアクセサ・ミューテタを定義する。
- 暗号化、復号化を実装する。
Admin.php
<?php
use Crypt;
class Admin extends Model
{
public function getNameAttribute($value)
{
return Crypt::decrypt($value);
}
public function setNameAttribute($value)
{
$this->attributes['name'] = Crypt::encrypt($value);
}
}
もちろんシーダー側も
シーダー側も予め暗号化しておく必要がある。
AdminTableSeeder.php
<?php
use Illuminate\Database\Seeder;
//use Crypt;
class AdminTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
DB::table('admins')->truncate();
DB::table('admins')->insert([
'loginid' => 'admin',
'name' => Crypt::encrypt('スーパーバイザー'),
'password' => bcrypt('pass'),
]);
}
}
こんな感じ。
ちなみに use Crypt; を有効にするとシーダーでエラーになる。
$ php artisan db:seed
Seeding: AdminTableSeeder
[ErrorException]
The use statement with non-compound name 'Crypt' has no effect
これはシーダーが Global であるため。正解は Crypt を use しない。
その後の顛末
laravel の Crypt は同じ文字列であっても、暗号化のたびに暗号後の文字列が異なる。
つまり、入力された文字列を暗号化して比較しようとしても一致しない。
もちろん復号化すれば、復号前の文字列が異なっていても両方とも正しく暗号前文字列に戻る。
しかたないから、検索が必要なキーに対しては、暗号後の文字列が一致する自前の暗号化/復号化クラスを自作した。
Crypt ファサードのオプションでなんとかならんかね。