From d9c4405db70c2b21d055b9d7f47a443d7ff77019 Mon Sep 17 00:00:00 2001 From: Michael Schlenker Date: Wed, 14 Aug 2024 12:12:54 +0200 Subject: [PATCH 1/2] Fix broken HashType.from_composite_str method for Blake2b, SHA3, Blake3 Signed-off-by: Michael Schlenker --- cyclonedx/model/__init__.py | 26 +++++++++++++++++++++++--- tests/test_model.py | 11 +++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/cyclonedx/model/__init__.py b/cyclonedx/model/__init__.py index 4edb50e1..6c475d79 100644 --- a/cyclonedx/model/__init__.py +++ b/cyclonedx/model/__init__.py @@ -418,6 +418,11 @@ def from_composite_str(composite_hash: str) -> 'HashType': Composite Hash string of the format `HASH_ALGORITHM`:`HASH_VALUE`. Example: `sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b`. + Valid case insensitive prefixes are: + `md5`, `sha1`, `sha256`, `sha384`, `sha512`, `blake2b256`, `blake2b384`, `blake2b512`, + `sha3-256`, `sha3-384`, `sha3-512`, + `blake3`. + Raises: `UnknownHashTypeException` if the type of hash cannot be determined. @@ -432,17 +437,32 @@ def from_composite_str(composite_hash: str) -> 'HashType': alg=HashAlgorithm.MD5, content=parts[1].lower() ) + elif algorithm_prefix[0:4] == 'sha3': + return HashType( + alg=getattr(HashAlgorithm, f'SHA3_{algorithm_prefix[5:]}'), + content=parts[1].lower() + ) + elif algorithm_prefix == 'sha1': + return HashType( + alg=HashAlgorithm.SHA_1, + content=parts[1].lower() + ) elif algorithm_prefix[0:3] == 'sha': + # This is actually SHA2... return HashType( alg=getattr(HashAlgorithm, f'SHA_{algorithm_prefix[3:]}'), content=parts[1].lower() ) - elif algorithm_prefix[0:6] == 'blake2': + elif algorithm_prefix[0:7] == 'blake2b': return HashType( - alg=getattr(HashAlgorithm, f'BLAKE2b_{algorithm_prefix[6:]}'), + alg=getattr(HashAlgorithm, f'BLAKE2B_{algorithm_prefix[7:]}'), + content=parts[1].lower() + ) + elif algorithm_prefix[0:6] == 'blake3': + return HashType( + alg=HashAlgorithm.BLAKE3, content=parts[1].lower() ) - raise UnknownHashTypeException(f'Unable to determine hash type from {composite_hash!r}') def __init__( diff --git a/tests/test_model.py b/tests/test_model.py index 7b9ab794..1ddb9379 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -262,6 +262,17 @@ def test_hash_type_from_hashlib_alg_throws_on_unknown(self) -> None: HashAlgorithm.SHA_256, '806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b'), ('MD5', 'MD5:dc26cd71b80d6757139f38156a43c545', HashAlgorithm.MD5, 'dc26cd71b80d6757139f38156a43c545'), + ('sha3-256', 'sha3-256:f43909a5e6420ee26b710718f296c7be85ba393e6b218107811067f49ea80101', + HashAlgorithm.SHA3_256, 'f43909a5e6420ee26b710718f296c7be85ba393e6b218107811067f49ea80101'), + ('sha1', 'sha1:b82b9f695a3ae28053cb3776d2132ab625798055', + HashAlgorithm.SHA_1, 'b82b9f695a3ae28053cb3776d2132ab625798055'), + # Name format as used by 'openssl dgst and the Blake2 RFC' + ('blake2b512', + 'blake2b512:6d518ac5c7a022e954ecb21b8bf68d7f5c52e3c3579cd96f3bde4' + 'f76daaaa69a96a5eee268fb8fa2745930c37f0672424136b538878474bc4f586a63e13ae23f', + HashAlgorithm.BLAKE2B_512, + '6d518ac5c7a022e954ecb21b8bf68d7f5c52e3c3579cd96f3bde4f76daaaa69a' + '96a5eee268fb8fa2745930c37f0672424136b538878474bc4f586a63e13ae23f'), ) def test_hash_type_from_composite_str(self, composite: str, e_alg: HashAlgorithm, e_content: str) -> None: h = HashType.from_composite_str(composite) From bdae258417f3f503f46b7762037e6f2081554dc7 Mon Sep 17 00:00:00 2001 From: Michael Schlenker Date: Wed, 14 Aug 2024 13:19:28 +0200 Subject: [PATCH 2/2] Add the weird legacy blake2256 etc. cases back in. Signed-off-by: Michael Schlenker --- cyclonedx/model/__init__.py | 7 ++++++- tests/test_model.py | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/cyclonedx/model/__init__.py b/cyclonedx/model/__init__.py index 6c475d79..61ba9beb 100644 --- a/cyclonedx/model/__init__.py +++ b/cyclonedx/model/__init__.py @@ -420,7 +420,7 @@ def from_composite_str(composite_hash: str) -> 'HashType': Valid case insensitive prefixes are: `md5`, `sha1`, `sha256`, `sha384`, `sha512`, `blake2b256`, `blake2b384`, `blake2b512`, - `sha3-256`, `sha3-384`, `sha3-512`, + `blake2256`, `blake2384`, `blake2512`, `sha3-256`, `sha3-384`, `sha3-512`, `blake3`. Raises: @@ -458,6 +458,11 @@ def from_composite_str(composite_hash: str) -> 'HashType': alg=getattr(HashAlgorithm, f'BLAKE2B_{algorithm_prefix[7:]}'), content=parts[1].lower() ) + elif algorithm_prefix[0:6] == 'blake2': + return HashType( + alg=getattr(HashAlgorithm, f'BLAKE2B_{algorithm_prefix[6:]}'), + content=parts[1].lower() + ) elif algorithm_prefix[0:6] == 'blake3': return HashType( alg=HashAlgorithm.BLAKE3, diff --git a/tests/test_model.py b/tests/test_model.py index 1ddb9379..76959f33 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -273,6 +273,12 @@ def test_hash_type_from_hashlib_alg_throws_on_unknown(self) -> None: HashAlgorithm.BLAKE2B_512, '6d518ac5c7a022e954ecb21b8bf68d7f5c52e3c3579cd96f3bde4f76daaaa69a' '96a5eee268fb8fa2745930c37f0672424136b538878474bc4f586a63e13ae23f'), + ('blake2512', + 'blake2512:6d518ac5c7a022e954ecb21b8bf68d7f5c52e3c3579cd96f3bde4' + 'f76daaaa69a96a5eee268fb8fa2745930c37f0672424136b538878474bc4f586a63e13ae23f', + HashAlgorithm.BLAKE2B_512, + '6d518ac5c7a022e954ecb21b8bf68d7f5c52e3c3579cd96f3bde4f76daaaa69a' + '96a5eee268fb8fa2745930c37f0672424136b538878474bc4f586a63e13ae23f'), ) def test_hash_type_from_composite_str(self, composite: str, e_alg: HashAlgorithm, e_content: str) -> None: h = HashType.from_composite_str(composite)