Permalink
Browse files

making secure_compare faster

[#3195 state:committed]

Signed-off-by: Jeremy Kemper <jeremy@bitsweat.net>
  • Loading branch information...
tenderlove authored and jeremy committed Sep 13, 2009
1 parent e590508 commit f959758687b63e8f5366b315cc4845c2bbd5f6e8
Showing with 8 additions and 28 deletions.
  1. +8 −28 activesupport/lib/active_support/message_verifier.rb
@@ -38,35 +38,15 @@ def generate(value)
end
private
- if "foo".respond_to?(:force_encoding)
- # constant-time comparison algorithm to prevent timing attacks
- def secure_compare(a, b)
- a = a.dup.force_encoding(Encoding::BINARY)
- b = b.dup.force_encoding(Encoding::BINARY)
+ # constant-time comparison algorithm to prevent timing attacks
+ def secure_compare(a, b)
+ return false unless a.bytesize == b.bytesize
- if a.length == b.length
- result = 0
- for i in 0..(a.length - 1)
- result |= a[i].ord ^ b[i].ord
- end
- result == 0
- else
- false
- end
- end
- else
- # For 1.8
- 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
+ l = a.unpack "C#{a.bytesize}"
+
+ res = 0
+ b.each_byte { |b| res |= b ^ l.shift }
+ res == 0
end
def generate_digest(data)

1 comment on commit f959758

@strmpnk

This comment has been minimized.

Show comment Hide comment
@strmpnk

strmpnk Jul 17, 2010

If you're worried about string comparison timing attack vectors here, one good strategy is to remove the attackers control or ability to guess of the actual content being compared. http://gist.github.com/479111 is a little benchmark I wrote to show how SHA1 can beat straight comparisons. The code is a little easy to understand and harder to get wrong as well as faster. I'm sure a C extension would beat any of this but assuming we are in standard ruby, this works well enough.

If you're worried about string comparison timing attack vectors here, one good strategy is to remove the attackers control or ability to guess of the actual content being compared. http://gist.github.com/479111 is a little benchmark I wrote to show how SHA1 can beat straight comparisons. The code is a little easy to understand and harder to get wrong as well as faster. I'm sure a C extension would beat any of this but assuming we are in standard ruby, this works well enough.

Please sign in to comment.