def host_port_pubkey_from_uri(uri): b_node_uri_scheme = str_to_bytes(node_uri_scheme) b_uri = str_to_bytes(uri) assert b_uri.startswith(b_node_uri_scheme) and \ b'@' in b_uri and b':' in b_uri, b_uri pubkey_hex, ip_port = b_uri[len(b_node_uri_scheme):].split(b'@') assert len(pubkey_hex) == 2 * 512 // 8 ip, port = ip_port.split(b':') return ip, port, decode_hex(pubkey_hex)
def intrinsic_gas_used(self): num_zero_bytes = str_to_bytes(self.data).count(ascii_chr(0)) num_non_zero_bytes = len(self.data) - num_zero_bytes return (opcodes.GTXCOST + (opcodes.CREATE[3] if not self.to else 0) + opcodes.GTXDATAZERO * num_zero_bytes + opcodes.GTXDATANONZERO * num_non_zero_bytes + (opcodes.GTXXSHARDCOST if self.is_cross_shard else 0))
class MockProtocol(devp2p.protocol.BaseProtocol): protocol_id = n max_cmd_id = size name = str_to_bytes('mock%d' % n) version = 1 def __init__(self, *args, **kwargs): super(MockProtocol, self).__init__(*args, **kwargs) self.cmd_by_id = ['mock_cmd%d' % i for i in range(size + 1)]
def ecies_encrypt(cls, data, raw_pubkey, shared_mac_data=''): """ ECIES Encrypt, where P = recipient public key is: 1) generate r = random value 2) generate shared-secret = kdf( ecdhAgree(r, P) ) 3) generate R = rG [same op as generating a public key] 4) send 0x04 || R || AsymmetricEncrypt(shared-secret, plaintext) || tag currently used by go: ECIES_AES128_SHA256 = &ECIESParams{ Hash: sha256.New, hashAlgo: crypto.SHA256, Cipher: aes.NewCipher, BlockSize: aes.BlockSize, KeyLen: 16, } """ # 1) generate r = random value ephem = ECCx() # 2) generate shared-secret = kdf( ecdhAgree(r, P) ) key_material = ephem.raw_get_ecdh_key(pubkey_x=raw_pubkey[:32], pubkey_y=raw_pubkey[32:]) assert len(key_material) == 32 key = eciesKDF(key_material, 32) assert len(key) == 32 key_enc, key_mac = key[:16], key[16:] key_mac = sha256(key_mac).digest() assert len(key_mac) == 32 # 3) generate R = rG [same op as generating a public key] ephem_pubkey = ephem.raw_pubkey # encrypt iv = pyelliptic.Cipher.gen_IV(cls.ecies_ciphername) assert len(iv) == 16 ctx = pyelliptic.Cipher(key_enc, iv, 1, cls.ecies_ciphername) ciphertext = ctx.ciphering(data) assert len(ciphertext) == len(data) # 4) send 0x04 || R || AsymmetricEncrypt(shared-secret, plaintext) || tag msg = ascii_chr(0x04) + ephem_pubkey + iv + ciphertext # the MAC of a message (called the tag) as per SEC 1, 3.5. tag = hmac_sha256(key_mac, msg[1 + 64:] + str_to_bytes(shared_mac_data)) assert len(tag) == 32 msg += tag assert len(msg) == 1 + 64 + 16 + 32 + len(data) == 113 + len(data) assert len(msg) - cls.ecies_encrypt_overhead_length == len(data) return msg
def pack(self, cmd_id, payload): """ UDP packets are structured as follows: hash || signature || packet-type || packet-data packet-type: single byte < 2**7 // valid values are [1,4] packet-data: RLP encoded list. Packet properties are serialized in the order in which they're defined. See packet-data below. Offset | 0 | MDC | Ensures integrity of packet, 65 | signature | Ensures authenticity of sender, `SIGN(sender-privkey, MDC)` 97 | type | Single byte in range [1, 4] that determines the structure of Data 98 | data | RLP encoded, see section Packet Data The packets are signed and authenticated. The sender's Node ID is determined by recovering the public key from the signature. sender-pubkey = ECRECOVER(Signature) The integrity of the packet can then be verified by computing the expected MDC of the packet as: MDC = SHA3(sender-pubkey || type || data) As an optimization, implementations may look up the public key by the UDP sending address and compute MDC before recovering the sender ID. If the MDC values do not match, the packet can be dropped. """ assert cmd_id in self.cmd_id_map.values() assert isinstance(payload, list) cmd_id = str_to_bytes(self.encoders['cmd_id'](cmd_id)) expiration = self.encoders['expiration'](int(time.time() + self.expiration)) encoded_data = rlp.encode(payload + [expiration]) signed_data = crypto.sha3(cmd_id + encoded_data) signature = crypto.sign(signed_data, self.privkey) # assert crypto.verify(self.pubkey, signature, signed_data) # assert self.pubkey == crypto.ecdsa_recover(signed_data, signature) # assert crypto.verify(self.pubkey, signature, signed_data) assert len(signature) == 65 mdc = crypto.sha3(signature + cmd_id + encoded_data) assert len(mdc) == 32 return mdc + signature + cmd_id + encoded_data
def __init__(self, ip, udp_port, tcp_port=0, from_binary=False): tcp_port = tcp_port or udp_port if from_binary: self.udp_port = dec_port(udp_port) self.tcp_port = dec_port(tcp_port) else: assert is_integer(udp_port) assert is_integer(tcp_port) self.udp_port = udp_port self.tcp_port = tcp_port try: # `ip` could be in binary or ascii format, independent of # from_binary's truthy. We use ad-hoc regexp to determine format _ip = str_to_bytes(ip) _ip = (bytes_to_str(ip) if PY3 else unicode(ip)) if ip_pattern.match(_ip) else _ip self._ip = ipaddress.ip_address(_ip) except ipaddress.AddressValueError as e: log.debug("failed to parse ip", error=e, ip=ip) raise e
def test_encryption(): initiator, responder = test_session() for i in range(5): msg_frame = sha3(str_to_bytes(str(i)) + b'f') * i + b'notpadded' msg_frame_padded = rzpad16(msg_frame) frame_size = len(msg_frame) msg_header = struct.pack('>I', frame_size)[1:] + sha3( str(i).encode('utf-8'))[:16 - 3] msg_ct = initiator.encrypt(msg_header, msg_frame_padded) r = responder.decrypt(msg_ct) assert r['header'] == msg_header assert r['frame'] == msg_frame for i in range(5): msg_frame = sha3((str(i) + 'f').encode('utf-8')) msg_header = struct.pack('>I', len(msg_frame))[1:] + sha3( str(i).encode('utf-8'))[:16 - 3] msg_ct = responder.encrypt(msg_header, msg_frame) r = initiator.decrypt(msg_ct) assert r['header'] == msg_header assert r['frame'] == msg_frame
def host_port_pubkey_to_uri(host, port, pubkey): assert len(pubkey) == 512 // 8 uri = '{}{}@{}:{}'.format(node_uri_scheme, bytes_to_str(encode_hex(pubkey)), str(host), port) return str_to_bytes(uri)
def raw_privkey(self): if self.privkey: return str_to_bytes(self.privkey) return self.privkey
def raw_pubkey(self): if self.pubkey_x and self.pubkey_y: return str_to_bytes(self.pubkey_x + self.pubkey_y) return self.pubkey_x + self.pubkey_y
def big_endian_to_int(x): return big_endian_int.deserialize( str_to_bytes(x).lstrip(b'\x00')) def int_to_big_endian(x): return big_endian_int.serialize(x)
def big_endian_to_int(x): return big_endian_int.deserialize(str_to_bytes(x).lstrip(b"\x00"))
def mac(data=b''): data = str_to_bytes(data) self.egress_mac.update(data) return self.egress_mac.digest()
def _mkpingid(self, echoed, node): assert node.pubkey pid = str_to_bytes(echoed) + node.pubkey log.debug('mkpingid', echoed=encode_hex(echoed), node=encode_hex(node.pubkey)) return pid
def to_uri(self): return utils.host_port_pubkey_to_uri(str_to_bytes(self.address.ip), self.address.udp_port, self.pubkey)