Skip to content
Browse files

Fix timing attack vulnerability in ActiveSupport::MessageVerifier.

Use a constant-time comparison algorithm to compare the candidate HMAC with the calculated HMAC to prevent leaking information about the calculated HMAC.

Signed-off-by: Michael Koziarski <michael@koziarski.com>
  • Loading branch information...
1 parent bd97c30 commit 5e6dab8b34152bc48c89032d20e5bda1511e28fb @codahale codahale committed with NZKoz
Showing with 16 additions and 3 deletions.
  1. +16 −3 activesupport/lib/active_support/message_verifier.rb
View
19 activesupport/lib/active_support/message_verifier.rb
@@ -25,10 +25,10 @@ def initialize(secret, digest = 'SHA1')
def verify(signed_message)
data, digest = signed_message.split("--")
- if digest != generate_digest(data)
- raise InvalidSignature
- else
+ if secure_compare(digest, generate_digest(data))
Marshal.load(ActiveSupport::Base64.decode64(data))
+ else
+ raise InvalidSignature
end
end
@@ -38,6 +38,19 @@ def generate(value)
end
private
+ # constant-time comparison algorithm to prevent timing attacks
+ def secure_compare(a, b)
+ if a.length == b.length
+ result = 0
+ for i in 0..(a.length - 1)
+ result |= a[i] ^ b[i]
+ end
+ result == 0
+ else
+ false
+ end
+ end
+
def generate_digest(data)
require 'openssl' unless defined?(OpenSSL)
OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new(@digest), @secret, data)

2 comments on commit 5e6dab8

@speedmax

This commit contains Ruby 1.9 incompatibility

It assumes string returns a character code, i am currently using following work around

http://gist.github.com/182118

Please sign in to comment.
Something went wrong with that request. Please try again.