From cbc9dbf9130c0b896913620711037ba7663a402d Mon Sep 17 00:00:00 2001 From: Samuel M Smith Date: Sun, 24 Mar 2024 14:09:06 -0600 Subject: [PATCH] Add new primitive code Tag10 --- src/keri/core/coring.py | 4 +- src/keri/core/counting.py | 14 +-- src/keri/core/serdering.py | 26 ++++-- tests/core/test_coring.py | 175 +++++++++++++++++++------------------ 4 files changed, 120 insertions(+), 99 deletions(-) diff --git a/src/keri/core/coring.py b/src/keri/core/coring.py index 07cc7f4a6..e06a18ffd 100644 --- a/src/keri/core/coring.py +++ b/src/keri/core/coring.py @@ -295,7 +295,8 @@ class MatterCodex: Tag1: str = '0J' # Tag1 1 B64 encoded char with pre pad for field tag Tag2: str = '0K' # Tag2 2 B64 encoded chars for field tag or version VV or trait like 'EO' Tag5: str = '0L' # Tag5 5 B64 encoded chars with pre pad for field tag - Tag6: str = '0M' # Tag6 6 B64 encoded chars for field tag or protocol kind version like KERIVV (KERI 1.1) or KKKVVV + Tag6: str = '0M' # Tag6 6 B64 encoded chars for field tag + Tag10: str = '0N' # Tag10 10 B64 encoded chars for field tag or version PPPPMmmMmm ECDSA_256k1N: str = '1AAA' # ECDSA secp256k1 verification key non-transferable, basic derivation. ECDSA_256k1: str = '1AAB' # ECDSA public verification or encryption key, basic derivation Ed448N: str = '1AAC' # Ed448 non-transferable prefix public signing verification key. Basic derivation. @@ -723,6 +724,7 @@ class Matter: '0K': Sizage(hs=2, ss=0, fs=4, ls=0), '0L': Sizage(hs=2, ss=0, fs=8, ls=0), '0M': Sizage(hs=2, ss=0, fs=8, ls=0), + '0N': Sizage(hs=2, ss=0, fs=12, ls=0), '1AAA': Sizage(hs=4, ss=0, fs=48, ls=0), '1AAB': Sizage(hs=4, ss=0, fs=48, ls=0), '1AAC': Sizage(hs=4, ss=0, fs=80, ls=0), diff --git a/src/keri/core/counting.py b/src/keri/core/counting.py index b49afba17..c000f1693 100644 --- a/src/keri/core/counting.py +++ b/src/keri/core/counting.py @@ -279,9 +279,10 @@ class Counter: The two versions, CESR Genus and Protocol Stack, may be synchronized in the following way: - * Major versions must match. + * Major versions must match or be compatible - * Minor versions may differ. + * Minor versions may differ but must be compatible within a + major version. Importantly the CESR code table version may not be included in the message body itself but only provided in the surrounding CESR stream. @@ -290,10 +291,13 @@ class Counter: primitives and groups must be protected from a CESR code table genus version malleability attack. - Because the major versions of the CESR code table and protocol stack - must match, the signed embedded protocol stack major version protects + When the major versions of the CESR code table and protocol stack + match, the signed embedded protocol stack major version protects the receiver from a major version malleability attack on the CESR - code table. + code table. Otherwise the major versions must be compatible in a way + that does not allow malleability. For example the set of allowed codes + for a given message protocol version are compatible across CESR code + table major versions. This, however, does not protect the receiver of a message body from a minor version malleability attack on the CESR code table. diff --git a/src/keri/core/serdering.py b/src/keri/core/serdering.py index 7fef3761d..bfdf73727 100644 --- a/src/keri/core/serdering.py +++ b/src/keri/core/serdering.py @@ -272,7 +272,7 @@ class Serder: #override in subclass to enforce specific protocol Protocol = None # required protocol, None means any in Protos is ok - Proto = Protos.keri # default CESR protocol type + Proto = Protos.keri # default CESR protocol type for makify on base Serder Vrsn = Vrsn_1_0 # default protocol version for protocol type Kind = Serials.json # default serialization kind @@ -1074,7 +1074,7 @@ def dumps(sad, kind=Serials.json): @classmethod - def _dumps(clas, sad, protocol, version, gversion=Vrsn_2_0): + def _dumps(clas, sad, protocol, version, cversion=Vrsn_2_0): """CESR native serialization of sad Returns: @@ -1085,7 +1085,19 @@ def _dumps(clas, sad, protocol, version, gversion=Vrsn_2_0): sad (dict | list)): serializable dict or list to serialize protocol (str): message protocol version (Versionage): message protocol version - gversion (Versionage): CESR code table genus version + cversion (Versionage): CESR code table genus version + + Versioning: + CESR native serialization includes message protocol, protocol version + and CESR (genus) version. Assumes genus is compatible with message + protocol so genus is not needed. Protects from malleability attack + and ensure compatible cesr codes especially count (group) codes. + Primitive codes are less problematic since so far all primitive codes + tables are backwards compatible across major versions. + + 0NPPPPMmmMmm (12 B64 characters) + + """ fixed = True # True = use fixed field, False= use field map @@ -1145,7 +1157,7 @@ def _dumps(clas, sad, protocol, version, gversion=Vrsn_2_0): val = bytearray(Counter(tag=AllTags.GenericListGroup, count=len(frame) % 4, - version=gversion).qb64b) + version=cversion).qb64b) val.extend(frame) case "c": # list of config traits strings @@ -1156,7 +1168,7 @@ def _dumps(clas, sad, protocol, version, gversion=Vrsn_2_0): val = bytearray(Counter(tag=AllTags.GenericListGroup, count=len(frame) % 4, - version=gversion).qb64b) + version=cversion).qb64b) val.extend(frame) case "a": # list of seals or field map of attributes @@ -1166,7 +1178,7 @@ def _dumps(clas, sad, protocol, version, gversion=Vrsn_2_0): pass val = bytearray(Counter(tag=AllTags.GenericMapGroup, count=len(frame) % 4, - version=gversion).qb64b) + version=cversion).qb64b) else: for e in v: # list pass @@ -1174,7 +1186,7 @@ def _dumps(clas, sad, protocol, version, gversion=Vrsn_2_0): val = bytearray(Counter(tag=AllTags.GenericListGroup, count=len(frame) % 4, - version=gversion).qb64b) + version=cversion).qb64b) val.extend(frame) diff --git a/tests/core/test_coring.py b/tests/core/test_coring.py index 51327e60d..14810b58a 100644 --- a/tests/core/test_coring.py +++ b/tests/core/test_coring.py @@ -75,91 +75,93 @@ def test_matter(): """ Test Matter class """ - assert dataclasses.asdict(MtrDex) == { - 'Ed25519_Seed': 'A', - 'Ed25519N': 'B', - 'X25519': 'C', - 'Ed25519': 'D', - 'Blake3_256': 'E', - 'Blake2b_256': 'F', - 'Blake2s_256': 'G', - 'SHA3_256': 'H', - 'SHA2_256': 'I', - 'ECDSA_256k1_Seed': 'J', - 'Ed448_Seed': 'K', - 'X448': 'L', - 'Short': 'M', - 'Big': 'N', - 'X25519_Private': 'O', - 'X25519_Cipher_Seed': 'P', - 'ECDSA_256r1_Seed': 'Q', - 'Tall': 'R', - 'Large': 'S', - 'Great': 'T', - 'Vast': 'U', - 'Label1': 'V', - 'Label2': 'W', - 'Tag3': 'X', - 'Tag7': 'Y', - 'Blind': 'Z', - 'Salt_128': '0A', - 'Ed25519_Sig': '0B', - 'ECDSA_256k1_Sig': '0C', - 'Blake3_512': '0D', - 'Blake2b_512': '0E', - 'SHA3_512': '0F', - 'SHA2_512': '0G', - 'Long': '0H', - 'ECDSA_256r1_Sig': '0I', - 'Tag1': '0J', - 'Tag2': '0K', - 'Tag5': '0L', - 'Tag6': '0M', - 'ECDSA_256k1N': '1AAA', - 'ECDSA_256k1': '1AAB', - 'Ed448N': '1AAC', - 'Ed448': '1AAD', - 'Ed448_Sig': '1AAE', - 'Tag4': '1AAF', - 'DateTime': '1AAG', - 'X25519_Cipher_Salt': '1AAH', - 'ECDSA_256r1N': '1AAI', - 'ECDSA_256r1': '1AAJ', - 'Null': '1AAK', - 'Yes': '1AAL', - 'No': '1AAM', - 'TBD1': '2AAA', - 'TBD2': '3AAA', - 'StrB64_L0': '4A', - 'StrB64_L1': '5A', - 'StrB64_L2': '6A', - 'StrB64_Big_L0': '7AAA', - 'StrB64_Big_L1': '8AAA', - 'StrB64_Big_L2': '9AAA', - 'Bytes_L0': '4B', - 'Bytes_L1': '5B', - 'Bytes_L2': '6B', - 'Bytes_Big_L0': '7AAB', - 'Bytes_Big_L1': '8AAB', - 'Bytes_Big_L2': '9AAB', - 'X25519_Cipher_L0': '4C', - 'X25519_Cipher_L1': '5C', - 'X25519_Cipher_L2': '6C', - 'X25519_Cipher_Big_L0': '7AAC', - 'X25519_Cipher_Big_L1': '8AAC', - 'X25519_Cipher_Big_L2': '9AAC', - 'X25519_Cipher_QB64_L0': '4D', - 'X25519_Cipher_QB64_L1': '5D', - 'X25519_Cipher_QB64_L2': '6D', - 'X25519_Cipher_QB64_Big_L0': '7AAD', - 'X25519_Cipher_QB64_Big_L1': '8AAD', - 'X25519_Cipher_QB64_Big_L2': '9AAD', - 'X25519_Cipher_QB2_L0': '4D', - 'X25519_Cipher_QB2_L1': '5D', - 'X25519_Cipher_QB2_L2': '6D', - 'X25519_Cipher_QB2_Big_L0': '7AAD', - 'X25519_Cipher_QB2_Big_L1': '8AAD', - 'X25519_Cipher_QB2_Big_L2': '9AAD' + assert dataclasses.asdict(MtrDex) == \ + { + 'Ed25519_Seed': 'A', + 'Ed25519N': 'B', + 'X25519': 'C', + 'Ed25519': 'D', + 'Blake3_256': 'E', + 'Blake2b_256': 'F', + 'Blake2s_256': 'G', + 'SHA3_256': 'H', + 'SHA2_256': 'I', + 'ECDSA_256k1_Seed': 'J', + 'Ed448_Seed': 'K', + 'X448': 'L', + 'Short': 'M', + 'Big': 'N', + 'X25519_Private': 'O', + 'X25519_Cipher_Seed': 'P', + 'ECDSA_256r1_Seed': 'Q', + 'Tall': 'R', + 'Large': 'S', + 'Great': 'T', + 'Vast': 'U', + 'Label1': 'V', + 'Label2': 'W', + 'Tag3': 'X', + 'Tag7': 'Y', + 'Blind': 'Z', + 'Salt_128': '0A', + 'Ed25519_Sig': '0B', + 'ECDSA_256k1_Sig': '0C', + 'Blake3_512': '0D', + 'Blake2b_512': '0E', + 'SHA3_512': '0F', + 'SHA2_512': '0G', + 'Long': '0H', + 'ECDSA_256r1_Sig': '0I', + 'Tag1': '0J', + 'Tag2': '0K', + 'Tag5': '0L', + 'Tag6': '0M', + 'Tag10': '0N', + 'ECDSA_256k1N': '1AAA', + 'ECDSA_256k1': '1AAB', + 'Ed448N': '1AAC', + 'Ed448': '1AAD', + 'Ed448_Sig': '1AAE', + 'Tag4': '1AAF', + 'DateTime': '1AAG', + 'X25519_Cipher_Salt': '1AAH', + 'ECDSA_256r1N': '1AAI', + 'ECDSA_256r1': '1AAJ', + 'Null': '1AAK', + 'Yes': '1AAL', + 'No': '1AAM', + 'TBD1': '2AAA', + 'TBD2': '3AAA', + 'StrB64_L0': '4A', + 'StrB64_L1': '5A', + 'StrB64_L2': '6A', + 'StrB64_Big_L0': '7AAA', + 'StrB64_Big_L1': '8AAA', + 'StrB64_Big_L2': '9AAA', + 'Bytes_L0': '4B', + 'Bytes_L1': '5B', + 'Bytes_L2': '6B', + 'Bytes_Big_L0': '7AAB', + 'Bytes_Big_L1': '8AAB', + 'Bytes_Big_L2': '9AAB', + 'X25519_Cipher_L0': '4C', + 'X25519_Cipher_L1': '5C', + 'X25519_Cipher_L2': '6C', + 'X25519_Cipher_Big_L0': '7AAC', + 'X25519_Cipher_Big_L1': '8AAC', + 'X25519_Cipher_Big_L2': '9AAC', + 'X25519_Cipher_QB64_L0': '4D', + 'X25519_Cipher_QB64_L1': '5D', + 'X25519_Cipher_QB64_L2': '6D', + 'X25519_Cipher_QB64_Big_L0': '7AAD', + 'X25519_Cipher_QB64_Big_L1': '8AAD', + 'X25519_Cipher_QB64_Big_L2': '9AAD', + 'X25519_Cipher_QB2_L0': '4D', + 'X25519_Cipher_QB2_L1': '5D', + 'X25519_Cipher_QB2_L2': '6D', + 'X25519_Cipher_QB2_Big_L0': '7AAD', + 'X25519_Cipher_QB2_Big_L1': '8AAD', + 'X25519_Cipher_QB2_Big_L2': '9AAD' } @@ -218,6 +220,7 @@ def test_matter(): '0K': Sizage(hs=2, ss=0, fs=4, ls=0), '0L': Sizage(hs=2, ss=0, fs=8, ls=0), '0M': Sizage(hs=2, ss=0, fs=8, ls=0), + '0N': Sizage(hs=2, ss=0, fs=12, ls=0), '1AAA': Sizage(hs=4, ss=0, fs=48, ls=0), '1AAB': Sizage(hs=4, ss=0, fs=48, ls=0), '1AAC': Sizage(hs=4, ss=0, fs=80, ls=0), @@ -6470,7 +6473,7 @@ def test_tholder(): if __name__ == "__main__": - #test_matter() + test_matter() test_texter() #test_counter() #test_prodex()