mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
c76a8c72d5
Hex encoding is base 16 which makes the original input twice as big. With this change less time need to be spent in fixed_length_secure_compare.
31 lines
989 B
Ruby
31 lines
989 B
Ruby
# frozen_string_literal: true
|
|
|
|
require "digest/sha2"
|
|
|
|
module ActiveSupport
|
|
module SecurityUtils
|
|
# Constant time string comparison, for fixed length strings.
|
|
#
|
|
# The values compared should be of fixed length, such as strings
|
|
# that have already been processed by HMAC. Raises in case of length mismatch.
|
|
def fixed_length_secure_compare(a, b)
|
|
raise ArgumentError, "string length mismatch." unless a.bytesize == b.bytesize
|
|
|
|
l = a.unpack "C#{a.bytesize}"
|
|
|
|
res = 0
|
|
b.each_byte { |byte| res |= byte ^ l.shift }
|
|
res == 0
|
|
end
|
|
module_function :fixed_length_secure_compare
|
|
|
|
# Constant time string comparison, for variable length strings.
|
|
#
|
|
# The values are first processed by SHA256, so that we don't leak length info
|
|
# via timing attacks.
|
|
def secure_compare(a, b)
|
|
fixed_length_secure_compare(::Digest::SHA256.digest(a), ::Digest::SHA256.digest(b)) && a == b
|
|
end
|
|
module_function :secure_compare
|
|
end
|
|
end
|