初めまして、ガッシーです。Qiita初投稿となります。(なんか癖でQuiitaって打っちゃうんですよね)
日頃Railsの開発で躓いて調べたことなどを書き留めていければなと思ってます。
そんなところで本題へ。
railsでカラムを暗号化する際には一般的にattr_encryptedを利用するかと思いますが
READMEを翻訳しますと
暗号化されたデータを検索することはできません。検索できないため、インデックスを作成することもできません。
との記載があります。
でも暗号化しつつ検索したいことって結構あると思うんですよね。
そこで登場するGemがblind_indexです。
ただし LIKE検索はできない ので注意してください。
#blind_indexとは
例えばnameというカラムでattr_encryptedを使うときは encrypted_name
と encrypted_name_iv
の2つのカラムを用意すると思いますが、
それに加えて encrypted_name_bidx
というカラムを追加してあげることで、そこに検索できる値を保存する感じです。早速やってみましょう。
##設定
READMEに書いてあることをそのままやっていけばいいのですが一応書きます。
Gemfileに下記を追加してbundle install
gem 'blind_index'
コンソールを起動して下記コードを実行しランダムなキーを取得します。
irb(main):001:0> BlindIndex.generate_key
# SecureRandom.hex(32).force_encoding(Encoding::US_ASCII) でも同じ
=> "222189cbba7ba0381c66faf8f687197b4bd4256a99bf81c917256c2871ca5289"
キーを保存・設定します。
blind_index_master_key: "222189cbba7ba0381c66faf8f687197b4bd4256a99bf81c917256c2871ca5289"
BlindIndex.master_key = Rails.application.credentials.blind_index_master_key
(initializerを読み込むためサーバーは再起動しておいてください)
blind_index用のカラムを追加します。
add_column :users, :encrypted_name_bidx, :string
modelも変更を加えます。
class User < ApplicationRecord
attr_encrypted :name, key: Rails.application.credentials.encrypted_key
blind_index :name, key: Rails.application.credentials.blind_index_master_key #←こちら追加
end
以上で設定は完了です!
※既に暗号化カラムが保存されている方はコンソールにて下記コマンドを実行することで既存のレコードにも対応できます。
User.unscoped.where(encrypted_name_bidx: nil).find_each do |user|
user.compute_name_bidx
user.save(validate: false)
end
##実行
User.where(name: "山田太郎")
これができるようになっているはずです。
#感想
完全一致検索しかできないけど何もできないよりはマシか・・・
知識がないのですが、最初こちらの記事 attr_encryptedされたカラムに対してwhere likeしたかった。を見ましたが恐らく現在ivカラムを利用した暗号化を行っている場合は適応できないかな?と思ってます。
Qiita初めての記事となりましたのでもし誤りがありましたらご指摘いただければ幸いです。