可逆式で暗号化を実装してみた
ソース
# frozen_string_literal: true # NOTE: 可逆式で暗号化して保存する # 対象をcodeとしたい場合 # * テーブルに encrypted_code を定義する # * テーブルに digested_code を定義する(indexに使用する) # * モデルに attr_encrypted :code を定義する # model_instance.code = xxx として使用する module Encryptable extend ActiveSupport::Concern ENCRYPTE_PURPOSE = "XXXX" ENCRYPTION_SALT = if Rails.env.staging? || Rails.env.production? ["SECRET_KEY_BASE"][1..32] else Rails.application.credentials.config[:secret_key_base][1..32] end # NOTE: 下記が定義される # code, code=, digest_code included do def self.attr_encrypted(attribute) # rubocop:disable Metrics/AbcSize encrypt_column_name = "encrypted_#{attribute}" digest_column_name = "digested_#{attribute}" crypt = ActiveSupport::MessageEncryptor.new(ENCRYPTION_SALT) # NOTE: 非暗号の値のゲッター define_method(attribute.to_s) do encrypted_data = public_send(encrypt_column_name.to_s) return nil if encrypted_data.blank? decrypted_data = instance_variable_get("@#{attribute}") return decrypted_data if decrypted_data.present? decrypted_data = crypt.decrypt_and_verify(encrypted_data, purpose: ENCRYPTE_PURPOSE) instance_variable_set("@#{attribute}", decrypted_data) end # NOTE: 非暗号の値のセッター define_method("#{attribute}=") do |val| encrypted_data = public_send(encrypt_column_name.to_s) # NOTE: 値に差分がない場合なにもしない(同じ値でも暗号値が変わるため) return if encrypted_data.present? && val == crypt.decrypt_and_verify(encrypted_data, purpose: ENCRYPTE_PURPOSE) instance_variable_set("@#{attribute}", val) encrypted_data = crypt.encrypt_and_sign(val, purpose: ENCRYPTE_PURPOSE) public_send("#{encrypt_column_name}=", encrypted_data) public_send("#{digest_column_name}=", Encryptable.generate_digest(val || "")) end # NOTE: 生のデータから検索を行う条件を設定 scope "digest_#{attribute}", ->(val) { where(sanitize_sql(digest_column_name) => Encryptable.generate_digest(val)) } end end def self.generate_digest(val) OpenSSL::Digest::SHA256.hexdigest(ENCRYPTION_SALT + val) end end 参考
-
attr-encrypted/attr_encrypted: Generates attr_accessors that encrypt and decrypt attributes iv(initialize vector)の実装の必要性に気付き素直にgemを使用することにした。 (ちなみに、桁数が大きくなるほど、暗号化した後の桁数の幅は、自前で実装した方が少ない)
-
[可逆式、不可逆式で暗号化したい ベジタブルプログラム](https://www.blog.v41.me/posts/ab5008a3-27a0-4053-8632-8b6ff84fd0fe)
This post is licensed under CC BY 4.0 by the author.