blog.kotamiyake.me

為せば成る、為さねば成らぬ何事も

以前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='