lib/api_auth/base.rb in api-auth-2.0.1 vs lib/api_auth/base.rb in api-auth-2.1.0
- old
+ new
@@ -39,11 +39,11 @@
if headers.md5_mismatch?
false
elsif !signatures_match?(headers, secret_key, options)
false
- elsif request_too_old?(headers)
+ elsif !request_within_time_window?(headers)
false
else
true
end
end
@@ -67,18 +67,19 @@
b64_encode(Digest::SHA2.new(512).digest(random_bytes))
end
private
- AUTH_HEADER_PATTERN = /APIAuth(?:-HMAC-(MD[245]|SHA(?:1|224|256|384|512)?))? ([^:]+):(.+)$/
+ AUTH_HEADER_PATTERN = /APIAuth(?:-HMAC-(MD5|SHA(?:1|224|256|384|512)?))? ([^:]+):(.+)$/
- def request_too_old?(headers)
+ def request_within_time_window?(headers)
# 900 seconds is 15 minutes
- Time.httpdate(headers.timestamp).utc < (Time.now.utc - 900)
+ Time.httpdate(headers.timestamp).utc > (Time.now.utc - 900) &&
+ Time.httpdate(headers.timestamp).utc < (Time.now.utc + 900)
rescue ArgumentError
- true
+ false
end
def signatures_match?(headers, secret_key, options)
match_data = parse_auth_header(headers.authorization_header)
return false unless match_data
@@ -89,10 +90,19 @@
options = { :digest => digest }.merge(options)
header_sig = match_data[3]
calculated_sig = hmac_signature(headers, secret_key, options)
- header_sig == calculated_sig
+ secure_equals?(header_sig, calculated_sig, secret_key)
+ end
+
+ def secure_equals?(m1, m2, key)
+ sha1_hmac(key, m1) == sha1_hmac(key, m2)
+ end
+
+ def sha1_hmac(key, message)
+ digest = OpenSSL::Digest.new('sha1')
+ OpenSSL::HMAC.digest(digest, key, message)
end
def hmac_signature(headers, secret_key, options)
canonical_string = headers.canonical_string(options[:override_http_method])
digest = OpenSSL::Digest.new(options[:digest])