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 # frozen_string_literal: true
require "openssl"
module ActiveSupport module ActiveSupport
class Digest #:nodoc: class Digest #:nodoc:
class <<self class <<self
def hash_digest_class def hash_digest_class
@hash_digest_class ||= ::Digest::MD5 @hash_digest_class ||= OpenSSL::Digest::MD5
end end
def hash_digest_class=(klass) def hash_digest_class=(klass)

View File

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

View File

@ -6,17 +6,17 @@ require "openssl"
class DigestTest < ActiveSupport::TestCase class DigestTest < ActiveSupport::TestCase
class InvalidDigest; end class InvalidDigest; end
def test_with_default_hash_digest_class 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 end
def test_with_custom_hash_digest_class def test_with_custom_hash_digest_class
original_hash_digest_class = ActiveSupport::Digest.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") digest = ActiveSupport::Digest.hexdigest("hello friend")
assert_equal 32, digest.length 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 ensure
ActiveSupport::Digest.hash_digest_class = original_hash_digest_class ActiveSupport::Digest.hash_digest_class = original_hash_digest_class
end 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: #### For '6.2', defaults from previous versions below and:
- `config.active_support.key_generator_hash_digest_class`: `OpenSSL::Digest::SHA256` - `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: #### 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.active_record.cache_versioning`: `true`
- `config.action_dispatch.use_authenticated_cookie_encryption`: `true` - `config.action_dispatch.use_authenticated_cookie_encryption`: `true`
- `config.active_support.use_authenticated_message_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_controller.default_protect_from_forgery`: `true`
- `config.action_view.form_with_generates_ids`: `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.has_many_inversing`: `false`
- `config.active_record.legacy_connection_handling`: `true` - `config.active_record.legacy_connection_handling`: `true`
- `config.active_support.use_authenticated_message_encryption`: `false` - `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` - `config.active_support.key_generator_hash_digest_class`: `OpenSSL::Digest::SHA1`
- `ActiveSupport.utc_to_local_returns_utc_offset_times`: `false` - `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 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 Upgrading from Rails 6.0 to Rails 6.1
------------------------------------- -------------------------------------

View File

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

View File

@ -9,11 +9,17 @@
# button_to view helpers consistently render <button> elements. # button_to view helpers consistently render <button> elements.
# Rails.application.config.action_view.button_to_generates_button_tag = false # Rails.application.config.action_view.button_to_generates_button_tag = false
# Change the digest class for they key generators to `OpenSSL::Digest::SHA256`. # Change the digest class for the key generators to `OpenSSL::Digest::SHA256`.
# Changing this defaults means invalidate all encripted messages generated by # Changing this default means invalidate all encrypted messages generated by
# your application and, all the encrypted cookies. Only change this after you # 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. # See upgrading guide for more information on how to build a rotator.
# https://guides.rubyonrails.org/v7.0/upgrading_ruby_on_rails.html # https://guides.rubyonrails.org/v7.0/upgrading_ruby_on_rails.html
# Rails.application.config.active_support.key_generator_hash_digest_class = OpenSSL::Digest::SHA256 # 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 assert_equal true, ActiveSupport::MessageEncryptor.use_authenticated_message_encryption
end 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" app "development"
assert_equal Digest::SHA1, ActiveSupport::Digest.hash_digest_class assert_equal OpenSSL::Digest::SHA256, ActiveSupport::Digest.hash_digest_class
end 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' remove_from_config '.*config\.load_defaults.*\n'
app "development" app "development"
assert_equal Digest::MD5, ActiveSupport::Digest.hash_digest_class assert_equal OpenSSL::Digest::MD5, ActiveSupport::Digest.hash_digest_class
end end
test "ActiveSupport::Digest.hash_digest_class can be configured via config.active_support.use_sha1_digests" do 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" app "development"
assert_equal Digest::SHA1, ActiveSupport::Digest.hash_digest_class assert_equal OpenSSL::Digest::SHA1, ActiveSupport::Digest.hash_digest_class
end end
test "ActiveSupport::Digest.hash_digest_class can be configured via config.active_support.hash_digest_class" do test "ActiveSupport::Digest.hash_digest_class can be configured via config.active_support.hash_digest_class" do
remove_from_config '.*config\.load_defaults.*\n' remove_from_config '.*config\.load_defaults.*\n'
app_file "config/initializers/custom_digest_class.rb", <<-RUBY 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 RUBY
app "development" app "development"
assert_equal Digest::SHA256, ActiveSupport::Digest.hash_digest_class assert_equal OpenSSL::Digest::SHA256, ActiveSupport::Digest.hash_digest_class
end end
test "ActiveSupport::KeyGenerator.hash_digest_class is OpenSSL::Digest::SHA256 by default for new apps" do 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 assert_equal 200, last_response.status
values = ActionView::LookupContext::DetailsKey.digest_caches.first.values 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) assert_equal %w(david dingus), last_response.body.split.map(&:strip)
end end