Merge "Create secretutils and include 'constant_time_compare' function"

This commit is contained in:
Jenkins 2016-01-21 04:25:57 +00:00 committed by Gerrit Code Review
commit 123e12201a
4 changed files with 94 additions and 0 deletions

View File

@ -0,0 +1,6 @@
=============
secretutils
=============
.. automodule:: oslo_utils.secretutils
:members:

View File

@ -28,6 +28,7 @@ API Documentation
api/importutils
api/netutils
api/reflection
api/secretutils
api/strutils
api/timeutils
api/units

35
oslo_utils/secretutils.py Normal file
View File

@ -0,0 +1,35 @@
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import hmac
try:
constant_time_compare = hmac.compare_digest
except AttributeError:
def constant_time_compare(first, second):
"""Returns True if both string inputs are equal, otherwise False.
This function should take a constant amount of time regardless of
how many characters in the strings match. This function uses an
approach designed to prevent timing analysis by avoiding
content-based short circuiting behaviour, making it appropriate
for cryptography.
"""
if len(first) != len(second):
return False
result = 0
for x, y in zip(first, second):
result |= ord(x) ^ ord(y)
return result == 0

View File

@ -0,0 +1,52 @@
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslotest import base as test_base
import testscenarios
from oslo_utils import secretutils
class SecretUtilsTest(testscenarios.TestWithScenarios,
test_base.BaseTestCase):
scenarios = [
('binary', {'converter': lambda text: text.encode('utf-8')}),
('unicode', {'converter': lambda text: text}),
]
def test_constant_time_compare(self):
# make sure it works as a compare, the "constant time" aspect
# isn't appropriate to test in unittests
ctc = secretutils.constant_time_compare
self.assertTrue(ctc(self.converter(u'abcd'),
self.converter(u'abcd')))
self.assertTrue(ctc(self.converter(u''),
self.converter(u'')))
self.assertFalse(ctc(self.converter(u'abcd'),
self.converter(u'efgh')))
self.assertFalse(ctc(self.converter(u'abc'),
self.converter(u'abcd')))
self.assertFalse(ctc(self.converter(u'abc'),
self.converter(u'abc\x00')))
self.assertFalse(ctc(self.converter(u''),
self.converter(u'abc')))
self.assertTrue(ctc(self.converter(u'abcd1234'),
self.converter(u'abcd1234')))
self.assertFalse(ctc(self.converter(u'abcd1234'),
self.converter(u'ABCD234')))
self.assertFalse(ctc(self.converter(u'abcd1234'),
self.converter(u'a')))
self.assertFalse(ctc(self.converter(u'abcd1234'),
self.converter(u'1234abcd')))