diff --git a/hypercore_crypto/__init__.py b/hypercore_crypto/__init__.py index 87fe1a8..89b29d3 100644 --- a/hypercore_crypto/__init__.py +++ b/hypercore_crypto/__init__.py @@ -1,10 +1,16 @@ """hypercore-crypto module.""" +# Note(decentral1se): Included to match export list of the original Javascript +# reference implementation. However, we don't implement this function +# ourselves. +from nacl.hash import blake2b # noqa + from hypercore_crypto.crypto import ( # noqa blake2b, data, discovery_key, encode_unsigned_int64, + key_pair, leaf, parent, random_bytes, diff --git a/hypercore_crypto/crypto.py b/hypercore_crypto/crypto.py index 0862b83..3ab3e01 100644 --- a/hypercore_crypto/crypto.py +++ b/hypercore_crypto/crypto.py @@ -1,11 +1,15 @@ """Cryptography primitives for Hypercore.""" +from typing import Optional, Tuple + +import nacl.exceptions from nacl.bindings import ( + crypto_sign, crypto_sign_keypair, - crypto_sign_PUBLICKEYBYTES, - crypto_sign_SECRETKEYBYTES, crypto_sign_seed_keypair, ) +from nacl.hash import blake2b +from nacl.signing import VerifyKey # https://en.wikipedia.org/wiki/Merkle_tree#Second_preimage_attack LEAF_TYPE = bytearray([0]) @@ -14,30 +18,31 @@ ROOT_TYPE = bytearray([2]) HYPERCORE = bytearray('hypercore', encoding='utf-8') -# TODO(decentral1se): don't forget to type this -def key_pair(seed=None): - """The signed public/secret key length.""" - - public_key = bytearray(crypto_sign_PUBLICKEYBYTES) - secret_key = bytearray(crypto_sign_SECRETKEYBYTES) +def key_pair(seed: Optional[bytes] = None) -> Tuple[bytes, bytes]: + """A new public key and secret key pair. + The seed must be at least 32 characters in length. + """ if seed: - crypto_sign_seed_keypair(public_key, secret_key, seed) - else: - crypto_sign_keypair(public_key, secret_key) - - return {'public-key': public_key, 'secret-key': secret_key} + return crypto_sign_seed_keypair(seed) + return crypto_sign_keypair() -def sign(): - pass +def sign(message: bytes, secret_key: bytes) -> bytes: + """Signed message from a secret key.""" + return crypto_sign(message, secret_key) -def verify(): - pass +def verify(signed_message: bytes, signature: bytes, public_key: bytes) -> bool: + """Verify a signed message.""" + try: + VerifyKey(public_key).verify(signed_message, signature=signature) + except (nacl.exceptions.TypeError, nacl.exceptions.BadSignatureError): + return False + return True -def data(): +def data(data: bytes): pass @@ -63,7 +68,3 @@ def discovery_key(): def encode_unsigned_int64(): pass - - -def blake2b(): - pass diff --git a/test/test_crypto.py b/test/test_crypto.py new file mode 100644 index 0000000..18bd364 --- /dev/null +++ b/test/test_crypto.py @@ -0,0 +1,9 @@ +"""Cryptography primitives test module.""" + +from hypercore_crypto import key_pair + + +def test_key_pair_length(): + public_key, secret_key = key_pair() + assert len(public_key) == 32 + assert len(secret_key) == 64