aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport
diff options
context:
space:
mode:
authorGuillermo Iguaran <guilleiguaran@gmail.com>2014-10-23 10:56:48 -0300
committerGuillermo Iguaran <guilleiguaran@gmail.com>2014-10-23 14:54:06 -0300
commitc8c660002f4b0e9606de96325f20b95248b6ff2d (patch)
treef7d6e16bc6a2876f5cfdee0f113746b1a606093e /activesupport
parent5a16b5cd6d35a1a8a6846f6f73d543f466a5f03f (diff)
downloadrails-c8c660002f4b0e9606de96325f20b95248b6ff2d.tar.gz
rails-c8c660002f4b0e9606de96325f20b95248b6ff2d.tar.bz2
rails-c8c660002f4b0e9606de96325f20b95248b6ff2d.zip
Add AS::SecurityUtils.secure_compare for constant time string comparison
Diffstat (limited to 'activesupport')
-rw-r--r--activesupport/lib/active_support/security_utils.rb20
-rw-r--r--activesupport/test/security_utils_test.rb9
2 files changed, 29 insertions, 0 deletions
diff --git a/activesupport/lib/active_support/security_utils.rb b/activesupport/lib/active_support/security_utils.rb
new file mode 100644
index 0000000000..64c4801179
--- /dev/null
+++ b/activesupport/lib/active_support/security_utils.rb
@@ -0,0 +1,20 @@
+module ActiveSupport
+ module SecurityUtils
+ # Constant time string comparison.
+ #
+ # The values compared should be of fixed length, such as strings
+ # that have already been processed by HMAC. This should not be used
+ # on variable length plaintext strings because it could leak length info
+ # via timing attacks.
+ def secure_compare(a, b)
+ return false unless a.bytesize == b.bytesize
+
+ l = a.unpack "C#{a.bytesize}"
+
+ res = 0
+ b.each_byte { |byte| res |= byte ^ l.shift }
+ res == 0
+ end
+ module_function :secure_compare
+ end
+end
diff --git a/activesupport/test/security_utils_test.rb b/activesupport/test/security_utils_test.rb
new file mode 100644
index 0000000000..08d2e3baa6
--- /dev/null
+++ b/activesupport/test/security_utils_test.rb
@@ -0,0 +1,9 @@
+require 'abstract_unit'
+require 'active_support/security_utils'
+
+class SecurityUtilsTest < ActiveSupport::TestCase
+ def test_secure_compare_should_perform_string_comparison
+ assert ActiveSupport::SecurityUtils.secure_compare('a', 'a')
+ assert !ActiveSupport::SecurityUtils.secure_compare('a', 'b')
+ end
+end