def string_xor(string_1, string_2): """ Calculates xor of two strings :param string_1: string 1 :param string_2: string 2 :return: xor of two strings """ if len(string_1) != len(string_2): raise ValueError("String must have the same length") return b"".join( rlp_utils.ascii_chr(rlp_utils.safe_ord(a) ^ rlp_utils.safe_ord(b)) for a, b in zip(string_1, string_2))
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
def decode_signature(sig): """ Decodes coordinates from ECC signature bytes :param sig: signature bytes :return: ECC signature parameters """ if not sig: raise ValueError("Signature is required") return rlp_utils.safe_ord(sig[64]) + 27, bitcoin.decode( sig[0:32], 256), bitcoin.decode(sig[32:64], 256)
def _decode_auth_ack_message(self, cipher_text): try: message = self._ecc.decrypt( cipher_text[:eth_common_constants.ENC_AUTH_ACK_MSG_LEN]) except RuntimeError as e: raise AuthenticationError(e) eph_pubkey = message[:eth_common_constants.PUBLIC_KEY_LEN] nonce = message[eth_common_constants. PUBLIC_KEY_LEN:eth_common_constants.PUBLIC_KEY_LEN + eth_common_constants.AUTH_NONCE_LEN] known = rlp_utils.safe_ord(message[-1]) assert known == 0 return (eth_common_constants.ENC_AUTH_ACK_MSG_LEN, eph_pubkey, nonce)
def parse_plain_auth_message(self, message): if len(message) != eth_common_constants.AUTH_MSG_LEN: raise ValueError( "Authentication message of len {0} is expected but was {1}". format(eth_common_constants.ENC_AUTH_MSG_LEN, len(message))) signature = message[:eth_common_constants.SIGNATURE_LEN] pubkey_start = eth_common_constants.SIGNATURE_LEN + eth_common_constants.MAC_LEN pubkey = message[pubkey_start:pubkey_start + eth_common_constants.PUBLIC_KEY_LEN] if not self._ecc.is_valid_key(pubkey): raise InvalidKeyError("Invalid initiator pubkey") nonce_start = eth_common_constants.SIGNATURE_LEN + eth_common_constants.MAC_LEN + eth_common_constants.PUBLIC_KEY_LEN nonce = message[nonce_start:nonce_start + eth_common_constants.AUTH_NONCE_LEN] known_flag = bool( rlp_utils.safe_ord(message[nonce_start + eth_common_constants.AUTH_NONCE_LEN:])) assert known_flag == 0 return signature, pubkey, nonce, eth_common_constants.P2P_PROTOCOL_VERSION
def test_safe_ord(self): self.assertEqual(65, rlp_utils.safe_ord("A")) self.assertEqual(97, rlp_utils.safe_ord("a")) self.assertEqual(49, rlp_utils.safe_ord("1")) self.assertEqual(1, rlp_utils.safe_ord(1)) self.assertEqual(64, rlp_utils.safe_ord(64))