Change the default digest for new apps to SHA256

As mentioned in
https://github.com/rails/rails/pull/40770#issuecomment-748347066 we
should default to SHA256 where SHA1 is used today. This switches over
the ActiveSupport::Digest to use SHA256 for new applications.

It also updates the constants to always refer to and use the OpenSSL
constants as well, as also discussed in that PR.
This commit is contained in:
Dirkjan Bussink 2021-01-07 16:54:57 +01:00
parent b5b4bdaeac
commit ba9207f301
No known key found for this signature in database
GPG Key ID: F1573D8E835753FD
9 changed files with 37 additions and 20 deletions

View File

@ -1,10 +1,12 @@
# frozen_string_literal: true
require "openssl"
module ActiveSupport
class Digest #:nodoc:
class <<self
def hash_digest_class
@hash_digest_class ||= ::Digest::MD5
@hash_digest_class ||= OpenSSL::Digest::MD5
end
def hash_digest_class=(klass)

View File

@ -88,9 +88,9 @@ module ActiveSupport
ActiveSupport::Deprecation.warn(<<-MSG.squish)
config.active_support.use_sha1_digests is deprecated and will
be removed from Rails 6.2. Use
config.active_support.hash_digest_class = ::Digest::SHA1 instead.
config.active_support.hash_digest_class = OpenSSL::Digest::SHA1 instead.
MSG
ActiveSupport::Digest.hash_digest_class = ::Digest::SHA1
ActiveSupport::Digest.hash_digest_class = OpenSSL::Digest::SHA1
end
if klass = app.config.active_support.hash_digest_class

View File

@ -6,17 +6,17 @@ require "openssl"
class DigestTest < ActiveSupport::TestCase
class InvalidDigest; end
def test_with_default_hash_digest_class
assert_equal ::Digest::MD5.hexdigest("hello friend"), ActiveSupport::Digest.hexdigest("hello friend")
assert_equal OpenSSL::Digest::MD5.hexdigest("hello friend"), ActiveSupport::Digest.hexdigest("hello friend")
end
def test_with_custom_hash_digest_class
original_hash_digest_class = ActiveSupport::Digest.hash_digest_class
ActiveSupport::Digest.hash_digest_class = ::Digest::SHA1
ActiveSupport::Digest.hash_digest_class = OpenSSL::Digest::SHA1
digest = ActiveSupport::Digest.hexdigest("hello friend")
assert_equal 32, digest.length
assert_equal ::Digest::SHA1.hexdigest("hello friend")[0...32], digest
assert_equal OpenSSL::Digest::SHA1.hexdigest("hello friend")[0...32], digest
ensure
ActiveSupport::Digest.hash_digest_class = original_hash_digest_class
end

View File

@ -1041,6 +1041,7 @@ text/javascript image/svg+xml application/postscript application/x-shockwave-fla
#### For '6.2', defaults from previous versions below and:
- `config.active_support.key_generator_hash_digest_class`: `OpenSSL::Digest::SHA256`
- `config.active_support.hash_digest_class`: `OpenSSL::Digest::SHA256`
#### For '6.1', defaults from previous versions below and:
@ -1076,7 +1077,7 @@ text/javascript image/svg+xml application/postscript application/x-shockwave-fla
- `config.active_record.cache_versioning`: `true`
- `config.action_dispatch.use_authenticated_cookie_encryption`: `true`
- `config.active_support.use_authenticated_message_encryption`: `true`
- `config.active_support.hash_digest_class`: `::Digest::SHA1`
- `config.active_support.hash_digest_class`: `OpenSSL::Digest::SHA1`
- `config.action_controller.default_protect_from_forgery`: `true`
- `config.action_view.form_with_generates_ids`: `true`
@ -1110,7 +1111,7 @@ text/javascript image/svg+xml application/postscript application/x-shockwave-fla
- `config.active_record.has_many_inversing`: `false`
- `config.active_record.legacy_connection_handling`: `true`
- `config.active_support.use_authenticated_message_encryption`: `false`
- `config.active_support.hash_digest_class`: `::Digest::MD5`
- `config.active_support.hash_digest_class`: `OpenSSL::Digest::MD5`
- `config.active_support.key_generator_hash_digest_class`: `OpenSSL::Digest::SHA1`
- `ActiveSupport.utc_to_local_returns_utc_offset_times`: `false`

View File

