From 1f3efa173c1e2c84b007bfda65562c5abe80b53f Mon Sep 17 00:00:00 2001 From: Samuel M Smith Date: Fri, 9 Aug 2024 11:28:35 -0600 Subject: [PATCH] refactor Diger to simplify --- src/keri/core/coring.py | 160 +++++++++++++------------------------- tests/core/test_coring.py | 5 +- 2 files changed, 58 insertions(+), 107 deletions(-) diff --git a/src/keri/core/coring.py b/src/keri/core/coring.py index 2a55d879..8db1148f 100644 --- a/src/keri/core/coring.py +++ b/src/keri/core/coring.py @@ -55,6 +55,9 @@ ECDSA_256r1_SEEDBYTES = 32 ECDSA_256k1_SEEDBYTES = 32 +# digest algorithm klas, digest size (not default), digest length +# size and length are needed for some digest types as function parameters +Digestage = namedtuple("Digestage", "klas size length") # SAID field labels Saidage = namedtuple("Saidage", "dollar at id_ i d") @@ -269,6 +272,8 @@ def __delitem__(self, name): + + @dataclass(frozen=True) class MatterCodex: """ @@ -3094,68 +3099,77 @@ class Diger(Matter): """ - def __init__(self, raw=None, ser=None, code=MtrDex.Blake3_256, **kwa): - """ - Assign digest verification function to ._verify + # Maps digest codes to Digestages of algorithms for computing digest. + # Should be based on the same set of codes as in DigestCodex + # so Matter.digestive property works. + # Use unit tests to ensure codex elements sets match - See Matter for inherited parameters + Digests = { + DigDex.Blake3_256: Digestage(klas=blake3.blake3, size=None, length=None), + DigDex.Blake2b_256: Digestage(klas=hashlib.blake2b, size=32, length=None), + DigDex.Blake2s_256: Digestage(klas=hashlib.blake2s, size=None, length=None), + DigDex.SHA3_256: Digestage(klas=hashlib.sha3_256, size=None, length=None), + DigDex.SHA2_256: Digestage(klas=hashlib.sha256, size=None, length=None), + DigDex.Blake3_512: Digestage(klas=blake3.blake3, size=None, length=64), + DigDex.Blake2b_512: Digestage(klas=hashlib.blake2b, size=None, length=None), + DigDex.SHA3_512: Digestage(klas=hashlib.sha3_512, size=None, length=None), + DigDex.SHA2_512: Digestage(klas=hashlib.sha512, size=None, length=None), + } + + def __init__(self, raw=None, ser=None, code=DigDex.Blake3_256, **kwa): + """Initialize attributes Inherited Parameters: - raw is bytes of unqualified crypto material usable for crypto operations - qb64b is bytes of fully qualified crypto material - qb64 is str or bytes of fully qualified crypto material - qb2 is bytes of fully qualified crypto material - code is str of derivation code - index is int of count of attached receipts for CryCntDex codes + See Matter Parameters: - ser is bytes serialization from which raw is computed if not raw + ser (bytes): serialization from which raw is computed if not raw """ - # Should implement all digests in DigCodex instance DigDex + try: super(Diger, self).__init__(raw=raw, code=code, **kwa) except EmptyMaterialError as ex: if not ser: raise ex - if code == MtrDex.Blake3_256: - dig = blake3.blake3(ser).digest() - elif code == MtrDex.Blake2b_256: - dig = hashlib.blake2b(ser, digest_size=32).digest() - elif code == MtrDex.Blake2s_256: - dig = hashlib.blake2s(ser, digest_size=32).digest() - elif code == MtrDex.SHA3_256: - dig = hashlib.sha3_256(ser).digest() - elif code == MtrDex.SHA2_256: - dig = hashlib.sha256(ser).digest() - else: - raise InvalidValueError("Unsupported code={code} for diger.") - - super(Diger, self).__init__(raw=dig, code=code, **kwa) - - if self.code == MtrDex.Blake3_256: - self._verify = self._blake3_256 - elif self.code == MtrDex.Blake2b_256: - self._verify = self._blake2b_256 - elif self.code == MtrDex.Blake2s_256: - self._verify = self._blake2s_256 - elif self.code == MtrDex.SHA3_256: - self._verify = self._sha3_256 - elif self.code == MtrDex.SHA2_256: - self._verify = self._sha2_256 - else: - raise InvalidValueError("Unsupported code={self.code} for diger.") + + raw = self._digest(ser, code=code) + + super(Diger, self).__init__(raw=raw, code=code, **kwa) + + if self.code not in DigDex: + raise InvalidCodeError(f"Unsupported Digest {code=}.") + + + def _digest(self, ser, code=DigDex.Blake3_256): + """Returns raw digest of ser using digest algorithm given by code + + Parameters: + ser (bytes): serialization from which raw digest is computed + code (str): derivation code used to lookup digest algorithm + """ + if code not in self.Digests: + raise InvalidCodeError(f"Unsupported Digest {code=}.") + + klas, size, length = self.Digests[code] # digest algo size & length + ikwa = dict(digest_size=size) if size else dict() # opt digest size + dkwa = dict(length=length) if length else dict() # opt digest length + raw = klas(ser, **ikwa).digest(**dkwa) + return (raw) + def verify(self, ser): """ Returns True if raw digest of ser bytes (serialization) matches .raw - using .raw as reference digest for ._verify digest algorithm determined + using .raw as reference digest for digest algorithm determined by .code Parameters: - ser (bytes): serialization to be digested and compared to .ser + ser (bytes): serialization to be digested and compared to .raw + """ - return (self._verify(ser=ser, raw=self.raw)) + return (self._digest(ser=ser, code=self.code) == self.raw) + def compare(self, ser, dig=None, diger=None): """ @@ -3202,65 +3216,6 @@ def compare(self, ser, dig=None, diger=None): return (False) - @staticmethod - def _blake3_256(ser, raw): - """ - Returns True if verified False otherwise - Verifiy blake3_256 digest of ser matches raw - - Parameters: - ser is bytes serialization - dig is bytes reference digest - """ - return (blake3.blake3(ser).digest() == raw) - - @staticmethod - def _blake2b_256(ser, raw): - """ - Returns True if verified False otherwise - Verifiy blake2b_256 digest of ser matches raw - - Parameters: - ser is bytes serialization - dig is bytes reference digest - """ - return (hashlib.blake2b(ser, digest_size=32).digest() == raw) - - @staticmethod - def _blake2s_256(ser, raw): - """ - Returns True if verified False otherwise - Verifiy blake2s_256 digest of ser matches raw - - Parameters: - ser is bytes serialization - dig is bytes reference digest - """ - return (hashlib.blake2s(ser, digest_size=32).digest() == raw) - - @staticmethod - def _sha3_256(ser, raw): - """ - Returns True if verified False otherwise - Verifiy blake2s_256 digest of ser matches raw - - Parameters: - ser is bytes serialization - dig is bytes reference digest - """ - return (hashlib.sha3_256(ser).digest() == raw) - - @staticmethod - def _sha2_256(ser, raw): - """ - Returns True if verified False otherwise - Verifiy blake2s_256 digest of ser matches raw - - Parameters: - ser is bytes serialization - dig is bytes reference digest - """ - return (hashlib.sha256(ser).digest() == raw) class Prefixer(Matter): @@ -3291,9 +3246,6 @@ def __init__(self, **kwa): -# digest algorithm klas, digest size (not default), digest length -# size and length are needed for some digest types as function parameters -Digestage = namedtuple("Digestage", "klas size length") class Saider(Matter): diff --git a/tests/core/test_coring.py b/tests/core/test_coring.py index 7ffc5649..fdd4cffb 100644 --- a/tests/core/test_coring.py +++ b/tests/core/test_coring.py @@ -4439,11 +4439,9 @@ def test_diger(): ser = b'abcdefghijklmnopqrstuvwxyz0123456789' dig = blake3.blake3(ser).digest() - with pytest.raises(coring.InvalidValueError): + with pytest.raises(kering.InvalidCodeError): diger = Diger(raw=dig, code=MtrDex.Ed25519) - with pytest.raises(coring.InvalidValueError): - diger = Diger(ser=ser, code=MtrDex.Ed25519) diger = Diger(raw=dig) # defaults provide Blake3_256 digester assert diger.code == MtrDex.Blake3_256 @@ -5389,6 +5387,7 @@ def test_tholder(): test_ilker() test_traitor() test_verser() + test_diger() #test_texter() #test_prodex() #test_indexer()