Augmenting the hashing strategy

It was only 'sha1' algorithm being used till now in ``hash_file``
method to create hash of the file contents. Need to add 'md5'
to keep the consistency with that of IPA code base. Also, this
method now supports all the algorithms hashlib does. As this
method wasn't being used at all, therefore making the default
algorithm to 'md5'. Will be used in oob firmware update (manual
clean step) to verify the checksum of the images.

Change-Id: I8159fd64d1c074bd539817a40900e34f8fae30d4
This commit is contained in:
Debayan Ray 2016-02-08 06:36:32 -08:00
parent dab2fc347b
commit 1de89030a7
2 changed files with 91 additions and 8 deletions

View File

@ -390,9 +390,36 @@ def file_open(*args, **kwargs):
return file(*args, **kwargs)
def hash_file(file_like_object):
"""Generate a hash for the contents of a file."""
checksum = hashlib.sha1()
def _get_hash_object(hash_algo_name):
"""Create a hash object based on given algorithm.
:param hash_algo_name: name of the hashing algorithm.
:raises: InvalidParameterValue, on unsupported or invalid input.
:returns: a hash object based on the given named algorithm.
"""
algorithms = (hashlib.algorithms_guaranteed if six.PY3
else hashlib.algorithms)
if hash_algo_name not in algorithms:
msg = (_("Unsupported/Invalid hash name '%s' provided.")
% hash_algo_name)
LOG.error(msg)
raise exception.InvalidParameterValue(msg)
return getattr(hashlib, hash_algo_name)()
def hash_file(file_like_object, hash_algo='md5'):
"""Generate a hash for the contents of a file.
It returns a hash of the file object as a string of double length,
containing only hexadecimal digits. It supports all the algorithms
hashlib does.
:param file_like_object: file like object whose hash to be calculated.
:param hash_algo: name of the hashing strategy, default being 'md5'.
:raises: InvalidParameterValue, on unsupported or invalid input.
:returns: a condensed digest of the bytes of contents.
"""
checksum = _get_hash_object(hash_algo)
for chunk in iter(lambda: file_like_object.read(32768), b''):
checksum.update(chunk)
return checksum.hexdigest()

View File

@ -261,12 +261,68 @@ class GenericUtilsTestCase(base.TestCase):
mock.ANY)
fake_context_manager.__enter__.assert_called_once_with()
def test_hash_file(self):
@mock.patch.object(utils, 'hashlib', autospec=True)
def test__get_hash_object(self, hashlib_mock):
algorithms_available = ('md5', 'sha1', 'sha224',
'sha256', 'sha384', 'sha512')
hashlib_mock.algorithms_guaranteed = algorithms_available
hashlib_mock.algorithms = algorithms_available
# | WHEN |
utils._get_hash_object('md5')
utils._get_hash_object('sha1')
utils._get_hash_object('sha224')
utils._get_hash_object('sha256')
utils._get_hash_object('sha384')
utils._get_hash_object('sha512')
# | THEN |
calls = [mock.call.md5(), mock.call.sha1(), mock.call.sha224(),
mock.call.sha256(), mock.call.sha384(), mock.call.sha512()]
hashlib_mock.assert_has_calls(calls)
def test__get_hash_object_throws_for_invalid_or_unsupported_hash_name(
self):
# | WHEN | & | THEN |
self.assertRaises(exception.InvalidParameterValue,
utils._get_hash_object,
'hickory-dickory-dock')
def test_hash_file_for_md5(self):
# | GIVEN |
data = b'Mary had a little lamb, its fleece as white as snow'
flo = six.BytesIO(data)
h1 = utils.hash_file(flo)
h2 = hashlib.sha1(data).hexdigest()
self.assertEqual(h1, h2)
file_like_object = six.BytesIO(data)
expected = hashlib.md5(data).hexdigest()
# | WHEN |
actual = utils.hash_file(file_like_object) # using default, 'md5'
# | THEN |
self.assertEqual(expected, actual)
def test_hash_file_for_sha1(self):
# | GIVEN |
data = b'Mary had a little lamb, its fleece as white as snow'
file_like_object = six.BytesIO(data)
expected = hashlib.sha1(data).hexdigest()
# | WHEN |
actual = utils.hash_file(file_like_object, 'sha1')
# | THEN |
self.assertEqual(expected, actual)
def test_hash_file_for_sha512(self):
# | GIVEN |
data = b'Mary had a little lamb, its fleece as white as snow'
file_like_object = six.BytesIO(data)
expected = hashlib.sha512(data).hexdigest()
# | WHEN |
actual = utils.hash_file(file_like_object, 'sha512')
# | THEN |
self.assertEqual(expected, actual)
def test_hash_file_throws_for_invalid_or_unsupported_hash(self):
# | GIVEN |
data = b'Mary had a little lamb, its fleece as white as snow'
file_like_object = six.BytesIO(data)
# | WHEN | & | THEN |
self.assertRaises(exception.InvalidParameterValue, utils.hash_file,
file_like_object, 'hickory-dickory-dock')
def test_is_valid_boolstr(self):
self.assertTrue(utils.is_valid_boolstr('true'))