以前MessageEncryptorを使った暗号化を紹介したのですが、Rails 5.2では若干使い方が変わっていたので紹介します。
ドキュメントに従い、以下のように書き直します。
pry(main)> len = ActiveSupport::MessageEncryptor.key_len => 32 pry(main)> salt = SecureRandom.random_bytes(len) => "\x10\x8D\xCC\x19%\xD0\x9F{_\xB9\x9C\xDF\xEC\xE9\x10\xA3\xF9\x82\"\r\xE1\xAF\x01.\x17\x00\xAD\xA3=\xA6\xD2\x00" pry(main)> key = ActiveSupport::KeyGenerator.new('salary').generate_key(salt, len) => "\"<\xE7\xC7-Z\xB6\xEA\xB29\x8B\xEBY\x9E\xEF!2\xFCL\x98\x02\xC7\x98;p'@6\xE0gV\xE9" pry(main)> crypt = ActiveSupport::MessageEncryptor.new(key) => #<ActiveSupport::MessageEncryptor:0x00007fe0bd1540f0 @aead_mode=true, @cipher="aes-256-gcm", @options={}, @rotations=[], @secret="\"<\xE7\xC7-Z\xB6\xEA\xB29\x8B\xEBY\x9E\xEF!2\xFCL\x98\x02\xC7\x98;p'@6\xE0gV\xE9", @serializer=Marshal, @sign_secret=nil, @verifier=ActiveSupport::MessageEncryptor::NullVerifier> pry(main)> encrypted_data = crypt.encrypt_and_sign(10000) => "vIhnJ/+b--dVcRCewozcXpKK8c--4UyU9gWcUa46EdjtLBx3vQ==" pry(main)> crypt.decrypt_and_verify(encrypted_data) => 10000
なぜ使い方が変わったのかと言うと、
これまではkeyに長過ぎる値を渡した場合は勝手に正しい長さに切り取ってくれたが、「想定外の結果(unexpected encryption/decryption results)」を引き起こすとして、正しい長さのkeyを渡さないと例外がraiseされるようになった。
ActiveSupport::MessageEncryptorを慎重に使う – nisshieeのブログ – https://nisshiee.hatenablog.jp/entry/2017/04/17/192703
ということらしい。
そのため以前のコードを実行するとエラーになります。
pry(main)> salery = 10000 => 10000 pry(main)> secret = SecureRandom.hex(128) => "b991b09ab1a52e6649e5f836c4efcb28ec0d7e899e88be7b072cf752bf2194e8d2600dc524748f67d400a831f967a3a7b7c0b64d0af7b19cc2ee92300aa8c028699ca35ed9bb28f45d6238bf37476832e89638c200efb9ef8dccdf368f920d9d4a6ad941402a6c0ebb078e5b80d2ce76e3dafe45c3d44389c9c3633e710afde2" pry(main)> encryptor = ::ActiveSupport::MessageEncryptor.new(secret) => #<ActiveSupport::MessageEncryptor:0x00007fe0c1bd3f68 @aead_mode=true, @cipher="aes-256-gcm", @options={}, @rotations=[], @secret= "b991b09ab1a52e6649e5f836c4efcb28ec0d7e899e88be7b072cf752bf2194e8d2600dc524748f67d400a831f967a3a7b7c0b64d0af7b19cc2ee92300aa8c028699ca35ed9bb28f45d6238bf37476832e89638c200efb9ef8dccdf368f920d9d4a6ad941402a6c0ebb078e5b80d2ce76e3dafe45c3d44389c9c3633e710afde2", @serializer=Marshal, @sign_secret=nil, @verifier=ActiveSupport::MessageEncryptor::NullVerifier> pry(main)> encrypt_salery = encryptor.encrypt_and_sign(salery) ArgumentError: key must be 32 bytes from /Users/kotamiyake/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activesupport-5.2.0/lib/active_support/message_encryptor.rb:169:in `key='