def eth_sign_msg( self, msg: bytes, keypath: Sequence[int], coin: eth.ETHCoin = eth.ETH ) -> bytes: """ Signs message, the msg will be prefixed with "\x19Ethereum message\n" + len(msg) in the hardware """ request = eth.ETHRequest() # pylint: disable=no-member request.sign_msg.CopyFrom(eth.ETHSignMessageRequest(coin=coin, keypath=keypath, msg=msg)) supports_antiklepto = self.version >= semver.VersionInfo(9, 5, 0) if supports_antiklepto: host_nonce = os.urandom(32) request.sign_msg.host_nonce_commitment.commitment = antiklepto_host_commit(host_nonce) signer_commitment = self._eth_msg_query( request, expected_response="antiklepto_signer_commitment" ).antiklepto_signer_commitment.commitment request = eth.ETHRequest() request.antiklepto_signature.CopyFrom( antiklepto.AntiKleptoSignatureRequest(host_nonce=host_nonce) ) signature = self._eth_msg_query(request, expected_response="sign").sign.signature antiklepto_verify(host_nonce, signer_commitment, signature[:64]) if self.debug: print(f"Antiklepto nonce verification PASSED") return signature return self._eth_msg_query(request, expected_response="sign").sign.signature
def eth_sign_msg(self, msg: bytes, keypath: Sequence[int], chain_id: int = 1) -> bytes: """ Signs message, the msg will be prefixed with "\x19Ethereum message\n" + len(msg) in the hardware. 27 is added to the recID to denote an uncompressed pubkey. """ def format_as_uncompressed(sig: bytes) -> bytes: # 27 is the magic constant to add to the recoverable ID to denote an uncompressed # pubkey. modified_signature = list(sig) modified_signature[64] += 27 return bytes(modified_signature) request = eth.ETHRequest() # pylint: disable=no-member request.sign_msg.CopyFrom( eth.ETHSignMessageRequest(coin=self._eth_coin(chain_id), chain_id=chain_id, keypath=keypath, msg=msg)) supports_antiklepto = self.version >= semver.VersionInfo(9, 5, 0) if supports_antiklepto: host_nonce = os.urandom(32) request.sign_msg.host_nonce_commitment.commitment = antiklepto_host_commit( host_nonce) signer_commitment = self._eth_msg_query( request, expected_response="antiklepto_signer_commitment" ).antiklepto_signer_commitment.commitment request = eth.ETHRequest() request.antiklepto_signature.CopyFrom( antiklepto.AntiKleptoSignatureRequest(host_nonce=host_nonce)) signature = self._eth_msg_query( request, expected_response="sign").sign.signature antiklepto_verify(host_nonce, signer_commitment, signature[:64]) if self.debug: print("Antiklepto nonce verification PASSED") return format_as_uncompressed(signature) signature = self._eth_msg_query( request, expected_response="sign").sign.signature return format_as_uncompressed(signature)
def eth_sign(self, transaction: bytes, keypath: Sequence[int], chain_id: int = 1) -> bytes: """ transaction should be given as a full rlp encoded eth transaction. """ nonce, gas_price, gas_limit, recipient, value, data, _, _, _ = rlp.decode( transaction) request = eth.ETHRequest() # pylint: disable=no-member request.sign.CopyFrom( eth.ETHSignRequest( coin=self._eth_coin(chain_id), chain_id=chain_id, keypath=keypath, nonce=nonce, gas_price=gas_price, gas_limit=gas_limit, recipient=recipient, value=value, data=data, )) supports_antiklepto = self.version >= semver.VersionInfo(9, 5, 0) if supports_antiklepto: host_nonce = os.urandom(32) request.sign.host_nonce_commitment.commitment = antiklepto_host_commit( host_nonce) signer_commitment = self._eth_msg_query( request, expected_response="antiklepto_signer_commitment" ).antiklepto_signer_commitment.commitment request = eth.ETHRequest() request.antiklepto_signature.CopyFrom( antiklepto.AntiKleptoSignatureRequest(host_nonce=host_nonce)) signature = self._eth_msg_query( request, expected_response="sign").sign.signature antiklepto_verify(host_nonce, signer_commitment, signature[:64]) if self.debug: print("Antiklepto nonce verification PASSED") return signature return self._eth_msg_query(request, expected_response="sign").sign.signature
def eth_pub( self, keypath: Sequence[int], chain_id: int = 1, output_type: "eth.ETHPubRequest.OutputType.V" = eth.ETHPubRequest. ADDRESS, display: bool = True, contract_address: bytes = b"", ) -> str: """ keypath is a list of child derivation numbers. e.g. m/44'/60'/0'/0/5 corresponds to [44+HARDENED, 60+HARDENED, 0+HARDENED, 0, 5]. """ # pylint: disable=no-member request = eth.ETHRequest() request.pub.CopyFrom( eth.ETHPubRequest( coin=self._eth_coin(chain_id), chain_id=chain_id, keypath=keypath, output_type=output_type, display=display, contract_address=contract_address, )) return self._eth_msg_query(request, expected_response="pub").pub.pub
def eth_sign_msg(self, msg: bytes, keypath: List[int], coin: eth.ETHCoin = eth.ETH) -> bytes: """ Signs message, the msg will be prefixed with "\x19Ethereum message\n" + len(msg) in the hardware """ request = eth.ETHRequest() # pylint: disable=no-member request.sign_msg.CopyFrom(eth.ETHSignMessageRequest(coin=coin, keypath=keypath, msg=msg)) return self._eth_msg_query(request, expected_response="sign").sign.signature
def eth_sign( self, transaction: bytes, keypath: List[int], coin: eth.ETHCoin = eth.ETH ) -> bytes: """ transaction should be given as a full rlp encoded eth transaction. """ nonce, gas_price, gas_limit, recipient, value, data, _, _, _ = rlp.decode(transaction) request = eth.ETHRequest() # pylint: disable=no-member request.sign.CopyFrom( eth.ETHSignRequest( coin=coin, keypath=keypath, nonce=nonce, gas_price=gas_price, gas_limit=gas_limit, recipient=recipient, value=value, data=data, ) ) return self._eth_msg_query(request, expected_response="sign").sign.signature