def derive_keypair( cls: Type[ED25519], decoded_seed: bytes, is_validator: bool ) -> Tuple[str, str]: """ Derives a keypair. Args: decoded_seed: an ED25519 seed from which to derive keypair. is_validator: if True indicates that caller wishes to derive a validator keypair from this seed, however, that is always invalid for this algorithm and will cause this function to raise. Returns: A (private key, public key) derived from seed Raises: XRPLKeypairsException: If the keypair is a validator keypair. """ if is_validator: raise XRPLKeypairsException("validator keypairs cannot use ED25519") raw_private = sha512_first_half(decoded_seed) private = ECPrivateKey(int.from_bytes(raw_private, "big"), _CURVE) public = EDDSA.get_public_key(private, sha512) return ( cls._format_key(cls._public_key_to_str(public)), cls._format_key(cls._private_key_to_str(private)), )
def derive_keypair( cls: Type[ED25519], decoded_seed: bytes, is_validator: bool ) -> Tuple[str, str]: """ Derives a key pair in Ed25519 format for use with the XRP Ledger from a seed value. Args: decoded_seed: The Ed25519 seed to derive a key pair from, as bytes. is_validator: Whether to derive a validator keypair. However, validator signing keys cannot use Ed25519. (See `#3434 <https://github.com/ripple/rippled/issues/3434>`_ for more information.) Returns: A (public key, private key) pair derived from the given seed. Raises: XRPLKeypairsException: If the keypair is a validator keypair. """ if is_validator: raise XRPLKeypairsException("Validator key pairs cannot use Ed25519") raw_private = sha512_first_half(decoded_seed) private = ECPrivateKey(int.from_bytes(raw_private, "big"), _CURVE) public = EDDSA.get_public_key(private, sha512) return ( cls._format_key(cls._public_key_to_str(public)), cls._format_key(cls._private_key_to_str(private)), )
def is_valid_message(cls: Type[SECP256K1], message: bytes, signature: bytes, public_key: str) -> bool: """ Verifies that message matches signature given public_key. Args: message: The message to validate. signature: The signature of the message. public_key: The public_key to use to verify the message. Returns: Whether the message matches the signature given the public key. """ public_key_point = _CURVE.decode_point(bytes.fromhex(public_key)) wrapped_public = ECPublicKey(public_key_point) return cast( bool, _SIGNER.verify(sha512_first_half(message), signature, wrapped_public), )
def sign(cls: Type[SECP256K1], message: bytes, private_key: str) -> bytes: """ Signs message in SECP256k1 using the given private key. Args: message: The message to sign in SECP256k1. private_key: The private key to use to sign the message. Returns: The signed message. """ wrapped_private = ECPrivateKey(int(private_key, 16), _CURVE) return cast( bytes, _SIGNER.sign_rfc6979( sha512_first_half(message), wrapped_private, sha256, canonical=True, ), )
def _get_secret(cls: Type[SECP256K1], candidate_merger: Callable[[bytes], bytes]) -> bytes: """ Given a function `candidate_merger` that knows how to prepare a sequence candidate bytestring into a possible full candidate secret, returns the first sequence value that is valid. If none are valid, raises; however this should be so exceedingly rare as to ignore. """ for raw_root in range(_SEQUENCE_MAX): root = raw_root.to_bytes( _SEQUENCE_SIZE, byteorder="big", signed=False, ) candidate = sha512_first_half(candidate_merger(root)) if cls._is_secret_valid(candidate): return candidate raise XRPLKeypairsException( """Could not determine a key pair. This is extremely improbable. Please try again.""", )