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.
This commit is contained in:
Dirkjan Bussink 2021-03-22 10:25:49 +01:00
parent bead3221c7
commit 0523532a3c
No known key found for this signature in database
GPG Key ID: F1573D8E835753FD
37 changed files with 110 additions and 73 deletions

View File

@ -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:

View File

@ -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

View File

@ -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.

View File

@ -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),

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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 `<input type="hidden" form="...">`
value.

View File

@ -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

View File

@ -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.

View File

@ -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")
# # => <img src="http://assets1.example.com/assets/rails.png" />

View File

@ -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)`

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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`.

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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",

View File

@ -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

View File

@ -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" }

View File

@ -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)

View File

@ -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])

View File

@ -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

View File

@ -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"))

View File

@ -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!")

View File

@ -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

View File

@ -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

View File

@ -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"
)

View File

@ -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

View File

@ -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`.

View File

@ -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.

View File

@ -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