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