@ -101,6 +101,13 @@ Rails.application.config.action_dispatch.cookies_rotations.tap do |cookies|
end
```
### Digest class for ActiveSupport::Digest changing to SHA256
The default digest class for ActiveSupport::Digest is changing from SHA1 to SHA256.
This has consequences for things like Etags that will change and cache keys as well.
Changing these keys can have impact on cache hit rates, so be careful and watch out
for this when upgrading to the new hash.
Upgrading from Rails 6.0 to Rails 6.1
-------------------------------------

View File

@ -116,7 +116,7 @@ module Rails
if respond_to?(:active_support)
active_support.use_authenticated_message_encryption = true
active_support.hash_digest_class = ::Digest::SHA1
active_support.hash_digest_class = OpenSSL::Digest::SHA1
end
if respond_to?(:action_controller)
@ -209,6 +209,7 @@ module Rails
end
if respond_to?(:active_support)
active_support.hash_digest_class = OpenSSL::Digest::SHA256
active_support.key_generator_hash_digest_class = OpenSSL::Digest::SHA256
end
else

View File

@ -9,11 +9,17 @@
# button_to view helpers consistently render <button> elements.
# Rails.application.config.action_view.button_to_generates_button_tag = false
# Change the digest class for they key generators to `OpenSSL::Digest::SHA256`.
# Changing this defaults means invalidate all encripted messages generated by
# Change the digest class for the key generators to `OpenSSL::Digest::SHA256`.
# Changing this default means invalidate all encrypted messages generated by
# your application and, all the encrypted cookies. Only change this after you
# rotated all the messages using they key rotator.
# rotated all the messages using the key rotator.
#
# See upgrading guide for more information on how to build a rotator.
# https://guides.rubyonrails.org/v7.0/upgrading_ruby_on_rails.html
# Rails.application.config.active_support.key_generator_hash_digest_class = OpenSSL::Digest::SHA256
# Change the digest class for ActiveSupport::Digest.
# Changing this default means that for example Etags change and
# various cache keys leading to cache invalidation.
#
# Rails.application.config.active_support.hash_digest_class = OpenSSL::Digest::SHA256

View File

@ -2257,18 +2257,18 @@ module ApplicationTests
assert_equal true, ActiveSupport::MessageEncryptor.use_authenticated_message_encryption
end
test "ActiveSupport::Digest.hash_digest_class is Digest::SHA1 by default for new apps" do
test "ActiveSupport::Digest.hash_digest_class is OpenSSL::Digest::SHA256 by default for new apps" do
app "development"
assert_equal Digest::SHA1, ActiveSupport::Digest.hash_digest_class
assert_equal OpenSSL::Digest::SHA256, ActiveSupport::Digest.hash_digest_class
end
test "ActiveSupport::Digest.hash_digest_class is Digest::MD5 by default for upgraded apps" do
test "ActiveSupport::Digest.hash_digest_class is OpenSSL::Digest::MD5 by default for upgraded apps" do
remove_from_config '.*config\.load_defaults.*\n'
app "development"
assert_equal Digest::MD5, ActiveSupport::Digest.hash_digest_class
assert_equal OpenSSL::Digest::MD5, ActiveSupport::Digest.hash_digest_class
end
test "ActiveSupport::Digest.hash_digest_class can be configured via config.active_support.use_sha1_digests" do
@ -2280,19 +2280,19 @@ module ApplicationTests
app "development"
assert_equal Digest::SHA1, ActiveSupport::Digest.hash_digest_class
assert_equal OpenSSL::Digest::SHA1, ActiveSupport::Digest.hash_digest_class
end
test "ActiveSupport::Digest.hash_digest_class can be configured via config.active_support.hash_digest_class" do
remove_from_config '.*config\.load_defaults.*\n'
app_file "config/initializers/custom_digest_class.rb", <<-RUBY
Rails.application.config.active_support.hash_digest_class = Digest::SHA256
Rails.application.config.active_support.hash_digest_class = OpenSSL::Digest::SHA256
RUBY
app "development"
assert_equal Digest::SHA256, ActiveSupport::Digest.hash_digest_class
assert_equal OpenSSL::Digest::SHA256, ActiveSupport::Digest.hash_digest_class
end
test "ActiveSupport::KeyGenerator.hash_digest_class is OpenSSL::Digest::SHA256 by default for new apps" do

View File

@ -57,7 +57,7 @@ class PerRequestDigestCacheTest < ActiveSupport::TestCase
assert_equal 200, last_response.status
values = ActionView::LookupContext::DetailsKey.digest_caches.first.values
assert_equal [ "effc8928d0b33535c8a21d24ec617161" ], values
assert_equal [ "ddb451d2c1b2374caa676005893bb776" ], values
assert_equal %w(david dingus), last_response.body.split.map(&:strip)
end