使用attr_encrypted用铁轨7

发布于 2025-01-25 19:42:59 字数 339 浏览 1 评论 0 原文

我们已将应用程序升级为Rails 7,现在我们对Attr_encrypted Gem有问题。当我们尝试启动Rails服务器/控制台时,我们会收到以下错误:

gems/ruby-3.0.2/gems/attr_encrypted-3.1.0/lib/attr_encrypted.rb:176:in `block in attr_encrypted': undefined method `[]=' for nil:NilClass (NoMethodError)

如果回到Rails 6,错误消失了,是否有人遇到了同样的问题?

We have upgraded our application to rails 7, and we are now having issues with the attr_encrypted gem. When we try start a rails server/console we get the following error:

gems/ruby-3.0.2/gems/attr_encrypted-3.1.0/lib/attr_encrypted.rb:176:in `block in attr_encrypted': undefined method `[]=' for nil:NilClass (NoMethodError)

If we revert back to rails 6 the error disappears, has anyone experienced the same issue?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

陪你到最终 2025-02-01 19:42:59

所以我终于弄清楚了发生了什么。

Rails 7.0具有其自身的加密,Attr_encrypted Gem和Rails 7是指变量 gencrypted_attributes ,而Rails 7变量则优先考虑,使Gem无用。 Attr_encrypted Gem上有一个PR可以解决此问题,但是GEM已多年没有更新,我怀疑现在会这样。

Gorails发布了一个教程,有关如何将数据从使用attr_encrypted迁移到使用Rails 7加密的教程。我不想付钱,所以我检查了该教程的GIT回购。

他们所做的是在迁移中解密数据并手动更新了新的加密字段。

这是他们迁移的链接。

So I have finally figured out what's going on.

Rails 7.0 has it's own encryption, both the attr_encrypted gem and rails 7 refer to the variable encrypted_attributes and the rails 7 variable takes precedence making the gem useless. There is a PR on the attr_encrypted gem to fix this but the gem has not been updated in years and I doubt it will be now.

GoRails published a tutorial on how to migrate your data from using attr_encrypted to using the rails 7 encryption. I did not want to pay for it so I checked out the git repo for the tutorial.

What they did is they decrypted the data themselves in a migration and updated the new encrypted fields manually.

Here is the link to their migration.
https://github.com/gorails-screencasts/migrate-attr_encrypted-to-rails-7-encryption/blob/master/db/migrate/20211005214633_migrate_encrypted_attributes.rb

呆° 2025-02-01 19:42:59

a 新版本4.0.0 attr_encrypted 于2023年4月6日发布,并带有Rails 7支持。

A new version 4.0.0 of the gem attr_encrypted was released on April 6 2023 and it comes with Rails 7 support.

命比纸薄 2025-02-01 19:42:59

基于先前的答案,两个方向都完全迁移:

