lib/ey-hmac/adapter.rb in ey-hmac-0.0.3 vs lib/ey-hmac/adapter.rb in ey-hmac-0.0.4

- old
+ new

@@ -110,17 +110,30 @@ if authorization_match = AUTHORIZATION_REGEXP.match(authorization_signature) key_id = authorization_match[1] signature_value = authorization_match[2] if key_secret = block.call(key_id) - if signature_value == (calculated_signature = signature(key_secret)) + calculated_signature = signature(key_secret) + if secure_compare(signature_value, calculated_signature) else raise(Ey::Hmac::SignatureMismatch, "Calculated siganature #{signature_value} does not match #{calculated_signature} using #{canonicalize.inspect}") end else raise(Ey::Hmac::MissingSecret, "Failed to find secret matching #{key_id.inspect}") end else raise(Ey::Hmac::MissingAuthorization, "Failed to parse authorization_signature #{authorization_signature}") end true end alias authenticate! authenticated! + + # Constant time string comparison. + # pulled from https://github.com/rack/rack/blob/master/lib/rack/utils.rb#L399 + def secure_compare(a, b) + return false unless a.bytesize == b.bytesize + + l = a.unpack("C*") + + r, i = 0, -1 + b.each_byte { |v| r |= v ^ l[i+=1] } + r == 0 + end end