56 lines
2.1 KiB
Python
56 lines
2.1 KiB
Python
from hashlib import sha3_256
|
|
from typing import Union
|
|
|
|
from nacl.signing import SigningKey, VerifyKey
|
|
from nacl.exceptions import BadSignatureError
|
|
from kasten import generator, Kasten
|
|
from kasten.exceptions import InvalidID
|
|
from kasten.types import KastenPacked, KastenChecksum
|
|
|
|
from onionrblocks.customtypes import RawEd25519PrivateKey, RawEd25519PublicKey
|
|
|
|
class Signed(generator.KastenBaseGenerator):
|
|
|
|
@classmethod
|
|
def generate(
|
|
cls,
|
|
packed_bytes: KastenPacked,
|
|
signingKey: Union[SigningKey, RawEd25519PrivateKey]
|
|
) -> Kasten:
|
|
"""Sign a digest of packed bytes, return a Kasten instance of it."""
|
|
# Use libsodium/pynacl (ed25519)
|
|
hashed = sha3_256(packed_bytes).digest()
|
|
try:
|
|
signed = signingKey.sign(hashed)
|
|
except AttributeError:
|
|
signingKey = SigningKey(signingKey)
|
|
signed = signingKey.sign(hashed)
|
|
# The KastenChecksum will be 64 bytes message then 32 bytes of the hash
|
|
# This can be fed right back into VerifyKey without splitting up
|
|
return Kasten(signed, packed_bytes, None,
|
|
auto_check_generator=False)
|
|
|
|
|
|
@staticmethod
|
|
def validate_id(
|
|
hash: KastenChecksum,
|
|
packed_bytes: KastenPacked,
|
|
verify_key: Union[VerifyKey, RawEd25519PublicKey]) -> None:
|
|
# Hash is 64 bytes message then 32 bytes of the hash of the packed_bytes
|
|
if len(hash) != 86:
|
|
raise InvalidID("Block not have proper signature length")
|
|
actual_hash = sha3_256(packed_bytes).digest()
|
|
if not isinstance(verify_key, VerifyKey):
|
|
verify_key = VerifyKey(verify_key)
|
|
|
|
# Ensure that the digest is correct
|
|
# Done in addition of the signature bc the sha3 can still ID blocks
|
|
# and to prevent swapping sigs
|
|
if actual_hash != hash[64:]:
|
|
raise InvalidID("Invalid sha3_256 digest")
|
|
# Ensure that the signature is correct
|
|
try:
|
|
verify_key.verify(hash)
|
|
except BadSignatureError as e:
|
|
raise InvalidID(repr(e))
|