Skip to content

Instantly share code, notes, and snippets.

@levigross
Last active January 13, 2023 06:06
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save levigross/8691015 to your computer and use it in GitHub Desktop.
Save levigross/8691015 to your computer and use it in GitHub Desktop.
Constant Time Comparison functions
; Taken from https://github.com/weavejester/crypto-equality/blob/master/src/crypto/equality.clj
(ns crypto.equality
"Securely test sequences of data for equality.")
(defn eq?
"Test whether two sequences of characters or bytes are equal in a way that
protects against timing attacks. Note that this does not prevent an attacker
from discovering the *length* of the data being compared."
[a b]
(let [a (map int a), b (map int b)]
(if (and a b (= (count a) (count b)))
(zero? (reduce bit-or (map bit-xor a b)))
false)))
#Taken from Django
def constant_time_compare(val1, val2):
"""
Returns True if the two strings are equal, False otherwise.
The time taken is independent of the number of characters that match.
For the sake of simplicity, this function executes in constant time only
when the two strings have the same length. It short-circuits when they
have different lengths.
"""
if len(val1) != len(val2):
return False
result = 0
for x, y in zip(val1, val2):
result |= ord(x) ^ ord(y)
return result == 0
#This is included within the stdlib in Py3k for an C alternative for Python 2.7.x see https://github.com/levigross/constant_time_compare/
from operator import _compare_digest as constant_time_compare
# Or you can use this function taken from Django
def constant_time_compare(val1, val2):
"""
Returns True if the two strings are equal, False otherwise.
The time taken is independent of the number of characters that match.
For the sake of simplicity, this function executes in constant time only
when the two strings have the same length. It short-circuits when they
have different lengths.
"""
if len(val1) != len(val2):
return False
result = 0
for x, y in zip(val1, val2):
result |= x ^ y
return result == 0
import Data.Bits
import Data.Char
import Data.List
import Data.Function
-- Thank you Yan for this snippet
constantTimeCompare a b =
((==) `on` length) a b && 0 == (foldl1 (.|.) joined)
where
joined = zipWith (xor `on` ord) a b
// Taken from http://codahale.com/a-lesson-in-timing-attacks/
public static boolean isEqual(byte[] a, byte[] b) {
if (a.length != b.length) {
return false;
}
int result = 0;
for (int i = 0; i < a.length; i++) {
result |= a[i] ^ b[i]
}
return result == 0;
}
def secure_compare(a, b)
return false if a.empty? || b.empty? || a.bytesize != b.bytesize
l = a.unpack "C#{a.bytesize}"
res = 0
b.each_byte { |byte| res |= byte ^ l.shift }
res == 0
end
@tomato42
Copy link

tomato42 commented Aug 3, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment