From 0523532a3ce41ec9d7de998824987c57c4c2b016 Mon Sep 17 00:00:00 2001 From: Dirkjan Bussink Date: Mon, 22 Mar 2021 10:25:49 +0100 Subject: [PATCH] Always use OpenSSL constants for Digest operations As also previously discussed in https://github.com/rails/rails/pull/40770#issuecomment-748347066, this moves the usage of Digest constants to always use the OpenSSL version of those Digest implementations. --- actioncable/CHANGELOG.md | 4 ++++ .../subscription_adapter/postgresql.rb | 4 ++-- actionmailbox/CHANGELOG.md | 3 +++ .../action_mailbox/inbound_email/message_id.rb | 2 +- actionpack/CHANGELOG.md | 4 ++++ .../metal/http_authentication.rb | 14 +++++++------- .../http_digest_authentication_test.rb | 4 ++-- actiontext/CHANGELOG.md | 4 ++++ .../lib/action_text/attachments/caching.rb | 2 +- actionview/CHANGELOG.md | 4 ++++ .../lib/action_view/helpers/asset_url_helper.rb | 2 +- activejob/CHANGELOG.md | 4 ++++ .../support/integration/adapters/sneakers.rb | 2 +- activerecord/CHANGELOG.md | 6 ++++++ .../abstract/schema_statements.rb | 6 +++--- .../lib/active_record/tasks/database_tasks.rb | 2 +- activestorage/CHANGELOG.md | 4 ++++ activestorage/app/models/active_storage/blob.rb | 2 +- .../app/models/active_storage/variant.rb | 2 +- .../app/models/active_storage/variation.rb | 2 +- activestorage/lib/active_storage/downloader.rb | 2 +- .../lib/active_storage/service/disk_service.rb | 4 ++-- .../direct_uploads_controller_test.rb | 10 +++++----- .../test/controllers/disk_controller_test.rb | 10 +++++----- activestorage/test/models/blob_test.rb | 4 ++-- .../service/azure_storage_public_service_test.rb | 2 +- .../test/service/azure_storage_service_test.rb | 8 ++++---- .../test/service/gcs_public_service_test.rb | 2 +- activestorage/test/service/gcs_service_test.rb | 10 +++++----- .../test/service/mirror_service_test.rb | 6 +++--- .../test/service/s3_public_service_test.rb | 2 +- activestorage/test/service/s3_service_test.rb | 16 ++++++++-------- .../test/service/shared_service_tests.rb | 6 +++--- activestorage/test/test_helper.rb | 2 +- activesupport/CHANGELOG.md | 4 ++++ .../lib/active_support/core_ext/digest/uuid.rb | 16 ++++++++-------- activesupport/test/core_ext/digest/uuid_test.rb | 2 +- 37 files changed, 110 insertions(+), 73 deletions(-) diff --git a/actioncable/CHANGELOG.md b/actioncable/CHANGELOG.md index e33ec06d0a..7607bf0e59 100644 --- a/actioncable/CHANGELOG.md +++ b/actioncable/CHANGELOG.md @@ -1,3 +1,7 @@ +* OpenSSL constants are now used for Digest computations. + + *Dirkjan Bussink* + * The Action Cable client now includes safeguards to prevent a "thundering herd" of client reconnects after server connectivity loss: diff --git a/actioncable/lib/action_cable/subscription_adapter/postgresql.rb b/actioncable/lib/action_cable/subscription_adapter/postgresql.rb index 3b114d4e54..563a2aa3c9 100644 --- a/actioncable/lib/action_cable/subscription_adapter/postgresql.rb +++ b/actioncable/lib/action_cable/subscription_adapter/postgresql.rb @@ -3,7 +3,7 @@ gem "pg", "~> 1.1" require "pg" require "thread" -require "digest/sha1" +require "openssl" module ActionCable module SubscriptionAdapter @@ -58,7 +58,7 @@ module ActionCable private def channel_identifier(channel) - channel.size > 63 ? Digest::SHA1.hexdigest(channel) : channel + channel.size > 63 ? OpenSSL::Digest::SHA1.hexdigest(channel) : channel end def listener diff --git a/actionmailbox/CHANGELOG.md b/actionmailbox/CHANGELOG.md index a56d85338b..a5d6ae7524 100644 --- a/actionmailbox/CHANGELOG.md +++ b/actionmailbox/CHANGELOG.md @@ -2,5 +2,8 @@ *Santiago Bartesaghi* +* OpenSSL constants are now used for Digest computations. + + *Dirkjan Bussink* Please check [6-1-stable](https://github.com/rails/rails/blob/6-1-stable/actionmailbox/CHANGELOG.md) for previous changes. diff --git a/actionmailbox/app/models/action_mailbox/inbound_email/message_id.rb b/actionmailbox/app/models/action_mailbox/inbound_email/message_id.rb index d8f52c8dbf..c4ef35f415 100644 --- a/actionmailbox/app/models/action_mailbox/inbound_email/message_id.rb +++ b/actionmailbox/app/models/action_mailbox/inbound_email/message_id.rb @@ -14,7 +14,7 @@ module ActionMailbox::InboundEmail::MessageId # attachment called +raw_email+. Before the upload, extract the Message-ID from the +source+ and set # it as an attribute on the new +InboundEmail+. def create_and_extract_message_id!(source, **options) - message_checksum = Digest::SHA1.hexdigest(source) + message_checksum = OpenSSL::Digest::SHA1.hexdigest(source) message_id = extract_message_id(source) || generate_missing_message_id(message_checksum) create! raw_email: create_and_upload_raw_email!(source), diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 7498111d79..795f8164c2 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,7 @@ +* OpenSSL constants are now used for Digest computations. + + *Dirkjan Bussink* + * Remove IE6-7-8 file download related hack/fix from ActionController::DataStreaming module Due to the age of those versions of IE this fix is no longer relevant, more importantly it creates an edge-case for unexpected Cache-Control headers. diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb index 76e9b44050..9db231f5af 100644 --- a/actionpack/lib/action_controller/metal/http_authentication.rb +++ b/actionpack/lib/action_controller/metal/http_authentication.rb @@ -138,11 +138,11 @@ module ActionController # # === Simple \Digest example # - # require "digest/md5" + # require "openssl" # class PostsController < ApplicationController # REALM = "SuperSecret" # USERS = {"dhh" => "secret", #plain text password - # "dap" => Digest::MD5.hexdigest(["dap",REALM,"secret"].join(":"))} #ha1 digest password + # "dap" => OpenSSL::Digest::MD5.hexdigest(["dap",REALM,"secret"].join(":"))} #ha1 digest password # # before_action :authenticate, except: [:index] # @@ -230,12 +230,12 @@ module ActionController # of a plain-text password. def expected_response(http_method, uri, credentials, password, password_is_ha1 = true) ha1 = password_is_ha1 ? password : ha1(credentials, password) - ha2 = ::Digest::MD5.hexdigest([http_method.to_s.upcase, uri].join(":")) - ::Digest::MD5.hexdigest([ha1, credentials[:nonce], credentials[:nc], credentials[:cnonce], credentials[:qop], ha2].join(":")) + ha2 = OpenSSL::Digest::MD5.hexdigest([http_method.to_s.upcase, uri].join(":")) + OpenSSL::Digest::MD5.hexdigest([ha1, credentials[:nonce], credentials[:nc], credentials[:cnonce], credentials[:qop], ha2].join(":")) end def ha1(credentials, password) - ::Digest::MD5.hexdigest([credentials[:username], credentials[:realm], password].join(":")) + OpenSSL::Digest::MD5.hexdigest([credentials[:username], credentials[:realm], password].join(":")) end def encode_credentials(http_method, credentials, password, password_is_ha1) @@ -309,7 +309,7 @@ module ActionController def nonce(secret_key, time = Time.now) t = time.to_i hashed = [t, secret_key] - digest = ::Digest::MD5.hexdigest(hashed.join(":")) + digest = OpenSSL::Digest::MD5.hexdigest(hashed.join(":")) ::Base64.strict_encode64("#{t}:#{digest}") end @@ -326,7 +326,7 @@ module ActionController # Opaque based on digest of secret key def opaque(secret_key) - ::Digest::MD5.hexdigest(secret_key) + OpenSSL::Digest::MD5.hexdigest(secret_key) end end diff --git a/actionpack/test/controller/http_digest_authentication_test.rb b/actionpack/test/controller/http_digest_authentication_test.rb index a0f543f607..c68bf62b7e 100644 --- a/actionpack/test/controller/http_digest_authentication_test.rb +++ b/actionpack/test/controller/http_digest_authentication_test.rb @@ -9,7 +9,7 @@ class HttpDigestAuthenticationTest < ActionController::TestCase before_action :authenticate_with_request, only: :display USERS = { "lifo" => "world", "pretty" => "please", - "dhh" => ::Digest::MD5.hexdigest(["dhh", "SuperSecret", "secret"].join(":")) } + "dhh" => OpenSSL::Digest::MD5.hexdigest(["dhh", "SuperSecret", "secret"].join(":")) } def index render plain: "Hello Secret" @@ -185,7 +185,7 @@ class HttpDigestAuthenticationTest < ActionController::TestCase test "authentication request with password stored as ha1 digest hash" do @request.env["HTTP_AUTHORIZATION"] = encode_credentials( username: "dhh", - password: ::Digest::MD5.hexdigest(["dhh", "SuperSecret", "secret"].join(":")), + password: OpenSSL::Digest::MD5.hexdigest(["dhh", "SuperSecret", "secret"].join(":")), password_is_ha1: true) get :display diff --git a/actiontext/CHANGELOG.md b/actiontext/CHANGELOG.md index a8addcdf9f..877eb9c139 100644 --- a/actiontext/CHANGELOG.md +++ b/actiontext/CHANGELOG.md @@ -1,3 +1,7 @@ +* OpenSSL constants are now used for Digest computations. + + *Dirkjan Bussink* + * Add support for passing `form:` option to `rich_text_area_tag` and `rich_text_area` helpers to specify the `` value. diff --git a/actiontext/lib/action_text/attachments/caching.rb b/actiontext/lib/action_text/attachments/caching.rb index 7c727bfc26..18e48d2a9d 100644 --- a/actiontext/lib/action_text/attachments/caching.rb +++ b/actiontext/lib/action_text/attachments/caching.rb @@ -9,7 +9,7 @@ module ActionText private def cache_digest - Digest::SHA256.hexdigest(node.to_s) + OpenSSL::Digest::SHA256.hexdigest(node.to_s) end end end diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index df249958e9..dc8fc1d834 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -1,3 +1,7 @@ +* OpenSSL constants are now used for Digest computations. + + *Dirkjan Bussink* + * The `translate` helper now passes `default` values that aren't translation keys through `I18n.translate` for interpolation. diff --git a/actionview/lib/action_view/helpers/asset_url_helper.rb b/actionview/lib/action_view/helpers/asset_url_helper.rb index 9c5515e559..ed18f54c9d 100644 --- a/actionview/lib/action_view/helpers/asset_url_helper.rb +++ b/actionview/lib/action_view/helpers/asset_url_helper.rb @@ -65,7 +65,7 @@ module ActionView # +asset_host+ to a proc like this: # # ActionController::Base.asset_host = Proc.new { |source| - # "http://assets#{Digest::MD5.hexdigest(source).to_i(16) % 2 + 1}.example.com" + # "http://assets#{OpenSSL::Digest::SHA256.hexdigest(source).to_i(16) % 2 + 1}.example.com" # } # image_tag("rails.png") # # => diff --git a/activejob/CHANGELOG.md b/activejob/CHANGELOG.md index 566186e99e..f42063bce8 100644 --- a/activejob/CHANGELOG.md +++ b/activejob/CHANGELOG.md @@ -1,3 +1,7 @@ +* OpenSSL constants are now used for Digest computations. + + *Dirkjan Bussink* + * Add a Serializer for the Range class This should allow things like `MyJob.perform_later(range: 1..100)` diff --git a/activejob/test/support/integration/adapters/sneakers.rb b/activejob/test/support/integration/adapters/sneakers.rb index 89dc61ca28..60ed141cde 100644 --- a/activejob/test/support/integration/adapters/sneakers.rb +++ b/activejob/test/support/integration/adapters/sneakers.rb @@ -31,7 +31,7 @@ module SneakersJobsManager @pid = fork do queues = %w(integration_tests) workers = queues.map do |q| - worker_klass = "ActiveJobWorker" + Digest::MD5.hexdigest(q) + worker_klass = "ActiveJobWorker" + OpenSSL::Digest::MD5.hexdigest(q) Sneakers.const_set(worker_klass, Class.new(ActiveJob::QueueAdapters::SneakersAdapter::JobWrapper) do from_queue q end) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 837313efe1..0c373c11c2 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,5 +1,11 @@ +* OpenSSL constants are now used for Digest computations. + + *Dirkjan Bussink* + * Relation#destroy_all perform its work in batches +* Prevent double saves in autosave of cyclic associations + Since destroy_all actually loads the entire relation and then iteratively destroys the records one by one, you can blow your memory gasket very easily. So let's do the right thing by default and do this work in batches of 100 by default and allow you to specify diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb index f6a0085206..a1913b9a91 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require "active_support/core_ext/string/access" -require "digest/sha2" +require "openssl" module ActiveRecord module ConnectionAdapters # :nodoc: @@ -1532,7 +1532,7 @@ module ActiveRecord def foreign_key_name(table_name, options) options.fetch(:name) do identifier = "#{table_name}_#{options.fetch(:column)}_fk" - hashed_identifier = Digest::SHA256.hexdigest(identifier).first(10) + hashed_identifier = OpenSSL::Digest::SHA256.hexdigest(identifier).first(10) "fk_rails_#{hashed_identifier}" end @@ -1560,7 +1560,7 @@ module ActiveRecord options.fetch(:name) do expression = options.fetch(:expression) identifier = "#{table_name}_#{expression}_chk" - hashed_identifier = Digest::SHA256.hexdigest(identifier).first(10) + hashed_identifier = OpenSSL::Digest::SHA256.hexdigest(identifier).first(10) "chk_rails_#{hashed_identifier}" end diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb index 068d11079e..9136b489cd 100644 --- a/activerecord/lib/active_record/tasks/database_tasks.rb +++ b/activerecord/lib/active_record/tasks/database_tasks.rb @@ -592,7 +592,7 @@ module ActiveRecord end def schema_sha1(file) - Digest::SHA1.hexdigest(File.read(file)) + OpenSSL::Digest::SHA1.hexdigest(File.read(file)) end def structure_dump_flags_for(adapter) diff --git a/activestorage/CHANGELOG.md b/activestorage/CHANGELOG.md index c1e9144032..6ccd9064a7 100644 --- a/activestorage/CHANGELOG.md +++ b/activestorage/CHANGELOG.md @@ -1,3 +1,7 @@ +* OpenSSL constants are now used for Digest computations. + + *Dirkjan Bussink* + * Deprecate `config.active_storage.replace_on_assign_to_many`. Future versions of Rails will behave the same way as when the config is set to `true`. diff --git a/activestorage/app/models/active_storage/blob.rb b/activestorage/app/models/active_storage/blob.rb index 0edd05ec4c..f337478e2e 100644 --- a/activestorage/app/models/active_storage/blob.rb +++ b/activestorage/app/models/active_storage/blob.rb @@ -305,7 +305,7 @@ class ActiveStorage::Blob < ActiveStorage::Record private def compute_checksum_in_chunks(io) - Digest::MD5.new.tap do |checksum| + OpenSSL::Digest::MD5.new.tap do |checksum| while chunk = io.read(5.megabytes) checksum << chunk end diff --git a/activestorage/app/models/active_storage/variant.rb b/activestorage/app/models/active_storage/variant.rb index 44b29f03fb..53a940f194 100644 --- a/activestorage/app/models/active_storage/variant.rb +++ b/activestorage/app/models/active_storage/variant.rb @@ -67,7 +67,7 @@ class ActiveStorage::Variant # Returns a combination key of the blob and the variation that together identifies a specific variant. def key - "variants/#{blob.key}/#{Digest::SHA256.hexdigest(variation.key)}" + "variants/#{blob.key}/#{OpenSSL::Digest::SHA256.hexdigest(variation.key)}" end # Returns the URL of the blob variant on the service. See {ActiveStorage::Blob#url} for details. diff --git a/activestorage/app/models/active_storage/variation.rb b/activestorage/app/models/active_storage/variation.rb index 70979b613e..c39550bbaa 100644 --- a/activestorage/app/models/active_storage/variation.rb +++ b/activestorage/app/models/active_storage/variation.rb @@ -75,7 +75,7 @@ class ActiveStorage::Variation end def digest - Digest::SHA1.base64digest Marshal.dump(transformations) + OpenSSL::Digest::SHA1.base64digest Marshal.dump(transformations) end private diff --git a/activestorage/lib/active_storage/downloader.rb b/activestorage/lib/active_storage/downloader.rb index 4d7e832af5..25866e8c7f 100644 --- a/activestorage/lib/active_storage/downloader.rb +++ b/activestorage/lib/active_storage/downloader.rb @@ -35,7 +35,7 @@ module ActiveStorage end def verify_integrity_of(file, checksum:) - unless Digest::MD5.file(file).base64digest == checksum + unless OpenSSL::Digest::MD5.file(file).base64digest == checksum raise ActiveStorage::IntegrityError end end diff --git a/activestorage/lib/active_storage/service/disk_service.rb b/activestorage/lib/active_storage/service/disk_service.rb index 147cfa3ed5..e17f8e87d2 100644 --- a/activestorage/lib/active_storage/service/disk_service.rb +++ b/activestorage/lib/active_storage/service/disk_service.rb @@ -2,7 +2,7 @@ require "fileutils" require "pathname" -require "digest/md5" +require "openssl" require "active_support/core_ext/numeric/bytes" module ActiveStorage @@ -158,7 +158,7 @@ module ActiveStorage end def ensure_integrity_of(key, checksum) - unless Digest::MD5.file(path_for(key)).base64digest == checksum + unless OpenSSL::Digest::MD5.file(path_for(key)).base64digest == checksum delete key raise ActiveStorage::IntegrityError end diff --git a/activestorage/test/controllers/direct_uploads_controller_test.rb b/activestorage/test/controllers/direct_uploads_controller_test.rb index 27e89a7f1c..8c49121584 100644 --- a/activestorage/test/controllers/direct_uploads_controller_test.rb +++ b/activestorage/test/controllers/direct_uploads_controller_test.rb @@ -15,7 +15,7 @@ if SERVICE_CONFIGURATIONS[:s3] && SERVICE_CONFIGURATIONS[:s3][:access_key_id].pr end test "creating new direct upload" do - checksum = Digest::MD5.base64digest("Hello") + checksum = OpenSSL::Digest::MD5.base64digest("Hello") metadata = { "foo": "bar", "my_key_1": "my_value_1", @@ -58,7 +58,7 @@ if SERVICE_CONFIGURATIONS[:gcs] end test "creating new direct upload" do - checksum = Digest::MD5.base64digest("Hello") + checksum = OpenSSL::Digest::MD5.base64digest("Hello") metadata = { "foo": "bar", "my_key_1": "my_value_1", @@ -100,7 +100,7 @@ if SERVICE_CONFIGURATIONS[:azure] end test "creating new direct upload" do - checksum = Digest::MD5.base64digest("Hello") + checksum = OpenSSL::Digest::MD5.base64digest("Hello") metadata = { "foo": "bar", "my_key_1": "my_value_1", @@ -130,7 +130,7 @@ end class ActiveStorage::DiskDirectUploadsControllerTest < ActionDispatch::IntegrationTest test "creating new direct upload" do - checksum = Digest::MD5.base64digest("Hello") + checksum = OpenSSL::Digest::MD5.base64digest("Hello") metadata = { "foo": "bar", "my_key_1": "my_value_1", @@ -155,7 +155,7 @@ class ActiveStorage::DiskDirectUploadsControllerTest < ActionDispatch::Integrati end test "creating new direct upload does not include root in json" do - checksum = Digest::MD5.base64digest("Hello") + checksum = OpenSSL::Digest::MD5.base64digest("Hello") metadata = { "foo": "bar", "my_key_1": "my_value_1", diff --git a/activestorage/test/controllers/disk_controller_test.rb b/activestorage/test/controllers/disk_controller_test.rb index 0183855ed3..98e2d687fc 100644 --- a/activestorage/test/controllers/disk_controller_test.rb +++ b/activestorage/test/controllers/disk_controller_test.rb @@ -67,7 +67,7 @@ class ActiveStorage::DiskControllerTest < ActionDispatch::IntegrationTest test "directly uploading blob with integrity" do data = "Something else entirely!" - blob = create_blob_before_direct_upload byte_size: data.size, checksum: Digest::MD5.base64digest(data) + blob = create_blob_before_direct_upload byte_size: data.size, checksum: OpenSSL::Digest::MD5.base64digest(data) put blob.service_url_for_direct_upload, params: data, headers: { "Content-Type" => "text/plain" } assert_response :no_content @@ -76,7 +76,7 @@ class ActiveStorage::DiskControllerTest < ActionDispatch::IntegrationTest test "directly uploading blob without integrity" do data = "Something else entirely!" - blob = create_blob_before_direct_upload byte_size: data.size, checksum: Digest::MD5.base64digest("bad data") + blob = create_blob_before_direct_upload byte_size: data.size, checksum: OpenSSL::Digest::MD5.base64digest("bad data") put blob.service_url_for_direct_upload, params: data assert_response :unprocessable_entity @@ -85,7 +85,7 @@ class ActiveStorage::DiskControllerTest < ActionDispatch::IntegrationTest test "directly uploading blob with mismatched content type" do data = "Something else entirely!" - blob = create_blob_before_direct_upload byte_size: data.size, checksum: Digest::MD5.base64digest(data) + blob = create_blob_before_direct_upload byte_size: data.size, checksum: OpenSSL::Digest::MD5.base64digest(data) put blob.service_url_for_direct_upload, params: data, headers: { "Content-Type" => "application/octet-stream" } assert_response :unprocessable_entity @@ -95,7 +95,7 @@ class ActiveStorage::DiskControllerTest < ActionDispatch::IntegrationTest test "directly uploading blob with different but equivalent content type" do data = "Something else entirely!" blob = create_blob_before_direct_upload( - byte_size: data.size, checksum: Digest::MD5.base64digest(data), content_type: "application/x-gzip") + byte_size: data.size, checksum: OpenSSL::Digest::MD5.base64digest(data), content_type: "application/x-gzip") put blob.service_url_for_direct_upload, params: data, headers: { "Content-Type" => "application/x-gzip" } assert_response :no_content @@ -104,7 +104,7 @@ class ActiveStorage::DiskControllerTest < ActionDispatch::IntegrationTest test "directly uploading blob with mismatched content length" do data = "Something else entirely!" - blob = create_blob_before_direct_upload byte_size: data.size - 1, checksum: Digest::MD5.base64digest(data) + blob = create_blob_before_direct_upload byte_size: data.size - 1, checksum: OpenSSL::Digest::MD5.base64digest(data) put blob.service_url_for_direct_upload, params: data, headers: { "Content-Type" => "text/plain" } assert_response :unprocessable_entity diff --git a/activestorage/test/models/blob_test.rb b/activestorage/test/models/blob_test.rb index dc8138192a..00660bae28 100644 --- a/activestorage/test/models/blob_test.rb +++ b/activestorage/test/models/blob_test.rb @@ -38,7 +38,7 @@ class ActiveStorage::BlobTest < ActiveSupport::TestCase assert_equal data, blob.download assert_equal data.length, blob.byte_size - assert_equal Digest::MD5.base64digest(data), blob.checksum + assert_equal OpenSSL::Digest::MD5.base64digest(data), blob.checksum end test "create_and_upload extracts content type from data" do @@ -129,7 +129,7 @@ class ActiveStorage::BlobTest < ActiveSupport::TestCase test "open without integrity" do create_blob(data: "Hello, world!").tap do |blob| - blob.update! checksum: Digest::MD5.base64digest("Goodbye, world!") + blob.update! checksum: OpenSSL::Digest::MD5.base64digest("Goodbye, world!") assert_raises ActiveStorage::IntegrityError do blob.open { |file| flunk "Expected integrity check to fail" } diff --git a/activestorage/test/service/azure_storage_public_service_test.rb b/activestorage/test/service/azure_storage_public_service_test.rb index 23dd12ca90..ba91c8d7de 100644 --- a/activestorage/test/service/azure_storage_public_service_test.rb +++ b/activestorage/test/service/azure_storage_public_service_test.rb @@ -21,7 +21,7 @@ if SERVICE_CONFIGURATIONS[:azure_public] test "direct upload" do key = SecureRandom.base58(24) data = "Something else entirely!" - checksum = Digest::MD5.base64digest(data) + checksum = OpenSSL::Digest::MD5.base64digest(data) content_type = "text/xml" url = @service.url_for_direct_upload(key, expires_in: 5.minutes, content_type: content_type, content_length: data.size, checksum: checksum) diff --git a/activestorage/test/service/azure_storage_service_test.rb b/activestorage/test/service/azure_storage_service_test.rb index d0e266b52e..488c3fc5dd 100644 --- a/activestorage/test/service/azure_storage_service_test.rb +++ b/activestorage/test/service/azure_storage_service_test.rb @@ -12,7 +12,7 @@ if SERVICE_CONFIGURATIONS[:azure] test "direct upload with content type" do key = SecureRandom.base58(24) data = "Something else entirely!" - checksum = Digest::MD5.base64digest(data) + checksum = OpenSSL::Digest::MD5.base64digest(data) content_type = "text/xml" url = @service.url_for_direct_upload(key, expires_in: 5.minutes, content_type: content_type, content_length: data.size, checksum: checksum) @@ -34,7 +34,7 @@ if SERVICE_CONFIGURATIONS[:azure] test "direct upload with content disposition" do key = SecureRandom.base58(24) data = "Something else entirely!" - checksum = Digest::MD5.base64digest(data) + checksum = OpenSSL::Digest::MD5.base64digest(data) url = @service.url_for_direct_upload(key, expires_in: 5.minutes, content_type: "text/plain", content_length: data.size, checksum: checksum) uri = URI.parse url @@ -56,7 +56,7 @@ if SERVICE_CONFIGURATIONS[:azure] key = SecureRandom.base58(24) data = "Foobar" - @service.upload(key, StringIO.new(data), checksum: Digest::MD5.base64digest(data), filename: ActiveStorage::Filename.new("test.txt"), content_type: "text/plain") + @service.upload(key, StringIO.new(data), checksum: OpenSSL::Digest::MD5.base64digest(data), filename: ActiveStorage::Filename.new("test.txt"), content_type: "text/plain") url = @service.url(key, expires_in: 2.minutes, disposition: :attachment, content_type: nil, filename: ActiveStorage::Filename.new("test.html")) response = Net::HTTP.get_response(URI(url)) @@ -70,7 +70,7 @@ if SERVICE_CONFIGURATIONS[:azure] key = SecureRandom.base58(24) data = "Foobar" - @service.upload(key, StringIO.new(data), checksum: Digest::MD5.base64digest(data), filename: ActiveStorage::Filename.new("test.txt"), disposition: :inline) + @service.upload(key, StringIO.new(data), checksum: OpenSSL::Digest::MD5.base64digest(data), filename: ActiveStorage::Filename.new("test.txt"), disposition: :inline) assert_equal("inline; filename=\"test.txt\"; filename*=UTF-8''test.txt", @service.client.get_blob_properties(@service.container, key).properties[:content_disposition]) diff --git a/activestorage/test/service/gcs_public_service_test.rb b/activestorage/test/service/gcs_public_service_test.rb index 9ab440122d..ed6af9ccbc 100644 --- a/activestorage/test/service/gcs_public_service_test.rb +++ b/activestorage/test/service/gcs_public_service_test.rb @@ -21,7 +21,7 @@ if SERVICE_CONFIGURATIONS[:gcs_public] test "direct upload" do key = SecureRandom.base58(24) data = "Something else entirely!" - checksum = Digest::MD5.base64digest(data) + checksum = OpenSSL::Digest::MD5.base64digest(data) url = @service.url_for_direct_upload(key, expires_in: 5.minutes, content_type: "text/plain", content_length: data.size, checksum: checksum) uri = URI.parse url diff --git a/activestorage/test/service/gcs_service_test.rb b/activestorage/test/service/gcs_service_test.rb index f0bc6dd032..959f95de42 100644 --- a/activestorage/test/service/gcs_service_test.rb +++ b/activestorage/test/service/gcs_service_test.rb @@ -16,7 +16,7 @@ if SERVICE_CONFIGURATIONS[:gcs] test "direct upload" do key = SecureRandom.base58(24) data = "Something else entirely!" - checksum = Digest::MD5.base64digest(data) + checksum = OpenSSL::Digest::MD5.base64digest(data) url = @service.url_for_direct_upload(key, expires_in: 5.minutes, content_type: "text/plain", content_length: data.size, checksum: checksum) uri = URI.parse url @@ -36,7 +36,7 @@ if SERVICE_CONFIGURATIONS[:gcs] test "direct upload with content disposition" do key = SecureRandom.base58(24) data = "Something else entirely!" - checksum = Digest::MD5.base64digest(data) + checksum = OpenSSL::Digest::MD5.base64digest(data) url = @service.url_for_direct_upload(key, expires_in: 5.minutes, content_type: "text/plain", content_length: data.size, checksum: checksum) uri = URI.parse url @@ -91,7 +91,7 @@ if SERVICE_CONFIGURATIONS[:gcs] key = SecureRandom.base58(24) data = "Something else entirely!" - @service.upload(key, StringIO.new(data), checksum: Digest::MD5.base64digest(data), disposition: :attachment, filename: ActiveStorage::Filename.new("test.txt"), content_type: "text/plain") + @service.upload(key, StringIO.new(data), checksum: OpenSSL::Digest::MD5.base64digest(data), disposition: :attachment, filename: ActiveStorage::Filename.new("test.txt"), content_type: "text/plain") url = @service.url(key, expires_in: 2.minutes, disposition: :inline, content_type: "text/html", filename: ActiveStorage::Filename.new("test.html")) response = Net::HTTP.get_response(URI(url)) @@ -105,7 +105,7 @@ if SERVICE_CONFIGURATIONS[:gcs] key = SecureRandom.base58(24) data = "Something else entirely!" - @service.upload(key, StringIO.new(data), checksum: Digest::MD5.base64digest(data), content_type: "text/plain") + @service.upload(key, StringIO.new(data), checksum: OpenSSL::Digest::MD5.base64digest(data), content_type: "text/plain") url = @service.url(key, expires_in: 2.minutes, disposition: :inline, content_type: "text/html", filename: ActiveStorage::Filename.new("test.html")) response = Net::HTTP.get_response(URI(url)) @@ -135,7 +135,7 @@ if SERVICE_CONFIGURATIONS[:gcs] test "update metadata" do key = SecureRandom.base58(24) data = "Something else entirely!" - @service.upload(key, StringIO.new(data), checksum: Digest::MD5.base64digest(data), disposition: :attachment, filename: ActiveStorage::Filename.new("test.html"), content_type: "text/html") + @service.upload(key, StringIO.new(data), checksum: OpenSSL::Digest::MD5.base64digest(data), disposition: :attachment, filename: ActiveStorage::Filename.new("test.html"), content_type: "text/html") @service.update_metadata(key, disposition: :inline, filename: ActiveStorage::Filename.new("test.txt"), content_type: "text/plain") url = @service.url(key, expires_in: 2.minutes, disposition: :attachment, content_type: "text/html", filename: ActiveStorage::Filename.new("test.html")) diff --git a/activestorage/test/service/mirror_service_test.rb b/activestorage/test/service/mirror_service_test.rb index 52f0331d31..32b3954bce 100644 --- a/activestorage/test/service/mirror_service_test.rb +++ b/activestorage/test/service/mirror_service_test.rb @@ -25,7 +25,7 @@ class ActiveStorage::Service::MirrorServiceTest < ActiveSupport::TestCase key = SecureRandom.base58(24) data = "Something else entirely!" io = StringIO.new(data) - checksum = Digest::MD5.base64digest(data) + checksum = OpenSSL::Digest::MD5.base64digest(data) @service.upload key, io.tap(&:read), checksum: checksum assert_predicate io, :eof? @@ -41,7 +41,7 @@ class ActiveStorage::Service::MirrorServiceTest < ActiveSupport::TestCase test "downloading from primary service" do key = SecureRandom.base58(24) data = "Something else entirely!" - checksum = Digest::MD5.base64digest(data) + checksum = OpenSSL::Digest::MD5.base64digest(data) @service.primary.upload key, StringIO.new(data), checksum: checksum @@ -60,7 +60,7 @@ class ActiveStorage::Service::MirrorServiceTest < ActiveSupport::TestCase test "mirroring a file from the primary service to secondary services where it doesn't exist" do key = SecureRandom.base58(24) data = "Something else entirely!" - checksum = Digest::MD5.base64digest(data) + checksum = OpenSSL::Digest::MD5.base64digest(data) @service.primary.upload key, StringIO.new(data), checksum: checksum @service.mirrors.third.upload key, StringIO.new("Surprise!") diff --git a/activestorage/test/service/s3_public_service_test.rb b/activestorage/test/service/s3_public_service_test.rb index e3ac7953bc..8f671bb3cd 100644 --- a/activestorage/test/service/s3_public_service_test.rb +++ b/activestorage/test/service/s3_public_service_test.rb @@ -35,7 +35,7 @@ if SERVICE_CONFIGURATIONS[:s3_public] test "direct upload" do key = SecureRandom.base58(24) data = "Something else entirely!" - checksum = Digest::MD5.base64digest(data) + checksum = OpenSSL::Digest::MD5.base64digest(data) url = @service.url_for_direct_upload(key, expires_in: 5.minutes, content_type: "text/plain", content_length: data.size, checksum: checksum) uri = URI.parse url diff --git a/activestorage/test/service/s3_service_test.rb b/activestorage/test/service/s3_service_test.rb index 2e987d8f35..8ee8fb34e9 100644 --- a/activestorage/test/service/s3_service_test.rb +++ b/activestorage/test/service/s3_service_test.rb @@ -17,7 +17,7 @@ if SERVICE_CONFIGURATIONS[:s3] test "direct upload" do key = SecureRandom.base58(24) data = "Something else entirely!" - checksum = Digest::MD5.base64digest(data) + checksum = OpenSSL::Digest::MD5.base64digest(data) url = @service.url_for_direct_upload(key, expires_in: 5.minutes, content_type: "text/plain", content_length: data.size, checksum: checksum) uri = URI.parse url @@ -37,7 +37,7 @@ if SERVICE_CONFIGURATIONS[:s3] test "direct upload with content disposition" do key = SecureRandom.base58(24) data = "Something else entirely!" - checksum = Digest::MD5.base64digest(data) + checksum = OpenSSL::Digest::MD5.base64digest(data) url = @service.url_for_direct_upload(key, expires_in: 5.minutes, content_type: "text/plain", content_length: data.size, checksum: checksum) uri = URI.parse url @@ -58,7 +58,7 @@ if SERVICE_CONFIGURATIONS[:s3] test "directly uploading file larger than the provided content-length does not work" do key = SecureRandom.base58(24) data = "Some text that is longer than the specified content length" - checksum = Digest::MD5.base64digest(data) + checksum = OpenSSL::Digest::MD5.base64digest(data) url = @service.url_for_direct_upload(key, expires_in: 5.minutes, content_type: "text/plain", content_length: data.size - 1, checksum: checksum) uri = URI.parse url @@ -99,7 +99,7 @@ if SERVICE_CONFIGURATIONS[:s3] begin key = SecureRandom.base58(24) data = "Something else entirely!" - service.upload key, StringIO.new(data), checksum: Digest::MD5.base64digest(data) + service.upload key, StringIO.new(data), checksum: OpenSSL::Digest::MD5.base64digest(data) assert_equal "AES256", service.bucket.object(key).server_side_encryption ensure @@ -115,7 +115,7 @@ if SERVICE_CONFIGURATIONS[:s3] @service.upload( key, StringIO.new(data), - checksum: Digest::MD5.base64digest(data), + checksum: OpenSSL::Digest::MD5.base64digest(data), filename: "cool_data.txt", content_type: content_type ) @@ -132,7 +132,7 @@ if SERVICE_CONFIGURATIONS[:s3] @service.upload( key, StringIO.new(data), - checksum: Digest::MD5.base64digest(data), + checksum: OpenSSL::Digest::MD5.base64digest(data), filename: ActiveStorage::Filename.new("cool_data.txt"), disposition: :attachment ) @@ -149,7 +149,7 @@ if SERVICE_CONFIGURATIONS[:s3] key = SecureRandom.base58(24) data = SecureRandom.bytes(8.megabytes) - service.upload key, StringIO.new(data), checksum: Digest::MD5.base64digest(data) + service.upload key, StringIO.new(data), checksum: OpenSSL::Digest::MD5.base64digest(data) assert data == service.download(key) ensure service.delete key @@ -163,7 +163,7 @@ if SERVICE_CONFIGURATIONS[:s3] key = SecureRandom.base58(24) data = SecureRandom.bytes(3.megabytes) - service.upload key, StringIO.new(data), checksum: Digest::MD5.base64digest(data) + service.upload key, StringIO.new(data), checksum: OpenSSL::Digest::MD5.base64digest(data) assert data == service.download(key) ensure service.delete key diff --git a/activestorage/test/service/shared_service_tests.rb b/activestorage/test/service/shared_service_tests.rb index c6d83a3553..20896e3ebd 100644 --- a/activestorage/test/service/shared_service_tests.rb +++ b/activestorage/test/service/shared_service_tests.rb @@ -22,7 +22,7 @@ module ActiveStorage::Service::SharedServiceTests test "uploading with integrity" do key = SecureRandom.base58(24) data = "Something else entirely!" - @service.upload(key, StringIO.new(data), checksum: Digest::MD5.base64digest(data)) + @service.upload(key, StringIO.new(data), checksum: OpenSSL::Digest::MD5.base64digest(data)) assert_equal data, @service.download(key) ensure @@ -34,7 +34,7 @@ module ActiveStorage::Service::SharedServiceTests data = "Something else entirely!" assert_raises(ActiveStorage::IntegrityError) do - @service.upload(key, StringIO.new(data), checksum: Digest::MD5.base64digest("bad data")) + @service.upload(key, StringIO.new(data), checksum: OpenSSL::Digest::MD5.base64digest("bad data")) end assert_not @service.exist?(key) @@ -48,7 +48,7 @@ module ActiveStorage::Service::SharedServiceTests @service.upload( key, StringIO.new(data), - checksum: Digest::MD5.base64digest(data), + checksum: OpenSSL::Digest::MD5.base64digest(data), filename: "racecar.jpg", content_type: "image/jpeg" ) diff --git a/activestorage/test/test_helper.rb b/activestorage/test/test_helper.rb index 6de61ec38e..75a9df5bfa 100644 --- a/activestorage/test/test_helper.rb +++ b/activestorage/test/test_helper.rb @@ -97,7 +97,7 @@ class ActiveSupport::TestCase def directly_upload_file_blob(filename: "racecar.jpg", content_type: "image/jpeg", record: nil) file = file_fixture(filename) byte_size = file.size - checksum = Digest::MD5.file(file).base64digest + checksum = OpenSSL::Digest::MD5.file(file).base64digest create_blob_before_direct_upload(filename: filename, byte_size: byte_size, checksum: checksum, content_type: content_type, record: record).tap do |blob| service = ActiveStorage::Blob.service.try(:primary) || ActiveStorage::Blob.service diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 6c401437bc..04c9ea8f59 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,7 @@ +* OpenSSL constants are now used for Digest computations. + + *Dirkjan Bussink* + * `TimeZone.iso8601` now accepts valid ordinal values similar to Ruby's `Date._iso8601` method. A valid ordinal value will be converted to an instance of `TimeWithZone` using the `:year` and `:yday` fragments returned from `Date._iso8601`. diff --git a/activesupport/lib/active_support/core_ext/digest/uuid.rb b/activesupport/lib/active_support/core_ext/digest/uuid.rb index 6e949a2d72..5e8f6671f4 100644 --- a/activesupport/lib/active_support/core_ext/digest/uuid.rb +++ b/activesupport/lib/active_support/core_ext/digest/uuid.rb @@ -11,17 +11,17 @@ module Digest # Generates a v5 non-random UUID (Universally Unique IDentifier). # - # Using Digest::MD5 generates version 3 UUIDs; Digest::SHA1 generates version 5 UUIDs. + # Using OpenSSL::Digest::MD5 generates version 3 UUIDs; OpenSSL::Digest::SHA1 generates version 5 UUIDs. # uuid_from_hash always generates the same UUID for a given name and namespace combination. # # See RFC 4122 for details of UUID at: https://www.ietf.org/rfc/rfc4122.txt def self.uuid_from_hash(hash_class, uuid_namespace, name) - if hash_class == Digest::MD5 + if hash_class == Digest::MD5 || hash_class == OpenSSL::Digest::MD5 version = 3 - elsif hash_class == Digest::SHA1 + elsif hash_class == Digest::SHA1 || hash_class == OpenSSL::Digest::SHA1 version = 5 else - raise ArgumentError, "Expected Digest::SHA1 or Digest::MD5, got #{hash_class.name}." + raise ArgumentError, "Expected OpenSSL::Digest::SHA1 or OpenSSL::Digest::MD5, got #{hash_class.name}." end hash = hash_class.new @@ -35,14 +35,14 @@ module Digest "%08x-%04x-%04x-%04x-%04x%08x" % ary end - # Convenience method for uuid_from_hash using Digest::MD5. + # Convenience method for uuid_from_hash using OpenSSL::Digest::MD5. def self.uuid_v3(uuid_namespace, name) - uuid_from_hash(Digest::MD5, uuid_namespace, name) + uuid_from_hash(OpenSSL::Digest::MD5, uuid_namespace, name) end - # Convenience method for uuid_from_hash using Digest::SHA1. + # Convenience method for uuid_from_hash using OpenSSL::Digest::SHA1. def self.uuid_v5(uuid_namespace, name) - uuid_from_hash(Digest::SHA1, uuid_namespace, name) + uuid_from_hash(OpenSSL::Digest::SHA1, uuid_namespace, name) end # Convenience method for SecureRandom.uuid. diff --git a/activesupport/test/core_ext/digest/uuid_test.rb b/activesupport/test/core_ext/digest/uuid_test.rb index 1934591476..1dc21bb2dc 100644 --- a/activesupport/test/core_ext/digest/uuid_test.rb +++ b/activesupport/test/core_ext/digest/uuid_test.rb @@ -20,7 +20,7 @@ class DigestUUIDExt < ActiveSupport::TestCase def test_invalid_hash_class assert_raise ArgumentError do - Digest::UUID.uuid_from_hash(Digest::SHA2, Digest::UUID::OID_NAMESPACE, "1.2.3") + Digest::UUID.uuid_from_hash(OpenSSL::Digest::SHA256, Digest::UUID::OID_NAMESPACE, "1.2.3") end end end