Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong attributes are stored for encrypted attributes #1431

Closed
3 tasks done
ghiculescu opened this issue Jul 17, 2023 · 6 comments
Closed
3 tasks done

Wrong attributes are stored for encrypted attributes #1431

ghiculescu opened this issue Jul 17, 2023 · 6 comments
Labels

Comments

@ghiculescu
Copy link
Contributor

If you have an encrypted attribute, and use object_changes, the changes stored don't match the attribute on the record.

I would expect this test to pass:

# frozen_string_literal: true

require "bundler/inline"

gemfile(true) do
  source "https://rubygems.org"

  git_source(:github) { |repo| "https://github.com/#{repo}.git" }

  gem "rails", github: "rails/rails", branch: "main"
  gem "sqlite3"
  gem "paper_trail", "14.0.0", require: false
  gem "debug"
end

require "active_record"
require "paper_trail"
require "paper_trail/frameworks/active_record"
require "minitest/autorun"
require "logger"

# This connection will do for database-independent bug reports.
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Encryption.configure(primary_key: "123", deterministic_key: "456", key_derivation_salt: "789")

ActiveRecord::Schema.define do
  create_table :posts, force: true do |t|
    t.text :name
  end

  create_table :versions do |t|
    t.string :item_type, null: false
    t.integer :item_id, null: false
    t.string :event, null: false
    t.string :whodunnit
    t.text :object, limit: 1_073_741_823
    t.text :object_changes, limit: 1_073_741_823
    t.datetime :created_at
  end
  add_index :versions, %i[item_type item_id]
end

class Post < ActiveRecord::Base
  encrypts :name
  has_paper_trail
end

class BugTest < Minitest::Test
  def test_bug
    post = Post.create!(name: "hi")
    assert_equal post.attributes_before_type_cast["name"], YAML.load(post.versions.first.object_changes)["name"].last
  end
end

But it fails:

Failure:
BugTest#test_bug [test.rb:53]:
--- expected
+++ actual
@@ -1 +1 @@
-"{\"p\":\"990=\",\"h\":{\"iv\":\"mzbu9T9UjQBSAOc+\",\"at\":\"X5y63TyZO96bnrqePCTijQ==\"}}"
+"{\"p\":\"F8U=\",\"h\":{\"iv\":\"NPtd3Io5+mLcv/CE\",\"at\":\"Rq/keM9l6i7zepK2zb1FwQ==\"}}"
  • This is not a usage question, this is a bug report
  • This bug can be reproduced with the script I provide below
  • This bug can be reproduced in the latest release of the paper_trail gem
@ghiculescu
Copy link
Contributor Author

I think the root cause is roughly here.

The type here is a ActiveRecord::Encryption::EncryptedAttributeType, and this returns a different result each time it's called with the same input:

(ruby) Post.type_for_attribute(:name).serialize('asdf')
"{\"p\":\"RLLLSA==\",\"h\":{\"iv\":\"H7c94XC/8rKT9jN/\",\"at\":\"QJmzn+d6IJ+4lnGRpOM3Ug==\"}}"
(ruby) Post.type_for_attribute(:name).serialize('asdf')
"{\"p\":\"ngsW0A==\",\"h\":{\"iv\":\"yeLWQvJucVR+LVcQ\",\"at\":\"yFddZTzXzefl+VzR1sCh+w==\"}}"
(ruby) Post.type_for_attribute(:name).serialize('asdf')
"{\"p\":\"M2O6tQ==\",\"h\":{\"iv\":\"TUz7TkOsgUN9XjoL\",\"at\":\"8zhIkMB3f0dHG2ea8qBWXw==\"}}"

Assuming this is intentional (I think it is, but not certain), then Paper Trail should not re-run the serialization since it returns a new value. We could skip re-serializing using a mechanism similar to TypeSerializers::PostgresArraySerializer.


@jorgemanrubia sorry to tag you on a gem that you have nothing to do with, but I was hoping you could just confirm if it's intended that EncryptedAttributeType#serialize returns a different output each time it's called.

@jorgemanrubia
Copy link

@ghiculescu yes, that's expected. When using the default "non deterministic" encryption, each time you encrypt a value it generates a random initialization vector, so the encrypted payload will be different, even if the cleartext is the same.

@github-actions
Copy link

This issue has been automatically marked as stale due to inactivity.
The resources of our volunteers are limited.
Bug reports must provide a script that reproduces the bug, using our template. Feature suggestions must include a promise to build the feature yourself.
Thank you for all your contributions.

@github-actions github-actions bot added the Stale label Oct 16, 2023
@ghiculescu
Copy link
Contributor Author

Okay. I think this is a bug then.

@ghiculescu
Copy link
Contributor Author

I can make a PR if that’s confirmed ^

@github-actions github-actions bot removed the Stale label Oct 17, 2023
Copy link

This issue has been automatically marked as stale due to inactivity.
The resources of our volunteers are limited.
Bug reports must provide a script that reproduces the bug, using our template. Feature suggestions must include a promise to build the feature yourself.
Thank you for all your contributions.

@github-actions github-actions bot added the Stale label Jan 15, 2024
@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Jan 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants