1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-06-27 10:22:34 +00:00

feat(core): support ethereum transaction signing anti-exfil protocol

This commit is contained in:
Ondřej Vejpustek 2025-03-17 16:20:55 +01:00
parent ba06f21a0e
commit af4434b334
2 changed files with 68 additions and 20 deletions

View File

@ -102,7 +102,7 @@ async def sign_tx(
rlp.write(sha, 0) rlp.write(sha, 0)
digest = sha.get_digest() digest = sha.get_digest()
result = _sign_digest(msg, keychain, digest) result = await _sign_digest(msg, keychain, digest)
progress_obj.stop() progress_obj.stop()
@ -253,25 +253,53 @@ async def send_request_chunk(data_left: int) -> bytes:
return resp.data_chunk return resp.data_chunk
def _sign_digest( async def send_request_entropy(nonce_commitment: bytes) -> bytes:
from trezor.messages import EthereumTxAck
from trezor.wire.context import call
req = EthereumTxRequest()
req.nonce_commitment = nonce_commitment
resp = await call(req, EthereumTxAck)
assert resp.entropy is not None
return resp.entropy
async def _sign_digest(
msg: EthereumSignTx, keychain: Keychain, digest: bytes msg: EthereumSignTx, keychain: Keychain, digest: bytes
) -> EthereumTxRequest: ) -> EthereumTxRequest:
from trezor.crypto.curve import secp256k1 from trezor.crypto.curve import secp256k1
node = keychain.derive(msg.address_n) node = keychain.derive(msg.address_n)
signature = secp256k1.sign_recoverable( private_key = node.private_key()
node.private_key(), digest, secp256k1.CANONICAL_SIG_ETHEREUM
) if msg.entropy_commitment is not None:
# use anti-exfil protocol
nonce_commitment = secp256k1.anti_exfil_commit_nonce(
private_key, digest, msg.entropy_commitment
)
entropy = await send_request_entropy(nonce_commitment)
signature = secp256k1.anti_exfil_sign(private_key, digest, entropy)
else:
signature = secp256k1.sign_recoverable(
private_key, digest, secp256k1.CANONICAL_SIG_ETHEREUM
)
req = EthereumTxRequest() req = EthereumTxRequest()
if msg.chain_id <= MAX_CHAIN_ID:
req.signature_v = signature[0] + 35 + 2 * msg.chain_id
else:
# https://github.com/trezor/trezor-core/pull/311
req.signature_v = signature[0]
req.signature_r = signature[1:33] if msg.entropy_commitment is not None:
req.signature_s = signature[33:] # use anti-exfil protocol
req.signature_v = None
req.signature_r = signature[:32]
req.signature_s = signature[32:]
else:
if msg.chain_id <= MAX_CHAIN_ID:
req.signature_v = 35 + 2 * msg.chain_id + signature[0]
else:
# https://github.com/trezor/trezor-core/pull/311
req.signature_v = signature[0]
req.signature_r = signature[1:33]
req.signature_s = signature[33:]
return req return req

View File

@ -119,7 +119,7 @@ async def sign_tx_eip1559(
rlp.write(sha, item.storage_keys) rlp.write(sha, item.storage_keys)
digest = sha.get_digest() digest = sha.get_digest()
result = _sign_digest(msg, keychain, digest) result = await _sign_digest(msg, keychain, digest)
return result return result
@ -151,20 +151,40 @@ def _get_total_length(msg: EthereumSignTxEIP1559, data_total: int) -> int:
return length return length
def _sign_digest( async def _sign_digest(
msg: EthereumSignTxEIP1559, keychain: Keychain, digest: bytes msg: EthereumSignTxEIP1559, keychain: Keychain, digest: bytes
) -> EthereumTxRequest: ) -> EthereumTxRequest:
from trezor.crypto.curve import secp256k1 from trezor.crypto.curve import secp256k1
from trezor.messages import EthereumTxRequest from trezor.messages import EthereumTxRequest
from .sign_tx import send_request_entropy
node = keychain.derive(msg.address_n) node = keychain.derive(msg.address_n)
signature = secp256k1.sign_recoverable( private_key = node.private_key()
node.private_key(), digest, secp256k1.CANONICAL_SIG_ETHEREUM
) if msg.entropy_commitment is not None:
# use anti-exfil protocol
nonce_commitment = secp256k1.anti_exfil_commit_nonce(
private_key, digest, msg.entropy_commitment
)
entropy = await send_request_entropy(nonce_commitment)
signature = secp256k1.anti_exfil_sign(private_key, digest, entropy)
else:
signature = secp256k1.sign_recoverable(
private_key, digest, secp256k1.CANONICAL_SIG_ETHEREUM
)
req = EthereumTxRequest() req = EthereumTxRequest()
req.signature_v = signature[0]
req.signature_r = signature[1:33] if msg.entropy_commitment is not None:
req.signature_s = signature[33:] # use anti-exfil protocol
req.signature_v = None
req.signature_r = signature[:32]
req.signature_s = signature[32:]
else:
req.signature_v = signature[0]
req.signature_r = signature[1:33]
req.signature_s = signature[33:]
return req return req