Rework to use pysodium, document and test further
Still on key_pair, sign and verify
This commit is contained in:
parent
1072d2662a
commit
c11909012a
@ -1,15 +1,8 @@
|
|||||||
"""hypercore-crypto module."""
|
"""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
|
from hypercore_crypto.crypto import ( # noqa
|
||||||
blake2b,
|
|
||||||
data,
|
data,
|
||||||
discovery_key,
|
discovery_key,
|
||||||
encode_unsigned_int64,
|
|
||||||
key_pair,
|
key_pair,
|
||||||
leaf,
|
leaf,
|
||||||
parent,
|
parent,
|
||||||
|
@ -2,14 +2,13 @@
|
|||||||
|
|
||||||
from typing import Optional, Tuple
|
from typing import Optional, Tuple
|
||||||
|
|
||||||
import nacl.exceptions
|
from pysodium import (
|
||||||
from nacl.bindings import (
|
crypto_sign_detached,
|
||||||
crypto_sign,
|
|
||||||
crypto_sign_keypair,
|
crypto_sign_keypair,
|
||||||
crypto_sign_seed_keypair,
|
crypto_sign_seed_keypair,
|
||||||
|
crypto_sign_SEEDBYTES,
|
||||||
|
crypto_sign_verify_detached,
|
||||||
)
|
)
|
||||||
from nacl.hash import blake2b
|
|
||||||
from nacl.signing import VerifyKey
|
|
||||||
|
|
||||||
# https://en.wikipedia.org/wiki/Merkle_tree#Second_preimage_attack
|
# https://en.wikipedia.org/wiki/Merkle_tree#Second_preimage_attack
|
||||||
LEAF_TYPE = bytearray([0])
|
LEAF_TYPE = bytearray([0])
|
||||||
@ -21,23 +20,35 @@ HYPERCORE = bytearray('hypercore', encoding='utf-8')
|
|||||||
def key_pair(seed: Optional[bytes] = None) -> Tuple[bytes, bytes]:
|
def key_pair(seed: Optional[bytes] = None) -> Tuple[bytes, bytes]:
|
||||||
"""A new public key and secret key pair.
|
"""A new public key and secret key pair.
|
||||||
|
|
||||||
The seed must be at least 32 characters in length.
|
:param seed: Seed value. Must be at least 32 characters in length
|
||||||
"""
|
"""
|
||||||
if seed:
|
if seed:
|
||||||
|
if len(seed) < crypto_sign_SEEDBYTES:
|
||||||
|
message = "'seed' argument must be of length > {}"
|
||||||
|
raise ValueError(message.format(crypto_sign_SEEDBYTES))
|
||||||
return crypto_sign_seed_keypair(seed)
|
return crypto_sign_seed_keypair(seed)
|
||||||
return crypto_sign_keypair()
|
return crypto_sign_keypair()
|
||||||
|
|
||||||
|
|
||||||
def sign(message: bytes, secret_key: bytes) -> bytes:
|
def sign(message: bytes, secret_key: bytes) -> bytes:
|
||||||
"""Signed message from a secret key."""
|
"""A message signature.
|
||||||
return crypto_sign(message, secret_key)
|
|
||||||
|
:param message: The message to be signed
|
||||||
|
:param secret_key: The secret key to use during signing
|
||||||
|
"""
|
||||||
|
return crypto_sign_detached(message, secret_key)
|
||||||
|
|
||||||
|
|
||||||
def verify(signed_message: bytes, signature: bytes, public_key: bytes) -> bool:
|
def verify(message: bytes, signature: bytes, public_key: bytes) -> bool:
|
||||||
"""Verify a signed message."""
|
"""Verify an unsigned message with accompanying signature.
|
||||||
|
|
||||||
|
:param message: The unsigned message to verify
|
||||||
|
:param signature: The signature to be verified
|
||||||
|
:param public_key: The public key to use during verifying
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
VerifyKey(public_key).verify(signed_message, signature=signature)
|
crypto_sign_verify_detached(signature, message, public_key)
|
||||||
except (nacl.exceptions.TypeError, nacl.exceptions.BadSignatureError):
|
except ValueError:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -64,7 +75,3 @@ def random_bytes():
|
|||||||
|
|
||||||
def discovery_key():
|
def discovery_key():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def encode_unsigned_int64():
|
|
||||||
pass
|
|
||||||
|
@ -43,7 +43,7 @@ package_dir =
|
|||||||
packages = find:
|
packages = find:
|
||||||
zip_safe = False
|
zip_safe = False
|
||||||
install_requires =
|
install_requires =
|
||||||
PyNaCl >= 1.3.0, < 2.0
|
pysodium >= 0.7.2, < 0.8
|
||||||
|
|
||||||
[options.packages.find]
|
[options.packages.find]
|
||||||
where = .
|
where = .
|
||||||
|
@ -1,9 +1,31 @@
|
|||||||
"""Cryptography primitives test module."""
|
"""Cryptography primitives test module."""
|
||||||
|
|
||||||
from hypercore_crypto import key_pair
|
import pytest
|
||||||
|
|
||||||
|
from hypercore_crypto import key_pair, sign, verify
|
||||||
|
from pysodium import crypto_sign_PUBLICKEYBYTES, crypto_sign_SECRETKEYBYTES
|
||||||
|
|
||||||
|
|
||||||
|
def test_key_pair_seed_length():
|
||||||
|
with pytest.raises(ValueError) as exception:
|
||||||
|
key_pair(b'wrong')
|
||||||
|
assert 'must be of length' in str(exception)
|
||||||
|
|
||||||
|
|
||||||
def test_key_pair_length():
|
def test_key_pair_length():
|
||||||
public_key, secret_key = key_pair()
|
public_key, secret_key = key_pair()
|
||||||
assert len(public_key) == 32
|
assert len(public_key) == crypto_sign_PUBLICKEYBYTES
|
||||||
assert len(secret_key) == 64
|
assert len(secret_key) == crypto_sign_SECRETKEYBYTES
|
||||||
|
|
||||||
|
|
||||||
|
def test_sign():
|
||||||
|
message = b'mymessage'
|
||||||
|
_, secret_key = key_pair()
|
||||||
|
assert message not in sign(message, secret_key)
|
||||||
|
|
||||||
|
|
||||||
|
def test_verify():
|
||||||
|
message = b'mymessage'
|
||||||
|
public_key, secret_key = key_pair()
|
||||||
|
signature = sign(message, secret_key)
|
||||||
|
assert verify(message, signature, public_key)
|
||||||
|
Loading…
Reference in New Issue
Block a user