From 317eb4524bfcbe9ea5ee739e1ad938b137d78b86 Mon Sep 17 00:00:00 2001 From: Aareon Sullivan Date: Thu, 28 Apr 2022 22:04:10 -0700 Subject: [PATCH 1/3] Create dtnb.py --- python/dtnb.py | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 python/dtnb.py diff --git a/python/dtnb.py b/python/dtnb.py new file mode 100644 index 0000000..7125a2d --- /dev/null +++ b/python/dtnb.py @@ -0,0 +1,94 @@ +from typing import Sequence + +from dataclasses import dataclass +from nacl.encoding import HexEncoder +from nacl.signing import SigningKey, VerifyKey + + +@dataclass +class Signature(bytes): + data: Sequence[bytes] + + def bytes(self): + """ 64-byte sequence signature """ + return self.data + + def hex(self): + """ Returns the signature as a hex string """ + return HexEncoder.encode(self.bytes()) + + @classmethod + def new(cls, _bytes): + """ Creates a new signature with the given bytes (length 64) """ + if len(_bytes) != 64: + raise Exception(f"Expected length of bytes to be 64 but got {len(_bytes)}") + + cls.data = _bytes + return cls() + + def verify(self, public_key: Sequence[bytes], message: Sequence[bytes]) -> bool: + vk = VerifyKey(public_key) + return vk.verify(message, self.bytes()) + + +@dataclass +class Wallet: + public_key: Sequence[bytes] + private_key: Sequence[bytes] + + @classmethod + def from_bytes(cls, pub: Sequence[bytes], priv: Sequence[bytes]): + if len(pub) != 32: + raise Exception(f"Expected public key to be 32 bytes long not {len(pub)}") + if len(priv) != 32: + raise Exception(f"Expected private key to be 32 bytes long not {len(priv)}") + cls.public_key = pub + cls.private_key = priv + return cls() + + @classmethod + def from_hex(cls, pub: str, priv: str): + try: + pub_bytes = HexEncoder.decode(pub) + priv_bytes = HexEncoder.decode(priv) + except: + raise + cls.public_key = pub_bytes + cls.private_key = priv_bytes + return cls() + + @classmethod + def from_private_bytes(cls, priv: Sequence[bytes]): + if len(priv) != 32: + raise Exception(f"Expected private key to be 32 bytes long not {len(priv)}") + key = SigningKey(priv, encoder=HexEncoder) + cls.public_key = key[32:] + cls.private_key = key[:32] + return cls() + + @classmethod + def from_private_hex(cls, priv: str): + try: + priv_bytes = HexEncoder.decode(priv) + except: + raise + return cls.from_private_bytes(priv_bytes) + + @classmethod + def generate(cls): + priv = SigningKey.generate() + cls.public_key = cls.private_key.verify_key.encode(encoder=HexEncoder) + cls.private_key = priv[:32] + return cls() + + @property + def private_key_hex(self): + return HexEncoder(self.private_key) + + @property + def public_key_hex(self): + return HexEncoder(self.public_key) + + def sign(self, message: Sequence[bytes]) -> Signature: + full_priv = self.private_key.append(self.public_key) + return Signature(SigningKey(full_priv, encoder=HexEncoder), message) From bc53cc72aeaf03583868e7955d7ca3c7a8fef9d2 Mon Sep 17 00:00:00 2001 From: Aareon Sullivan Date: Fri, 29 Apr 2022 09:22:13 -0700 Subject: [PATCH 2/3] Create dtnb_test.py --- python/dtnb_test.py | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 python/dtnb_test.py diff --git a/python/dtnb_test.py b/python/dtnb_test.py new file mode 100644 index 0000000..5aa8361 --- /dev/null +++ b/python/dtnb_test.py @@ -0,0 +1,39 @@ +from typing import Annotated, Sequence +from dtnb import Wallet + + +class DemoKeys: + private_hex: str + public_hex: str + signature_mocks: Annotated[Sequence[bytes], 2] # list of 2 items containing message and signature + + def __init__(self, priv: str, pub: str, signature: Annotated[Sequence[bytes], 2]): + self.private_hex = priv + self.public_hex = pub + self.signature_mocks = signature + + +def demo_keys(): + return ( + DemoKeys( + "80811257e5bc79976cba8fd689efe737947caf4e2a741ca11edb601ae3ab654d", + "4c41c0f516401d8ac975eae151bd6fda312cc81e5ce412f041373996a48cf762", + ["HELLO, WORLD!", "5e9544bef0046166f15353a0298f41fc7791f1d66203cea659422b6e1a7f12737cffcb5fd71dac1d8f631703a09e9fd03210a6748af5e61cf1c1c3453060760b"] + ), + DemoKeys("5a9299a36b91c82918fa5b3d4ea5144cc588c20e66aadb44812d4f2eac953a76", "4299a3508b6207a560143a87dbefc9273e13487f49fc79b31e22a02330947141", ["HELLO, WORLD!", + "307d9fa244cf0a38bba092588a90dcd03cee190214fdc2362c3d0c14b8d768b36fc36716915747642f6144b0171fe95c56034dd203e7191bc4b2012dbbbefe02"] + ), + DemoKeys("09645e081d7d9e3bc01ec94081cf4048244ecf4dc8098b4b0a8275cee07003aa", "1c25ff99a7fded3d632146616fd58c3a32b4cc683e04cfc53d8bbc5e59ef38ce", + ["HELLO, WORLD!", "b355dd1fd6b1ba6cd529c10a6a6a732ca6eb8417d12fbf29344cdc5425dc4cc1a24efc9db04f9530a18150be0ba9d5844e4da0be87e6e19d224b9670da13d007"] + ) + ) + + +def test_creating_wallets_from_keys(): + for dk in demo_keys(): + wallet = Wallet.from_hex(dk.public_hex, dk.private_hex) + + +if __name__ == "__main__": + + test_creating_wallets_from_keys() From 89b3d2e0095ce13980f5ea27641099edcd900a00 Mon Sep 17 00:00:00 2001 From: Aareon Sullivan Date: Fri, 29 Apr 2022 09:23:04 -0700 Subject: [PATCH 3/3] Fix HexEncoder usage --- python/dtnb.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/python/dtnb.py b/python/dtnb.py index 7125a2d..92641ca 100644 --- a/python/dtnb.py +++ b/python/dtnb.py @@ -53,9 +53,7 @@ def from_hex(cls, pub: str, priv: str): priv_bytes = HexEncoder.decode(priv) except: raise - cls.public_key = pub_bytes - cls.private_key = priv_bytes - return cls() + return cls(pub_bytes, priv_bytes) @classmethod def from_private_bytes(cls, priv: Sequence[bytes]): @@ -83,11 +81,11 @@ def generate(cls): @property def private_key_hex(self): - return HexEncoder(self.private_key) + return HexEncoder.encode(self.private_key) @property def public_key_hex(self): - return HexEncoder(self.public_key) + return HexEncoder.encode(self.public_key) def sign(self, message: Sequence[bytes]) -> Signature: full_priv = self.private_key.append(self.public_key)