Skip to content

Commit 308fb19

Browse files
bdewaterioquatix
authored andcommitted
Add OpenSSL.secure_compare with same semantics as Active Support >= 5.2
secure_compare is for user input, fixed_length_secure_compare for already processed data that is known to have the same length
1 parent 0faa750 commit 308fb19

File tree

2 files changed

+31
-0
lines changed

2 files changed

+31
-0
lines changed

lib/openssl.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,17 @@
2020
require 'openssl/x509'
2121
require 'openssl/ssl'
2222
require 'openssl/pkcs5'
23+
24+
module OpenSSL
25+
# call-seq:
26+
# OpenSSL.secure_compare(string, string) -> boolean
27+
#
28+
# Constant time memory comparison. Inputs are hashed using SHA-256 to mask
29+
# the length of the secret. Returns +true+ if the strings are identical,
30+
# +false+ otherwise.
31+
def self.secure_compare(a, b)
32+
hashed_a = OpenSSL::Digest::SHA256.digest(a)
33+
hashed_b = OpenSSL::Digest::SHA256.digest(b)
34+
OpenSSL.fixed_length_secure_compare(hashed_a, hashed_b) && a == b
35+
end
36+
end

test/test_ossl.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,23 @@ def test_fixed_length_secure_compare
2626
assert_raises(ArgumentError) { OpenSSL.fixed_length_secure_compare("aaa", "bbbb") }
2727
end
2828

29+
def test_secure_compare
30+
refute OpenSSL.secure_compare("aaa", "a")
31+
refute OpenSSL.secure_compare("aaa", "aa")
32+
33+
assert OpenSSL.secure_compare("aaa", "aaa")
34+
35+
refute OpenSSL.secure_compare("aaa", "aaaa")
36+
refute OpenSSL.secure_compare("aaa", "baa")
37+
refute OpenSSL.secure_compare("aaa", "aba")
38+
refute OpenSSL.secure_compare("aaa", "aab")
39+
refute OpenSSL.secure_compare("aaa", "aaab")
40+
refute OpenSSL.secure_compare("aaa", "b")
41+
refute OpenSSL.secure_compare("aaa", "bb")
42+
refute OpenSSL.secure_compare("aaa", "bbb")
43+
refute OpenSSL.secure_compare("aaa", "bbbb")
44+
end
45+
2946
def test_memcmp_timing
3047
# Ensure using fixed_length_secure_compare takes almost exactly the same amount of time to compare two different strings.
3148
# Regular string comparison will short-circuit on the first non-matching character, failing this test.

0 commit comments

Comments
 (0)