From 108a27434762fa29979da25aba4005c4a241b38e Mon Sep 17 00:00:00 2001 From: Samuel M Smith Date: Sat, 3 Aug 2024 14:13:20 -0600 Subject: [PATCH] Refactored Encrypter to support all cipher codes. Need units tests --- src/keri/app/keeping.py | 8 +++-- src/keri/core/signing.py | 65 ++++++++++++++++++++++++++++---------- tests/core/test_signing.py | 8 ++--- 3 files changed, 58 insertions(+), 23 deletions(-) diff --git a/src/keri/app/keeping.py b/src/keri/app/keeping.py index 6949d748..b1d2f108 100644 --- a/src/keri/app/keeping.py +++ b/src/keri/app/keeping.py @@ -902,7 +902,7 @@ def salt(self, salt): may be plain text or cipher text handled by updateAeid """ if self.encrypter: - salt = self.encrypter.encrypt(ser=salt).qb64 + salt = self.encrypter.encrypt(ser=salt, code=core.MtrDex.X25519_Cipher_Salt).qb64 self.ks.gbls.pin('salt', salt) @@ -1020,7 +1020,8 @@ def incept(self, icodes=None, icount=1, icode=coring.MtrDex.Ed25519_Seed, if creator.salt: pp.salt = (creator.salt if not self.encrypter - else self.encrypter.encrypt(ser=creator.salt).qb64) + else self.encrypter.encrypt(ser=creator.salt, + code=core.MtrDex.X25519_Cipher_Salt).qb64) dt = helping.nowIso8601() ps = PreSit( @@ -1543,7 +1544,8 @@ def ingest(self, secrecies, iridx=0, ncount=1, ncode=coring.MtrDex.Ed25519_Seed, pp = PrePrm(pidx=pidx, algo=algo, salt=(creator.salt if not self.encrypter - else self.encrypter.encrypt(ser=creator.salt).qb64), + else self.encrypter.encrypt(ser=creator.salt, + code=core.MtrDex.X25519_Cipher_Salt).qb64), stem=creator.stem, tier=creator.tier) pre = csigners[0].verfer.qb64b diff --git a/src/keri/core/signing.py b/src/keri/core/signing.py index e448bcbc..3df201ec 100644 --- a/src/keri/core/signing.py +++ b/src/keri/core/signing.py @@ -12,7 +12,8 @@ from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat from cryptography.hazmat.primitives.asymmetric import ec, utils -from ..kering import (EmptyMaterialError, InvalidCodeError, InvalidSizeError) +from ..kering import (EmptyMaterialError, InvalidCodeError, InvalidSizeError, + InvalidValueError) from ..help import helping @@ -766,8 +767,8 @@ def __init__(self, raw=None, code=MtrDex.X25519, verkey=None, **kwa): if not raw and verkey: verfer = Verfer(qb64b=verkey) if verfer.code not in (MtrDex.Ed25519N, MtrDex.Ed25519): - raise ValueError("Unsupported verkey derivation code = {}." - "".format(verfer.code)) + raise InvalidValueError(f"Unsupported verkey derivation code =" + f" {verfer.code}.") # convert signing public key to encryption public key raw = pysodium.crypto_sign_pk_to_box_pk(verfer.raw) @@ -776,7 +777,7 @@ def __init__(self, raw=None, code=MtrDex.X25519, verkey=None, **kwa): if self.code == MtrDex.X25519: self._encrypt = self._x25519 else: - raise ValueError("Unsupported encrypter code = {}.".format(self.code)) + raise InvalidValueError(f"Unsupported encrypter code = {self.code}.") def verifySeed(self, seed): """ @@ -807,23 +808,55 @@ def encrypt(self, ser=None, prim=None, code=None): qb64 or qb2 is to be encrypted based on code code (str): code of plain text type for resultant encrypted cipher """ - if not (ser or prim): - raise EmptyMaterialError(f"Neither bar serialization or primitive " - f"are provided.") + if not ser: - if ser: - prim = Matter(qb64b=ser) + if not prim: + raise EmptyMaterialError(f"Neither bar serialization or primitive " + f"are provided.") - if prim.code == MtrDex.Salt_128: # future other salt codes - code = MtrDex.X25519_Cipher_Salt - elif prim.code == MtrDex.Ed25519_Seed: # future other seed codes - code = MtrDex.X25519_Cipher_Seed - else: - raise ValueError("Unsupported plain text code = {}.".format(prim.code)) + if not code: + if prim.code == MtrDex.Salt_128: # future other salt codes + code = MtrDex.X25519_Cipher_Salt + elif prim.code == MtrDex.Ed25519_Seed: # future other seed codes + code = MtrDex.X25519_Cipher_Seed + else: + raise InvalidValueError(f"Unsupported primitive with code =" + f" {prim.code} when cipher code is " + f"missing.") + + if code in CiXAllQB64Dex: + ser = prim.qb64b + elif code in CiXVarQB2Dex: + ser = prim.qb2 + else: + raise InvalidCodeError(f"Invalide primitive cipher {code=} not " + f"qb64 or qb2.") + + if not code: # assumes default is sniffable stream + code = CiXDex.X25519_Cipher_L0 + + if hasattr(ser, "encode"): + ser = ser.encode() # convert str to bytes + if not isinstance(ser, bytes): + ser = bytes(ser) # convert bytearray and memoryview to bytes + + #if not (ser or prim): + #raise EmptyMaterialError(f"Neither bar serialization or primitive " + #f"are provided.") + + #if ser: + #prim = Matter(qb64b=ser) + + #if prim.code == MtrDex.Salt_128: # future other salt codes + #code = MtrDex.X25519_Cipher_Salt + #elif prim.code == MtrDex.Ed25519_Seed: # future other seed codes + #code = MtrDex.X25519_Cipher_Seed + #else: + #raise ValueError("Unsupported plain text code = {}.".format(prim.code)) # encrypting fully qualified qb64 version of plain text ensures its # derivation code round trips through eventual decryption - return (self._encrypt(ser=prim.qb64b, pubkey=self.raw, code=code)) + return (self._encrypt(ser=ser, pubkey=self.raw, code=code)) @staticmethod def _x25519(ser, pubkey, code): diff --git a/tests/core/test_signing.py b/tests/core/test_signing.py index 9b8ec4d1..ef616b5a 100644 --- a/tests/core/test_signing.py +++ b/tests/core/test_signing.py @@ -779,12 +779,12 @@ def test_encrypter(): assert encrypter.raw == pubkey assert encrypter.verifySeed(seed=cryptsigner.qb64) - cipher = encrypter.encrypt(ser=seedqb64b) + cipher = encrypter.encrypt(ser=seedqb64b, code=MtrDex.X25519_Cipher_Seed) assert cipher.code == MtrDex.X25519_Cipher_Seed uncb = pysodium.crypto_box_seal_open(cipher.raw, encrypter.raw, prikey) assert uncb == seedqb64b - cipher = encrypter.encrypt(ser=saltqb64b) + cipher = encrypter.encrypt(ser=saltqb64b, code=MtrDex.X25519_Cipher_Salt) assert cipher.code == MtrDex.X25519_Cipher_Salt uncb = pysodium.crypto_box_seal_open(cipher.raw, encrypter.raw, prikey) assert uncb == saltqb64b @@ -857,7 +857,7 @@ def test_decrypter(): assert encrypter.raw == pubkey # create cipher of seed - seedcipher = encrypter.encrypt(ser=seedqb64b) + seedcipher = encrypter.encrypt(ser=seedqb64b, code=MtrDex.X25519_Cipher_Seed) assert seedcipher.code == MtrDex.X25519_Cipher_Seed # each encryption uses a nonce so not a stable representation for testing @@ -882,7 +882,7 @@ def test_decrypter(): assert signer.verfer.transferable # create cipher of salt - saltcipher = encrypter.encrypt(ser=saltqb64b) + saltcipher = encrypter.encrypt(ser=saltqb64b, code=MtrDex.X25519_Cipher_Salt) assert saltcipher.code == MtrDex.X25519_Cipher_Salt # each encryption uses a nonce so not a stable representation for testing