예제 #1
0
    def deserialize(self):
        if self._msg_bytes is None or len(
                self._msg_bytes
        ) < eth_common_constants.MDC_LEN + eth_common_constants.SIGNATURE_LEN:
            raise ValueError("Message bytes empty or too short.")

        mdc = self._memory_view[:eth_common_constants.MDC_LEN].tobytes()
        if mdc != eth_common_utils.keccak_hash(
                self._memory_view[eth_common_constants.MDC_LEN:].tobytes()):
            raise WrongMACError("Message hash does not match MDC")

        mdc_sig_len = eth_common_constants.MDC_LEN + eth_common_constants.SIGNATURE_LEN
        signature = self._memory_view[eth_common_constants.
                                      MDC_LEN:mdc_sig_len].tobytes()

        self._msg_type = rlp_utils.safe_ord(self._memory_view[mdc_sig_len])

        encoded_data = self._memory_view[mdc_sig_len:].tobytes()
        signed_data = eth_common_utils.keccak_hash(encoded_data)
        remote_pubkey = crypto_utils.recover_public_key(signed_data, signature)

        self._public_key = remote_pubkey

        if not crypto_utils.verify_signature(remote_pubkey, signature,
                                             signed_data):
            raise InvalidSignatureError(
                "Message signature does not match public key")

        encoded_payload = self._memory_view[mdc_sig_len + eth_common_constants.
                                            MSG_TYPE_LEN:].tobytes()

        self._deserialize_rlp_payload(encoded_payload)

        self._is_deserialized = True
예제 #2
0
    def test_recover_public_key(self):
        dummy_private_key = crypto_utils.make_private_key(
            helpers.generate_bytearray(111))
        public_key = crypto_utils.private_to_public_key(dummy_private_key)

        msg = helpers.generate_bytearray(222)
        msg_hash = eth_common_utils.keccak_hash(msg)

        signature = crypto_utils.sign(msg_hash, dummy_private_key)

        recovered_pub_key = crypto_utils.recover_public_key(
            msg_hash, signature)

        self.assertEqual(recovered_pub_key, public_key)
예제 #3
0
def verify_eth_transaction_signature(transaction: Transaction) -> bool:
    """
    checks eth transaction signature
    :param transaction:
    :return: if signature matches public key
    """
    try:
        signature = transaction.signature()
        unsigned_msg = transaction.get_unsigned()
        public_key = crypto_utils.recover_public_key(unsigned_msg, signature, keccak_hash)
        return crypto_utils.verify_signature(public_key, signature, keccak_hash(memoryview(unsigned_msg)))
    # pylint: disable=broad-except
    except Exception:
        return False
예제 #4
0
    def to_json(self) -> Dict[str, Any]:
        """
        Serializes data to be close to Ethereum RPC spec for publishing to the transaction
        feed.

        see https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionbyhash

        Some fields are excluded, since they will never be populated by bxgateway.
        (mainly fields related to the block the transaction gets included in)
        - blockHash
        - blockNumber
        - transactionIndex
        """
        message_hash = self.hash()

        input_data = convert.bytes_to_hex(self.data)
        if not input_data:
            input_data = "0x"
        else:
            input_data = f"0x{input_data}"

        signature = crypto_utils.encode_signature(self.v, self.r, self.s)
        from_key = crypto_utils.recover_public_key(
            self.get_unsigned(), signature, eth_common_utils.keccak_hash
        )
        from_address = crypto_utils.public_key_to_address(from_key)
        serialized_output = {
            "from": convert.bytes_to_hex_string_format(from_address),
            "gas": hex(self.start_gas),
            "gas_price": hex(self.gas_price),
            "hash": f"0x{str(message_hash)}",
            "input": input_data,
            "nonce": hex(self.nonce),
            "value": hex(self.value),
            "v": hex(self.v),
            "r": hex(self.r),
            "s": hex(self.s)
        }

        to = self.to
        if to is not None:
            serialized_output["to"] = convert.bytes_to_hex_string_format(to)

        return serialized_output
예제 #5
0
    def parse_auth_message(self, message):
        assert not self._is_initiator

        if self._is_eip8_auth:
            (signature, pubkey, nonce,
             version) = self.parse_eip8_auth_message(message)
        else:
            (signature, pubkey, nonce,
             version) = self.parse_plain_auth_message(message)

        token = self._ecc.get_ecdh_key(pubkey)
        remote_ephemeral_pubkey = crypto_utils.recover_public_key(
            crypto_utils.string_xor(token, nonce), signature)
        if not self._ecc.is_valid_key(remote_ephemeral_pubkey):
            raise InvalidKeyError("Invalid remote ephemeral pubkey")

        self._remote_ephemeral_pubkey = remote_ephemeral_pubkey
        self._initiator_nonce = nonce
        self._remote_pubkey = pubkey
        self._remote_version = eth_common_constants.P2P_PROTOCOL_VERSION
예제 #6
0
 def from_address(self) -> str:
     from_key = crypto_utils.recover_public_key(
         self.get_unsigned(), self.signature(),
         eth_common_utils.keccak_hash)
     from_address = crypto_utils.public_key_to_address(from_key)
     return convert.bytes_to_hex_string_format(from_address)