Help us understand the problem. What is going on with this article?

【Ruby 2.4.6 update】ArgumentError: key must be 32 bytes への、versionを動かさない対処

More than 1 year has passed since last update.

背景

Ruby 2.3.1 -> 2.4.6 へversion upしたら、ActiveSupport::MessageEncryptor周りでエラーがでた。
この中で使われているOpenSSLがもともと32bytes以上でも受け入れていたところを、32バイトぴったりしか受け付けなくなったのが原因の様子。
これが修正のcommit
データベースに32バイトより大きいkeyで暗号化したデータが入っていたので、それらをdecryptできなくて落ちていた。
ちなみにRailsは4系。

捕捉

Rails 5.0.0.1 で対応が入っているらしい
https://github.com/rails/rails/pull/25192/files
でも今回はRailsのversionは上げられないので別の対処法を探す。
色々調べた感じ、多くの人はRubyのversionを戻したりとversionを上げ下げしてこの問題を回避してそうだった。

解決案その1

Ruby 2.3系に戻し、32バイトより大きいkeyでdecryptして、32bytesでまたencryptする。
これでもいいのですが、ちょっと時間がかかりそう。

参考

解決案その2

32バイトっていうので、とりあえず32bytesにしてみた。
しかしdecryptで失敗。
これはchiperの方はsecretを32bytesに切ってくれるが、復号で使うverifierの方はそのままの長さを使ってるからのが原因の模様。

d = ActiveSupport::MessageEncryptor.new(some_key[0..31])
rb(main):005:0> d.encrypt_and_sign("hoge")
=> "K3dtYVJUL1NucVpnRUFJWm9OZ3VQQT09LS1SMlRKb3dWWXFFajZ5MDFMcHQ3NmxRPT0=--910efa18ef525a38f7bf2482e94a54ec39ad1e65"

d = ActiveSupport::MessageEncryptor.new(some_key[0..31])
irb(main):003:0> d.encrypt_and_sign("hoge")
ArgumentError: key must be 32 bytes

しかし、ActiveSupport::MessageEncryptorのコードを読んでいたら、optionsで渡せそう。
option引数の先頭で渡せば@sign_secretに入って、そっちが優先されてverifierが作成される。

#=>  ActiveSupport::MessageEncryptor
    def initialize(secret, *signature_key_or_options)
      options = signature_key_or_options.extract_options!
      sign_secret = signature_key_or_options.first
      @secret = secret
      @sign_secret = sign_secret
      @cipher = options[:cipher] || 'aes-256-cbc'
      @verifier = MessageVerifier.new(@sign_secret || @secret, digest: options[:digest] || 'SHA1', serializer: NullSerializer)
      @serializer = options[:serializer] || Marshal
    end

つまりこうすれば良い。

  ActiveSupport::MessageEncryptor.new(some_key[0..31], some_key) 

急ぎだったので、解決案2で解決しました。
salt使うように修正予定。

終わり

ベテランの方に助けてもらいました
ライブラリのコードリーディング力を高めなければ

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away