Skip to content

Commit

Permalink
Change the default digest for new apps to SHA256
Browse files Browse the repository at this point in the history
As mentioned in
#40770 (comment) 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.
  • Loading branch information
dbussink committed Jan 8, 2021
1 parent b5b4bda commit ba9207f
Show file tree
Hide file tree
Showing 9 changed files with 37 additions and 20 deletions.
4 changes: 3 additions & 1 deletion activesupport/lib/active_support/digest.rb
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
4 changes: 2 additions & 2 deletions activesupport/lib/active_support/railtie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ class Railtie < Rails::Railtie # :nodoc:
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
Expand Down
6 changes: 3 additions & 3 deletions activesupport/test/digest_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@
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
Expand Down
5 changes: 3 additions & 2 deletions guides/source/configuring.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down Expand Up @@ -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`

Expand Down Expand Up @@ -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`

Expand Down
7 changes: 7 additions & 0 deletions guides/source/upgrading_ruby_on_rails.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
-------------------------------------

Expand Down
3 changes: 2 additions & 1 deletion railties/lib/rails/application/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def load_defaults(target_version)

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)
Expand Down Expand Up @@ -209,6 +209,7 @@ def load_defaults(target_version)
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
14 changes: 7 additions & 7 deletions railties/test/application/configuration_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2257,18 +2257,18 @@ class D < C
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
Expand All @@ -2280,19 +2280,19 @@ class D < C

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
Expand Down
2 changes: 1 addition & 1 deletion railties/test/application/per_request_digest_cache_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def index
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

Expand Down

0 comments on commit ba9207f

Please sign in to comment.