class SwitchToRailsBuiltInEncryption < ActiveRecord::Migration[7.0]

  ATTRIBUTES = [
    [Account, :password],
    [Account, :client_secret],
  ]

  def up
    ATTRIBUTES.each do |klass, attribute|
      klass.reset_column_information

      add_column klass.table_name, attribute, :string, length: 510

      klass.all.each do |record|
        puts "Processing #{klass} with ID #{record.id}"
        if record.send("encrypted_#{attribute}").present?
          encrypted_value = record.send("encrypted_#{attribute}")
          iv = record.send("encrypted_#{attribute}_iv")
          value = decrypt(encrypted_value, iv)
          record.update!(attribute => value)
        end
      end

      remove_column klass.table_name, "encrypted_#{attribute}"
      remove_column klass.table_name, "encrypted_#{attribute}_iv"
    end
  end

  def down
    ATTRIBUTES.each do |klass, attribute|
      add_column klass.table_name, "encrypted_#{attribute}", :string, length: 510
      add_column klass.table_name, "encrypted_#{attribute}_iv", :string, length: 510

      klass.all.each do |record|
        puts "Processing #{klass} with ID #{record.id}"
        if record.send(attribute).present?
          encrypted_value, iv = encrypt(record.send(attribute))
          record.update!("encrypted_#{attribute}" => encrypted_value, "encrypted_#{attribute}_iv" => iv)
        end
      end

      remove_column klass.table_name, attribute
    end
  end

  # based on https://github.com/gorails-screencasts/migrate-attr_encrypted-to-rails-7-encryption/blob/master/db/migrate/20211005214633_migrate_encrypted_attributes.rb
  # as suggested by https://stackoverflow.com/questions/72096672/using-attr-encrypted-with-rails-7
  def decrypt(encrypted_value, iv)
    value = Base64.decode64(encrypted_value)

    cipher = OpenSSL::Cipher.new("aes-256-gcm")
    cipher.decrypt

    cipher.key = Rails.application.credentials.key
    cipher.iv = Base64.decode64(iv)

    cipher.auth_tag = value[-16..]
    cipher.auth_data = ""

    cipher.update(value[0..-17]) + cipher.final
  end

  def encrypt(value)
    cipher = OpenSSL::Cipher.new("aes-256-gcm")
    cipher.encrypt

    cipher.key = Rails.application.credentials.key
    iv = cipher.random_iv

    cipher.auth_data = ""

    encrypted_value = cipher.update(value) + cipher.final

    return Base64.encode64(encrypted_value + cipher.auth_tag), Base64.encode64(iv)
  end
end

Based on previous answer, a complete migration in both directions:

class SwitchToRailsBuiltInEncryption < ActiveRecord::Migration[7.0]

  ATTRIBUTES = [
    [Account, :password],
    [Account, :client_secret],
  ]

  def up
    ATTRIBUTES.each do |klass, attribute|
      klass.reset_column_information

      add_column klass.table_name, attribute, :string, length: 510

      klass.all.each do |record|
        puts "Processing #{klass} with ID #{record.id}"
        if record.send("encrypted_#{attribute}").present?
          encrypted_value = record.send("encrypted_#{attribute}")
          iv = record.send("encrypted_#{attribute}_iv")
          value = decrypt(encrypted_value, iv)
          record.update!(attribute => value)
        end
      end

      remove_column klass.table_name, "encrypted_#{attribute}"
      remove_column klass.table_name, "encrypted_#{attribute}_iv"
    end
  end

  def down
    ATTRIBUTES.each do |klass, attribute|
      add_column klass.table_name, "encrypted_#{attribute}", :string, length: 510
      add_column klass.table_name, "encrypted_#{attribute}_iv", :string, length: 510

      klass.all.each do |record|
        puts "Processing #{klass} with ID #{record.id}"
        if record.send(attribute).present?
          encrypted_value, iv = encrypt(record.send(attribute))
          record.update!("encrypted_#{attribute}" => encrypted_value, "encrypted_#{attribute}_iv" => iv)
        end
      end

      remove_column klass.table_name, attribute
    end
  end

  # based on https://github.com/gorails-screencasts/migrate-attr_encrypted-to-rails-7-encryption/blob/master/db/migrate/20211005214633_migrate_encrypted_attributes.rb
  # as suggested by https://stackoverflow.com/questions/72096672/using-attr-encrypted-with-rails-7
  def decrypt(encrypted_value, iv)
    value = Base64.decode64(encrypted_value)

    cipher = OpenSSL::Cipher.new("aes-256-gcm")
    cipher.decrypt

    cipher.key = Rails.application.credentials.key
    cipher.iv = Base64.decode64(iv)

    cipher.auth_tag = value[-16..]
    cipher.auth_data = ""

    cipher.update(value[0..-17]) + cipher.final
  end

  def encrypt(value)
    cipher = OpenSSL::Cipher.new("aes-256-gcm")
    cipher.encrypt

    cipher.key = Rails.application.credentials.key
    iv = cipher.random_iv

    cipher.auth_data = ""

    encrypted_value = cipher.update(value) + cipher.final

    return Base64.encode64(encrypted_value + cipher.auth_tag), Base64.encode64(iv)
  end
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文