しめ鯖日記

swift, iPhoneアプリ開発, ruby on rails等のTipsや入門記事書いてます

個人情報カラムの暗号化に丁度いいGem、attr_encrypted

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_が付くのも分かりやすくて運用しやすそうだと感じました。
人によっては冗長なので嫌いそうですが。