rails 3.1和3.2之间的ActiveSupport :: MessageEncryptor不同

时间:2015-02-03 01:16:12

标签: ruby-on-rails ruby ruby-on-rails-3 encryption ruby-on-rails-3.2

我有一个旧项目,我正试图沿着升级路径从Rails 3.1移动到3.2。我遇到了ActiveSupport :: MessageEncryptor的问题 - 在Rails 3.1中加密的数据无法在Rails 3.2中解密 - 我收到以下错误: 的ActiveSupport :: MessageEncryptor :: InvalidMessage

以下是Rails控制台中两个会话的输出 - 首先我在Rails 3.1.12中加密示例字符串:

Loading development environment (Rails 3.1.12)
2.1.5 :001 > secret = "01ac28236532ee53e0a0c4f562ce2f398c7e9287f5015d2baab0e1d986579a1a2fb6296946327ffffc3a"
 => "01ac28236532ee53e0a0c4f562ce2f398c7e9287f5015d2baab0e1d986579a1a2fb6296946327ffffc3a"
2.1.5 :002 > encryptor =  ActiveSupport::MessageEncryptor.new(secret)
 => #<ActiveSupport::MessageEncryptor:0x007fd8a6f607a8 @secret="01ac28236532ee53e0a0c4f562ce2f398c7e9287f5015d2baab0e1d986579a1a2fb6296946327ffffc3a", @cipher="aes-256-cbc">
2.1.5 :003 > encryptor.encrypt_and_sign("123-45-6789")
 => "BAhJIktNaE1kZHkwUHZZWVFub2RVeFk3MEY2Sm9LMjA3SzUzYXYxVStVb25HZlhjPS0tTzRXZmRwODJqZ1Boa0twdHlWeWthUT09BjoGRUY=--70b6be792b274777104f53c2f4f324320e9cd808"

现在我尝试在Rails 3.2环境中解密生成的字符串:

Loading development environment (Rails 3.2.21)
2.1.5 :001 > secret = "01ac28236532ee53e0a0c4f562ce2f398c7e9287f5015d2baab0e1d986579a1a2fb6296946327ffffc3a"
 => "01ac28236532ee53e0a0c4f562ce2f398c7e9287f5015d2baab0e1d986579a1a2fb6296946327ffffc3a"
2.1.5 :002 > encryptor =  ActiveSupport::MessageEncryptor.new(secret)
 => #<ActiveSupport::MessageEncryptor:0x007f8802a02508 @secret="01ac28236532ee53e0a0c4f562ce2f398c7e9287f5015d2baab0e1d986579a1a2fb6296946327ffffc3a", @cipher="aes-256-cbc", @verifier=#<ActiveSupport::MessageVerifier:0x007f8802a09bf0 @secret="01ac28236532ee53e0a0c4f562ce2f398c7e9287f5015d2baab0e1d986579a1a2fb6296946327ffffc3a", @digest="SHA1", @serializer=ActiveSupport::MessageEncryptor::NullSerializer>, @serializer=Marshal>
2.1.5 :003 > encryptor.decrypt_and_verify("BAhJIktNaE1kZHkwUHZZWVFub2RVeFk3MEY2Sm9LMjA3SzUzYXYxVStVb25HZlhjPS0tTzRXZmRwODJqZ1Boa0twdHlWeWthUT09BjoGRUY=--70b6be792b274777104f53c2f4f324320e9cd808")
ActiveSupport::MessageEncryptor::InvalidMessage: ActiveSupport::MessageEncryptor::InvalidMessage

在这两种情况下,我都使用默认密码“aes-256-cbc”;我注意到rails 3.2中的ActiveSupport :: MessageEncryptor对象附加了一些实例变量。我希望能够以一种可以在rails 3.2下读取的格式在新的数据库字段中重写我的数据,所以我想让3.1中的ActiveSupport :: MessageEncryptor拥有它在3.2中拥有的所有属性。 。知道我错过了什么吗?

1 个答案:

答案 0 :(得分:1)

我发现了我的问题:

MessageEncryptor对象在Rails 3.2下在3.1中没有的一个属性是MessageVerifier。 (在3.1中,函数verifier包装对MessageVerifier.new的调用,而在3.2中,验证器是实例变量@verifier的读取器,在初始化时创建。)

在3.1中,MessageVerifier使用Marshal作为其序列化程序。在3.2中,它支持选择另一个序列化程序。 MessageEncryptor的初始化程序调用MessageVerifier.new,但为序列化程序指定NullSerializer。

因此,虽然我的旧数据已由加密器加密,而加密器的验证程序正在使用Marshal作为其序列化程序,但新加密器正试图使用​​其序列化程序为NullSerializer的验证程序读取它。

关于所有这一切最令人困惑的是我找不到关于同一问题的任何帖子。这对任何人都有用吗?

无论如何,我在ActiveSupport :: MessageEncryptor上使用猴子补丁解决了我的问题,如下所示:

module ActiveSupport
  class MessageEncryptor
    def initialize(secret, options = {})

      unless options.is_a?(Hash)
        ActiveSupport::Deprecation.warn "The second parameter should be an options hash. Use :cipher => 'algorithm' to specify the cipher algorithm."
        options = { :cipher => options }
      end

      @secret = secret
      @cipher = options[:cipher] || 'aes-256-cbc'

      # the default version of this function creates the verifier with NullSerializer, not providing the option to specify a serializer
      # however, in ActiveSupport 3.1 and earlier MessageVerifier uses the Marshal serializer; thus, all our existing data was verified
      # and subsequently encrypted using Marshal.
      # Considering migrating all existing data over to a new value using NullSerializer, as the latest version of ActiveSupport::MessageEncryptor
      # still has a verifier that's hard-coded to use NullSerializer. If we do that, then we can get rid of this patch once the migration is complete
      @verifier = MessageVerifier.new(@secret, :serializer => options[:verifier_serializer] || NullSerializer)
      @serializer = options[:serializer] || Marshal

    end
  end
end