1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-04-19 16:49:02 +00:00

refactor(core,crypto): rename sign() to sign_recoverable()

[no changelog]
This commit is contained in:
Ondřej Vejpustek 2025-03-21 14:25:22 +01:00
parent 8b4936926c
commit fe777474dd
21 changed files with 98 additions and 54 deletions

View File

@ -87,14 +87,14 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(
mod_trezorcrypto_nist256p1_publickey_obj, 1, 2,
mod_trezorcrypto_nist256p1_publickey);
/// def sign(
/// def sign_recoverable(
/// secret_key: bytes, digest: bytes, compressed: bool = True
/// ) -> bytes:
/// """
/// Uses secret key to produce the signature of the digest.
/// """
STATIC mp_obj_t mod_trezorcrypto_nist256p1_sign(size_t n_args,
const mp_obj_t *args) {
STATIC mp_obj_t mod_trezorcrypto_nist256p1_sign_recoverable(
size_t n_args, const mp_obj_t *args) {
mp_buffer_info_t sk = {0};
mp_buffer_info_t dig = {0};
mp_get_buffer_raise(args[0], &sk, MP_BUFFER_READ);
@ -118,9 +118,9 @@ STATIC mp_obj_t mod_trezorcrypto_nist256p1_sign(size_t n_args,
sig.buf[0] = 27 + pby + compressed * 4;
return mp_obj_new_str_from_vstr(&mp_type_bytes, &sig);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_nist256p1_sign_obj,
2, 3,
mod_trezorcrypto_nist256p1_sign);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(
mod_trezorcrypto_nist256p1_sign_recoverable_obj, 2, 3,
mod_trezorcrypto_nist256p1_sign_recoverable);
/// def verify(public_key: bytes, signature: bytes, digest: bytes) -> bool:
/// """
@ -225,8 +225,8 @@ STATIC const mp_rom_map_elem_t mod_trezorcrypto_nist256p1_globals_table[] = {
MP_ROM_PTR(&mod_trezorcrypto_nist256p1_generate_secret_obj)},
{MP_ROM_QSTR(MP_QSTR_publickey),
MP_ROM_PTR(&mod_trezorcrypto_nist256p1_publickey_obj)},
{MP_ROM_QSTR(MP_QSTR_sign),
MP_ROM_PTR(&mod_trezorcrypto_nist256p1_sign_obj)},
{MP_ROM_QSTR(MP_QSTR_sign_recoverable),
MP_ROM_PTR(&mod_trezorcrypto_nist256p1_sign_recoverable_obj)},
{MP_ROM_QSTR(MP_QSTR_verify),
MP_ROM_PTR(&mod_trezorcrypto_nist256p1_verify_obj)},
{MP_ROM_QSTR(MP_QSTR_verify_recover),

View File

@ -114,7 +114,7 @@ enum {
#endif
/// def sign(
/// def sign_recoverable(
/// secret_key: bytes,
/// digest: bytes,
/// compressed: bool = True,
@ -123,8 +123,8 @@ enum {
/// """
/// Uses secret key to produce the signature of the digest.
/// """
STATIC mp_obj_t mod_trezorcrypto_secp256k1_sign(size_t n_args,
const mp_obj_t *args) {
STATIC mp_obj_t mod_trezorcrypto_secp256k1_sign_recoverable(
size_t n_args, const mp_obj_t *args) {
mp_buffer_info_t sk = {0};
mp_buffer_info_t dig = {0};
mp_get_buffer_raise(args[0], &sk, MP_BUFFER_READ);
@ -160,9 +160,9 @@ STATIC mp_obj_t mod_trezorcrypto_secp256k1_sign(size_t n_args,
sig.buf[0] = 27 + pby + compressed * 4;
return mp_obj_new_str_from_vstr(&mp_type_bytes, &sig);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_secp256k1_sign_obj,
2, 4,
mod_trezorcrypto_secp256k1_sign);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(
mod_trezorcrypto_secp256k1_sign_recoverable_obj, 2, 4,
mod_trezorcrypto_secp256k1_sign_recoverable);
/// def verify(public_key: bytes, signature: bytes, digest: bytes) -> bool:
/// """
@ -267,8 +267,8 @@ STATIC const mp_rom_map_elem_t mod_trezorcrypto_secp256k1_globals_table[] = {
MP_ROM_PTR(&mod_trezorcrypto_secp256k1_generate_secret_obj)},
{MP_ROM_QSTR(MP_QSTR_publickey),
MP_ROM_PTR(&mod_trezorcrypto_secp256k1_publickey_obj)},
{MP_ROM_QSTR(MP_QSTR_sign),
MP_ROM_PTR(&mod_trezorcrypto_secp256k1_sign_obj)},
{MP_ROM_QSTR(MP_QSTR_sign_recoverable),
MP_ROM_PTR(&mod_trezorcrypto_secp256k1_sign_recoverable_obj)},
{MP_ROM_QSTR(MP_QSTR_verify),
MP_ROM_PTR(&mod_trezorcrypto_secp256k1_verify_obj)},
{MP_ROM_QSTR(MP_QSTR_verify_recover),

View File

@ -16,7 +16,7 @@ def publickey(secret_key: bytes, compressed: bool = True) -> bytes:
# upymod/modtrezorcrypto/modtrezorcrypto-nist256p1.h
def sign(
def sign_recoverable(
secret_key: bytes, digest: bytes, compressed: bool = True
) -> bytes:
"""

View File

@ -18,7 +18,7 @@ CANONICAL_SIG_EOS: int = 2
# upymod/modtrezorcrypto/modtrezorcrypto-secp256k1.h
def sign(
def sign_recoverable(
secret_key: bytes,
digest: bytes,
compressed: bool = True,

View File

@ -24,7 +24,7 @@ from .curve_benchmark import (
from .hash_benchmark import HashBenchmark
# This is a wrapper above the trezor.crypto.curve.ed25519 module that satisfies SignCurve protocol, the modules uses `message` instead of `digest` in `sign()` and `verify()`
# This is a wrapper above the trezor.crypto.curve.ed25519 module that satisfies SignCurve protocol, the wrapper maps `digest` to `message` in `sign()` and `verify()`
class Ed25519:
def __init__(self) -> None:
pass
@ -44,6 +44,48 @@ class Ed25519:
return ed25519.verify(public_key, signature, digest)
# This is a wrapper above the trezor.crypto.curve.secp256k1 module that satisfies SignCurve and MultiplyCurve protocol, the wrapper maps `sign()` to `sign_recoverable()`
class Secp256k1:
def __init__(self) -> None:
pass
def generate_secret(self) -> bytes:
return secp256k1.generate_secret()
def publickey(self, secret_key: bytes) -> bytes:
return secp256k1.publickey(secret_key)
def multiply(self, secret_key: bytes, public_key: bytes) -> bytes:
return secp256k1.multiply(secret_key, public_key)
def sign(self, secret_key: bytes, digest: bytes) -> bytes:
return secp256k1.sign_recoverable(secret_key, digest)
def verify(self, public_key: bytes, signature: bytes, digest: bytes) -> bool:
return secp256k1.verify(public_key, signature, digest)
# This is a wrapper above the trezor.crypto.curve.nist256p1 module that satisfies SignCurve and MultiplyCurve protocol, the wrapper maps `sign()` to `sign_recoverable()`
class Nist256p1:
def __init__(self) -> None:
pass
def generate_secret(self) -> bytes:
return nist256p1.generate_secret()
def publickey(self, secret_key: bytes) -> bytes:
return nist256p1.publickey(secret_key)
def multiply(self, secret_key: bytes, public_key: bytes) -> bytes:
return nist256p1.multiply(secret_key, public_key)
def sign(self, secret_key: bytes, digest: bytes) -> bytes:
return nist256p1.sign_recoverable(secret_key, digest)
def verify(self, public_key: bytes, signature: bytes, digest: bytes) -> bool:
return nist256p1.verify(public_key, signature, digest)
benchmarks = {
"crypto/hash/blake2b": HashBenchmark(lambda: blake2b()),
"crypto/hash/blake2s": HashBenchmark(lambda: blake2s()),
@ -79,17 +121,17 @@ benchmarks = {
"crypto/cipher/chacha20poly1305/decrypt": DecryptBenchmark(
lambda: chacha20poly1305(random_bytes(32), random_bytes(12)), 64
),
"crypto/curve/secp256k1/sign": SignBenchmark(secp256k1),
"crypto/curve/secp256k1/verify": VerifyBenchmark(secp256k1),
"crypto/curve/secp256k1/publickey": PublickeyBenchmark(secp256k1),
"crypto/curve/secp256k1/multiply": MultiplyBenchmark(secp256k1),
"crypto/curve/nist256p1/sign": SignBenchmark(nist256p1),
"crypto/curve/nist256p1/verify": VerifyBenchmark(nist256p1),
"crypto/curve/nist256p1/publickey": PublickeyBenchmark(nist256p1),
"crypto/curve/nist256p1/multiply": MultiplyBenchmark(nist256p1),
"crypto/curve/secp256k1/sign": SignBenchmark(Secp256k1()),
"crypto/curve/secp256k1/verify": VerifyBenchmark(Secp256k1()),
"crypto/curve/secp256k1/publickey": PublickeyBenchmark(Secp256k1()),
"crypto/curve/secp256k1/multiply": MultiplyBenchmark(Secp256k1()),
"crypto/curve/nist256p1/sign": SignBenchmark(Nist256p1()),
"crypto/curve/nist256p1/verify": VerifyBenchmark(Nist256p1()),
"crypto/curve/nist256p1/publickey": PublickeyBenchmark(Nist256p1()),
"crypto/curve/nist256p1/multiply": MultiplyBenchmark(Nist256p1()),
"crypto/curve/ed25519/sign": SignBenchmark(Ed25519()),
"crypto/curve/ed25519/verify": VerifyBenchmark(Ed25519()),
"crypto/curve/ed25519/publickey": PublickeyBenchmark(ed25519),
"crypto/curve/ed25519/publickey": PublickeyBenchmark(Ed25519()),
"crypto/curve/curve25519/publickey": PublickeyBenchmark(curve25519),
"crypto/curve/curve25519/multiply": MultiplyBenchmark(curve25519),
}

View File

@ -59,6 +59,6 @@ async def sign_tx(envelope: BinanceSignTx, keychain: Keychain) -> BinanceSignedT
# generate_content_signature
msghash = sha256(msg_json.encode()).digest()
signature_bytes = secp256k1.sign(node.private_key(), msghash)[1:65]
signature_bytes = secp256k1.sign_recoverable(node.private_key(), msghash)[1:65]
return BinanceSignedTx(signature=signature_bytes, public_key=node.public_key())

View File

@ -108,7 +108,7 @@ def ecdsa_sign(node: bip32.HDNode, digest: bytes) -> bytes:
from trezor.crypto import der
from trezor.crypto.curve import secp256k1
sig = secp256k1.sign(node.private_key(), digest)
sig = secp256k1.sign_recoverable(node.private_key(), digest)
sigder = der.encode_seq((sig[1:33], sig[33:65]))
return sigder

View File

@ -52,7 +52,7 @@ async def sign_message(
seckey = node.private_key()
digest = message_digest(coin, message)
signature = secp256k1.sign(seckey, digest)
signature = secp256k1.sign_recoverable(seckey, digest)
if script_type == InputScriptType.SPENDADDRESS:
script_type_info = 0

View File

@ -51,7 +51,7 @@ async def sign_tx(msg: EosSignTx, keychain: Keychain) -> EosSignedTx:
write_bytes_fixed(sha, bytearray(32), 32)
digest = sha.get_digest()
signature = secp256k1.sign(
signature = secp256k1.sign_recoverable(
node.private_key(), digest, True, secp256k1.CANONICAL_SIG_EOS
)

View File

@ -46,7 +46,7 @@ async def sign_message(
decode_message(msg.message), address, account="ETH", path=path, verify=False
)
signature = secp256k1.sign(
signature = secp256k1.sign_recoverable(
node.private_key(),
message_digest(msg.message),
False,

View File

@ -262,7 +262,7 @@ def _sign_digest(
from trezor.crypto.curve import secp256k1
node = keychain.derive(msg.address_n)
signature = secp256k1.sign(
signature = secp256k1.sign_recoverable(
node.private_key(), digest, False, secp256k1.CANONICAL_SIG_ETHEREUM
)

View File

@ -158,7 +158,7 @@ def _sign_digest(
from trezor.messages import EthereumTxRequest
node = keychain.derive(msg.address_n)
signature = secp256k1.sign(
signature = secp256k1.sign_recoverable(
node.private_key(), digest, False, secp256k1.CANONICAL_SIG_ETHEREUM
)

View File

@ -48,7 +48,7 @@ async def sign_typed_data(
msg.primary_type, msg.metamask_v4_compat
)
signature = secp256k1.sign(
signature = secp256k1.sign_recoverable(
node.private_key(), data_hash, False, secp256k1.CANONICAL_SIG_ETHEREUM
)

View File

@ -133,11 +133,11 @@ def sign_challenge(
if curve == "secp256k1":
from trezor.crypto.curve import secp256k1
signature = secp256k1.sign(seckey, data)
signature = secp256k1.sign_recoverable(seckey, data)
elif curve == "nist256p1":
from trezor.crypto.curve import nist256p1
signature = nist256p1.sign(seckey, data)
signature = nist256p1.sign_recoverable(seckey, data)
elif curve == "ed25519":
from trezor.crypto.curve import ed25519

View File

@ -54,7 +54,7 @@ async def sign_tx(msg: RippleSignTx, keychain: Keychain) -> RippleSignedTx:
# Signs and encodes signature into DER format
first_half_of_sha512 = sha512(to_sign).digest()[:32]
sig = secp256k1.sign(node.private_key(), first_half_of_sha512)
sig = secp256k1.sign_recoverable(node.private_key(), first_half_of_sha512)
sig_encoded = der.encode_seq((sig[1:33], sig[33:65]))
tx = serialize(msg, source_address, node.public_key(), sig_encoded)

View File

@ -94,7 +94,7 @@ class Credential:
dig = hashlib.sha256()
for segment in data:
dig.update(segment)
sig = nist256p1.sign(self._private_key(), dig.digest(), False)
sig = nist256p1.sign_recoverable(self._private_key(), dig.digest(), False)
return der.encode_seq((sig[1:33], sig[33:]))
def bogus_signature(self) -> bytes:

View File

@ -1309,7 +1309,7 @@ def basic_attestation_sign(data: Iterable[bytes]) -> bytes:
dig = hashlib.sha256()
for segment in data:
dig.update(segment)
sig = nist256p1.sign(_FIDO_ATT_PRIV_KEY, dig.digest(), False)
sig = nist256p1.sign_recoverable(_FIDO_ATT_PRIV_KEY, dig.digest(), False)
return der.encode_seq((sig[1:33], sig[33:]))

View File

@ -20,7 +20,7 @@ if not utils.BITCOIN_ONLY:
# NOTE: copy-pasted from apps.binance.sign_tx
def generate_content_signature(json: bytes, private_key: bytes) -> bytes:
msghash = sha256(json).digest()
return secp256k1.sign(private_key, msghash)[1:65]
return secp256k1.sign_recoverable(private_key, msghash)[1:65]
@unittest.skipUnless(not utils.BITCOIN_ONLY, "altcoin")

View File

@ -250,17 +250,17 @@ class TestCryptoNist256p1(unittest.TestCase):
pk = nist256p1.publickey(sk)
dig = bytes([1] + [0] * 31)
sig = nist256p1.sign(sk, dig)
sig = nist256p1.sign_recoverable(sk, dig)
self.assertTrue(nist256p1.verify(pk, sig, dig))
self.assertTrue(nist256p1.verify(pk, sig[1:], dig))
dig = bytes([0] * 31 + [1])
sig = nist256p1.sign(sk, dig)
sig = nist256p1.sign_recoverable(sk, dig)
self.assertTrue(nist256p1.verify(pk, sig, dig))
self.assertTrue(nist256p1.verify(pk, sig[1:], dig))
dig = bytes([0xFF] * 32)
sig = nist256p1.sign(sk, dig)
sig = nist256p1.sign_recoverable(sk, dig)
self.assertTrue(nist256p1.verify(pk, sig, dig))
self.assertTrue(nist256p1.verify(pk, sig[1:], dig))
@ -269,7 +269,7 @@ class TestCryptoNist256p1(unittest.TestCase):
sk = nist256p1.generate_secret()
pk = nist256p1.publickey(sk)
dig = random.bytes(32)
sig = nist256p1.sign(sk, dig)
sig = nist256p1.sign_recoverable(sk, dig)
self.assertTrue(nist256p1.verify(pk, sig, dig))
self.assertTrue(nist256p1.verify(pk, sig[1:], dig))
@ -279,7 +279,7 @@ class TestCryptoNist256p1(unittest.TestCase):
sk = nist256p1.generate_secret()
pk = nist256p1.publickey(sk, compressed)
dig = random.bytes(32)
sig = nist256p1.sign(sk, dig, compressed)
sig = nist256p1.sign_recoverable(sk, dig, compressed)
pk2 = nist256p1.verify_recover(sig, dig)
self.assertEqual(pk, pk2)

View File

@ -221,15 +221,15 @@ class TestCryptoSecp256k1(unittest.TestCase):
pk = secp256k1.publickey(sk)
dig = bytes([1] + [0] * 31)
sig = secp256k1.sign(sk, dig)
sig = secp256k1.sign_recoverable(sk, dig)
self.assertTrue(secp256k1.verify(pk, sig, dig))
dig = bytes([0] * 31 + [1])
sig = secp256k1.sign(sk, dig)
sig = secp256k1.sign_recoverable(sk, dig)
self.assertTrue(secp256k1.verify(pk, sig, dig))
dig = bytes([0xFF] * 32)
sig = secp256k1.sign(sk, dig)
sig = secp256k1.sign_recoverable(sk, dig)
self.assertTrue(secp256k1.verify(pk, sig, dig))
def test_sign_verify_random(self):
@ -237,7 +237,7 @@ class TestCryptoSecp256k1(unittest.TestCase):
sk = secp256k1.generate_secret()
pk = secp256k1.publickey(sk)
dig = random.bytes(32)
sig = secp256k1.sign(sk, dig)
sig = secp256k1.sign_recoverable(sk, dig)
self.assertTrue(secp256k1.verify(pk, sig, dig))
def test_verify_recover(self):
@ -246,7 +246,7 @@ class TestCryptoSecp256k1(unittest.TestCase):
sk = secp256k1.generate_secret()
pk = secp256k1.publickey(sk, compressed)
dig = random.bytes(32)
sig = secp256k1.sign(sk, dig, compressed)
sig = secp256k1.sign_recoverable(sk, dig, compressed)
pk2 = secp256k1.verify_recover(sig, dig)
self.assertEqual(pk, pk2)

View File

@ -295,7 +295,9 @@ def test_sign_native(curve, r):
digest = r.randbytes(32)
sig = r.randbytes(64)
lib.tc_ecdsa_sign_digest(curve.ptr, priv, digest, sig, c.c_void_p(0), c.c_void_p(0))
lib.tc_ecdsa_sign_digest_recoverable(
curve.ptr, priv, digest, sig, c.c_void_p(0), c.c_void_p(0)
)
exp = bytes2num(priv)
sk = ecdsa.SigningKey.from_secret_exponent(exp, curve, hashfunc=hashlib.sha256)
@ -316,7 +318,7 @@ def test_sign_zkp(r):
digest = r.randbytes(32)
sig = r.randbytes(64)
lib.zkp_ecdsa_sign_digest(
lib.zkp_ecdsa_sign_digest_recoverable(
curve.ptr, priv, digest, sig, c.c_void_p(0), c.c_void_p(0)
)