From 6a280a279a2bcb63ff0294f4a3e8fad9debdd00c Mon Sep 17 00:00:00 2001 From: matejcik Date: Wed, 31 Jan 2024 12:14:19 +0100 Subject: [PATCH] feat(python): add cosi.sign_with_privkeys we've had multiple copies of this function all over the codebase, it's time to move it where it belongs --- core/tools/headertool.py | 24 +----------------------- python/src/trezorlib/cosi.py | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/core/tools/headertool.py b/core/tools/headertool.py index b745471e1..e8656d844 100755 --- a/core/tools/headertool.py +++ b/core/tools/headertool.py @@ -9,28 +9,6 @@ from typing import List, Sequence, Tuple # =========================== signing ========================= -def sign_with_privkeys(digest: bytes, privkeys: Sequence[bytes]) -> bytes: - """Locally produce a CoSi signature.""" - pubkeys = [cosi.pubkey_from_privkey(sk) for sk in privkeys] - nonces = [cosi.get_nonce(sk, digest, i) for i, sk in enumerate(privkeys)] - - global_pk = cosi.combine_keys(pubkeys) - global_R = cosi.combine_keys(R for r, R in nonces) - - sigs = [ - cosi.sign_with_privkey(digest, sk, global_pk, r, global_R) - for sk, (r, R) in zip(privkeys, nonces) - ] - - signature = cosi.combine_sig(global_R, sigs) - try: - cosi.verify_combined(signature, digest, global_pk) - except Exception as e: - raise click.ClickException("Failed to produce valid signature.") from e - - return signature - - def parse_privkey_args(privkey_data: List[str]) -> Tuple[int, List[bytes]]: privkeys = [] sigmask = 0 @@ -182,7 +160,7 @@ def cli( if privkeys: echo("Signing with local private keys...", err=True) - signature = sign_with_privkeys(digest, privkeys) + signature = cosi.sign_with_privkeys(digest, privkeys) if insert_signature: echo("Inserting external signature...", err=True) diff --git a/python/src/trezorlib/cosi.py b/python/src/trezorlib/cosi.py index 0501abdec..c9ed57f0b 100644 --- a/python/src/trezorlib/cosi.py +++ b/python/src/trezorlib/cosi.py @@ -138,6 +138,22 @@ def sign_with_privkey( return Ed25519Signature(_ed25519.encodeint(S)) +def sign_with_privkeys(digest: bytes, privkeys: Sequence[bytes]) -> bytes: + """Locally produce a CoSi signature from a list of private keys.""" + pubkeys = [pubkey_from_privkey(sk) for sk in privkeys] + nonces = [get_nonce(sk, digest, i) for i, sk in enumerate(privkeys)] + + global_pk = combine_keys(pubkeys) + global_R = combine_keys(R for _, R in nonces) + + sigs = [ + sign_with_privkey(digest, sk, global_pk, r, global_R) + for sk, (r, _) in zip(privkeys, nonces) + ] + + return combine_sig(global_R, sigs) + + # ====== Client functions ====== #