-
Notifications
You must be signed in to change notification settings - Fork 21.9k
Description
ActiveRecord::Railtie
initialization fires before ActiveSupport::Railtie
In Rails::Application::Configuration#load_defaults(7.0)
it sets active_support.key_generator_hash_digest_class = OpenSSL::Digest::SHA256
Then in the ActiveSupport::Railtie
it sets ActiveSupport::KeyGenerator.hash_digest_class = active_support.key_generator_hash_digest_class
However, the ActiveRecord::Railtie
configures ActiveRecord::Encryption
before this configuration change happens.
What this causes is the ActiveRecord::Encryption::Configurable.configure
to set the context.key_provider = ActiveRecord::Encryption::DerivedSecretKeyProvider.new(primary_key)
, which uses the ActiveSupport::KeyGenerator
from ActiveRecord::Encryption::KeyGenerator#derive_key_from
method. At this point it uses the classes default hash_digest_class
of OpenSSL::Digest::SHA1
.
After ActiveSupport::Railtie
runs the ActiveSupport::KeyGenerator.hash_digest_class
changes to OpenSSL::Digest::SHA256
I am not sure what the best fix is and there may be others, but a couple I can think of are:
ActiveRecord::Encryption
is "explicit" about how it configures/uses theActiveSupport::KeyGenerator
and possibly adds additional options forhash_digest_class
anditerations
. This removes the dependency. It also allows the database to live past future changes to ActiveSupport defaults.ActiveSupport::KeyGenerator
changes it's class default to beOpenSSL::Digest::SHA256
and thenew_framework_defaults_7_0.rb
file sets it back toOpenSSL::Digest::SHA1
Steps to reproduce
- Create a new rails 7 project using all rails 7 defaults (removed
new_framework_defaults_7_0.rb
file andapplication.rb
changes toconfig.load_defaults 7.0
) - Configure Encryption by running
bin/rails db:encryption:init
and adding the generated credentials (bin/rails credentials:edit
)
Add this entry to the credentials of the target environment:
active_record_encryption:
primary_key: nYeEQD0EqOKXeRMFcUq7BX6goxGt0hPq
deterministic_key: aduCGCnZWFtRIN3xc8CiM15kZKt2Az8T
key_derivation_salt: fidtmePZxQNmR6Gc4Yv7j1lko06ISaBu
- Start a rails console (
bin/rails console
)
ActiveRecord::Encryption.key_provider.encryption_key.secret
primary_key = "nYeEQD0EqOKXeRMFcUq7BX6goxGt0hPq"
key_derivation_salt = "fidtmePZxQNmR6Gc4Yv7j1lko06ISaBu"
ActiveRecord::Encryption::DerivedSecretKeyProvider.new(primary_key).encryption_key.secret
OpenSSL::PKCS5.pbkdf2_hmac(primary_key, key_derivation_salt, 2**16, 32, OpenSSL::Digest::SHA1.new)
OpenSSL::PKCS5.pbkdf2_hmac(primary_key, key_derivation_salt, 2**16, 32, OpenSSL::Digest::SHA256.new)
Expected behavior
ActiveRecord::Encryption.key_provider.encryption_key.secret
\xE547G\xE7\x99?\x95\xAEX\xE1\xEFS\xE9p\x87}\x93\xF8\x8A\x9Ch\x80\x95#Bee\x95\nD\x7F
Actual behavior
ActiveRecord::Encryption.key_provider.encryption_key.secret
\x8B
\x17k\xA1\xC9:a\x05>N\x10\xE4\eYD\xCFUh\x10\x9Ep\x89\x10\x15vt\xE0\x94\xAAN
ActiveRecord::Encryption::DerivedSecretKeyProvider.new(primary_key).encryption_key.secret
\xE547G\xE7\x99?\x95\xAEX\xE1\xEFS\xE9p\x87}\x93\xF8\x8A\x9Ch\x80\x95#Bee\x95\nD\x7F
OpenSSL::PKCS5.pbkdf2_hmac(primary_key, key_derivation_salt, 2**16, 32, OpenSSL::Digest::SHA1.new)
\x8B
\x17k\xA1\xC9:a\x05>N\x10\xE4\eYD\xCFUh\x10\x9Ep\x89\x10\x15vt\xE0\x94\xAAN
OpenSSL::PKCS5.pbkdf2_hmac(primary_key, key_derivation_salt, 2**16, 32, OpenSSL::Digest::SHA256.new)
\xE547G\xE7\x99?\x95\xAEX\xE1\xEFS\xE9p\x87}\x93\xF8\x8A\x9Ch\x80\x95#Bee\x95\nD\x7F
System configuration
Rails version: 7.0
(gem 'rails', github: 'rails/rails', branch: 'main'
)
Ruby version: ruby 2.7.2p137