Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions src/hio/core/memo/memoing.py
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,49 @@ def _encodeQVK(cls, raw, code='B'):
return qb64 # qualified base64 verkey


@classmethod
def _decodeQVK(cls, qb64):
"""Utility method for use with signed headers that decodes qualified
base64 verkey to raw domain bytes from CESR compatible text code

Parameters:
qb64 (str): qualified base64 verkey to be decoded with code
code (str): code for type of raw verkey CESR compatible
Ed25519N: str = 'B' # Ed25519 verkey non-transferable, basic derivation.

Returns:
tuple(raw, code) where:
raw (bytes): verkey suitable for crypto operations
code (str): CESR compatible code from qb64
"""
cz = 1 # only support qb64 length 44
code = qb64[:cz]
if code not in ('B'):
raise hioing.MemoerError(f"Invalid qvk {code=}")

qz = len(qb64) # text size
if qz != 44:
raise hioing.MemoerError(f"Invalid qvk text size {qz=} not 44")

cz = len(code)
pz = cz % 4 # net pad size given cz
if cz != pz != 1: # special case here for now we only accept cz=1
raise hioing.MemoerError(f"Invalid {cz=} not equal {pz=} not equal 1")

base = pz * b'A' + qb64[cz:].encode() # strip code from b64 and prepad pz 'A's
paw = decodeB64(base) # now should have pz leading sextexts of zeros
raw = paw[pz:] # remove prepad midpad bytes to invert back to raw
# ensure midpad bytes are zero
pi = int.from_bytes(paw[:pz], "big")
if pi != 0:
raise hioing.MemoerError(f"Nonzero midpad bytes=0x{pi:0{(pz)*2}x}.")

if len(raw) != ((qz - cz) * 3 // 4): # exact lengths
raise hioing.MemoerError(f"Improperly qualified material = {qss}")

return raw, code


@classmethod
def _encodeQSS(cls, raw, code='A'):
"""Utility method for use with signed headers that encodes raw sigseed as
Expand Down
7 changes: 7 additions & 0 deletions tests/core/memo/test_memoing.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,13 @@ def test_memoer_class():
_, _, oz, _, _, _ = Memoer.Sizes[SGDex.Signed] # cz mz oz nz sz hz
assert len(oid) == 44 == oz

qvk = Memoer._encodeQVK(raw=verkey)
assert qvk == 'BG-R9L4kTXULe33Tqidn0c-W-x6xU4lIXCdhZQYrsih2'
raw, code = Memoer._decodeQVK(oid)
assert raw == verkey
assert code == 'B'
assert len(qvk) == 44

sigseed = (b"\x9bF\n\xf1\xc2L\xeaBC:\xf7\xe9\xd71\xbc\xd2{\x7f\x81\xae5\x9c\xca\xf9\xdb\xac@`'\x0e\xa4\x10")
qss = Memoer._encodeQSS(raw=sigseed)
assert qss == 'AJtGCvHCTOpCQzr36dcxvNJ7f4GuNZzK-dusQGAnDqQQ'
Expand Down