attr_encryptedというGemに関する調査メモです。
attr_encryptedとは
カラムの暗号化を簡単にしてくれるGemです。
基本的な使い方
GemfileにGemの追加
gem 'attr_encrypted'
テーブル作成。
暗号化したいカラムは先頭にencrypted_
を付けます。
class CreateItems < ActiveRecord::Migration def change create_table :items do |t| t.string :encrypted_ssn t.timestamps end end end
Modelで暗号化したいカラムを指定します。
ここでは先頭のencrypted_
を外してカラム名を指定します。
class Item < ActiveRecord::Base attr_encrypted :ssn, key: 'a secret key' end
これで設定が完了です。
Itemのssnというアクセサに値を入れるとencrypted_ssn
に値が入ります。
> item = Item.new > item.ssn = 111 > p item => #<Item id: nil, encrypted_ssn: "7soC4rjWnvr11UQbMFvuHA==\n"> > p item.ssn => 111
encrypted_ssn
に変な値を入れた場合はsaveは成功するのですがssn
を取得しようとすると例外になります。
データの不整合が起こりえるのは怖いですね。
> item = Item.new > item.encrypted_ssn = 111 > item.save > item.ssn => OpenSSL::Cipher::CipherError: wrong final block length
利用できるオプション
saltを使う場合はmodeオプションを使います。
下のようにper_attribute_iv_and_salt
オプションを使い、テーブルには_salt
付きと_iv
付きカラムを追加すると使えるようになります。
_salt
付きと_iv
付きカラムがない場合はssn取得時にエラーになります。
データの保存は普通にできてしまうので、ここもデータの不整合が発生しようで怖いですね。
ちなみにiv
とは「初期化ベクトル」の事だと思われます。
「初期化ベクトル」は暗号化のキーに使われる値のようですがsalt
との違いがイマイチわからないです。
class Item attr_encrypted :ssn, key: 'a secret key', mode: :per_attribute_iv_and_salt end
create_table :users do |t| t.string :encrypted_ssn t.string :encrypted_ssn_salt t.string :encrypted_ssn_iv t.timestamps end
> item = Item.new > item.ssn = 111 > p item => #<Item id: 1, encrypted_ssn: "0wCz2wbhHSwHVPu9B6l2iQ==\n", encrypted_ssn_salt: "5d9da63fb2cc9f85", encrypted_ssn_iv: "GNdLpaB3cMlBbYMgPbAXDA==\n">
下のようにattribute
を使えばencrypted_ssn
でなくssn_encrypted
というカラムに保存する事もできます。
class Item attr_encrypted :ssn, key: 'a secret key', attribute: 'ssn_encrypted' end
ifも使えるので本番環境でだけ暗号化するという事もできます。
暗号化しない場合もssn=
でセットした値はssn_encrypted
に入るので開発環境と本番環境でアクセサを変える必要がありません。
class Item attr_encrypted :ssn, key: 'a secret key', attribute: 'ssn_encrypted', if: Rails.env.production? end
まとめ
attr_encrypted
は暗号化が非常に簡単にできるのでとても使いやすそうです。
カラム名の先頭にencrypted_
が付くのも分かりやすくて運用しやすそうだと感じました。
人によっては冗長なので嫌いそうですが。