def to_endpoint(self): """ struct Endpoint { unsigned network; // ipv4:4, ipv6:6 unsigned transport; // tcp:6, udp:17 unsigned address; // BE encoded 32-bit or 128-bit unsigned (layer3 address) unsigned port; // BE encoded 16-bit unsigned (layer4 port) } """ transport = 6 r = [utils.ienc(self._ip.version), utils.ienc(transport)] r += [self._ip.packed, utils.ienc(self.port)] return r
def to_endpoint(self): """ struct Endpoint { unsigned network; // ipv4:4, ipv6:6 unsigned transport; // tcp:6, udp:17 unsigned address; // BE encoded 32-bit or 128-bit unsigned (layer3 address) unsigned port; // BE encoded 16-bit unsigned (layer4 port) } """ transport = 6 r = [utils.ienc(self._ip.version), utils.ienc(transport)] r += [self._ip.packed, struct.pack('>H', self.port)] return r
def create_auth_message(self, remote_pubkey, token=None, ephemeral_privkey=None, nonce=None): """ 1. initiator generates ecdhe-random and nonce and creates auth 2. initiator connects to remote and sends auth New: E(remote-pubk, S(ephemeral-privk, ecdh-shared-secret ^ nonce) || H(ephemeral-pubk) || pubk || nonce || 0x0 ) Known: E(remote-pubk, S(ephemeral-privk, token ^ nonce) || H(ephemeral-pubk) || pubk || nonce || 0x1) """ if not token: # new ecdh_shared_secret = self.node.get_ecdh_key(remote_pubkey) token = ecdh_shared_secret flag = 0x0 else: flag = 0x1 nonce = nonce or ienc(random.randint(0, 2**256 - 1)) assert len(nonce) == 32 token_xor_nonce = sxor(token, nonce) assert len(token_xor_nonce) == 32 # generate session ephemeral key if not ephemeral_privkey: ephemeral_privkey = sha3(ienc(random.randint(0, 2**256 - 1))) self.ephemeral_ecc = ECCx(raw_privkey=ephemeral_privkey) ephemeral_pubkey = self.ephemeral_ecc.raw_pubkey assert len(ephemeral_pubkey) == 512 / 8 # S(ephemeral-privk, ecdh-shared-secret ^ nonce) S = self.ephemeral_ecc.sign(token_xor_nonce) assert len(S) == 65 # S || H(ephemeral-pubk) || pubk || nonce || 0x0 auth_message = S + sha3( ephemeral_pubkey) + self.node.raw_pubkey + nonce + chr(flag) assert len(auth_message) == 65 + 32 + 64 + 32 + 1 == 194 return auth_message
def something(): ################## # send authentication if not yet if not self._authentication_sent: remote_node = RemoteNode(remote_pubkey) # FIXME LOOKUP self.send_authentication(remote_node) # - success -> AcknowledgeAuthentication self.acknowledge_authentication(other, remote_pubkey, remote_ecdhe_pubkey) # ecdhe_shared_secret = ecdh.agree(ecdhe-random, ecdhe-random-public) # Compute public key with the local private key and return a 512bits shared key ecdhe_shared_secret = self.ephemeral_ecc.get_ecdh_key(remote_pubkey) ecdhe_pubkey = self.ephemeral_ecc.get_pubkey() # shared-secret = sha3(ecdhe-shared-secret || sha3(nonce || remote-nonce)) shared_secret = sha3(ecdhe_shared_secret + sha3(ienc(self.nonce) + ienc(remote_nonce))) self.aes_secret = sha3(ecdhe_shared_secret + shared_secret) self.mac_secret = sha3(ecdhe_shared_secret + self.aes_secret) # egress-mac = sha3(mac-secret^nonce || auth) self.egress_mac = sha3(sxor(self.mac_secret, self.nonce) + ciphertext) # ingress-mac = sha3(mac-secret^remote-nonce || auth) self.ingress_mac = sha3( sxor(self.mac_secret, remote_nonce) + ciphertext) self.token = sha3(shared_secret) iv = pyelliptic.Cipher.gen_IV('aes-256-ctr') self.aes_enc = pyelliptic.Cipher(self.aes_secret, iv, 1, ciphername='aes-256-ctr') self.aes_dec = pyelliptic.Cipher(self.aes_secret, iv, 0, ciphername='aes-256-ctr') self.is_ready = True
def create_auth_message(self, remote_pubkey, ephemeral_privkey=None, nonce=None): """ 1. initiator generates ecdhe-random and nonce and creates auth 2. initiator connects to remote and sends auth New: E(remote-pubk, S(ephemeral-privk, ecdh-shared-secret ^ nonce) || H(ephemeral-pubk) || pubk || nonce || 0x0 ) Known: E(remote-pubk, S(ephemeral-privk, token ^ nonce) || H(ephemeral-pubk) || pubk || nonce || 0x1) """ assert self.is_initiator if not self.ecc.is_valid_key(remote_pubkey): raise InvalidKeyError('invalid remote pubkey') self.remote_pubkey = remote_pubkey token = self.token_by_pubkey.get(remote_pubkey) if not token: # new ecdh_shared_secret = self.ecc.get_ecdh_key(remote_pubkey) token = ecdh_shared_secret flag = 0x0 else: flag = 0x1 self.initiator_nonce = nonce or sha3( ienc(random.randint(0, 2**256 - 1))) assert len(self.initiator_nonce) == 32 token_xor_nonce = sxor(token, self.initiator_nonce) assert len(token_xor_nonce) == 32 ephemeral_pubkey = self.ephemeral_ecc.raw_pubkey assert len(ephemeral_pubkey) == 512 / 8 if not self.ecc.is_valid_key(ephemeral_pubkey): raise InvalidKeyError('invalid ephemeral pubkey') # S(ephemeral-privk, ecdh-shared-secret ^ nonce) S = self.ephemeral_ecc.sign(token_xor_nonce) assert len(S) == 65 # S || H(ephemeral-pubk) || pubk || nonce || 0x0 auth_message = S + sha3(ephemeral_pubkey) + self.ecc.raw_pubkey + \ self.initiator_nonce + chr(flag) assert len(auth_message) == 65 + 32 + 64 + 32 + 1 == 194 return auth_message
def create_auth_ack_message(self, ephemeral_pubkey=None, nonce=None, token_found=False): """ authRecipient = E(remote-pubk, remote-ephemeral-pubk || nonce || 0x1) // token found authRecipient = E(remote-pubk, remote-ephemeral-pubk || nonce || 0x0) // token not found nonce and empehemeral-pubk are local! """ assert not self.is_initiator ephemeral_pubkey = ephemeral_pubkey or self.ephemeral_ecc.raw_pubkey self.responder_nonce = nonce or sha3(ienc(random.randint(0, 2 ** 256 - 1))) flag = chr(1 if token_found else 0) msg = ephemeral_pubkey + self.responder_nonce + flag assert len(msg) == 64 + 32 + 1 == 97 == self.auth_ack_message_length return msg
def create_auth_message(self, remote_pubkey, ephemeral_privkey=None, nonce=None): """ 1. initiator generates ecdhe-random and nonce and creates auth 2. initiator connects to remote and sends auth New: E(remote-pubk, S(ephemeral-privk, ecdh-shared-secret ^ nonce) || H(ephemeral-pubk) || pubk || nonce || 0x0 ) Known: E(remote-pubk, S(ephemeral-privk, token ^ nonce) || H(ephemeral-pubk) || pubk || nonce || 0x1) """ assert self.is_initiator if not self.ecc.is_valid_key(remote_pubkey): raise InvalidKeyError('invalid remote pubkey') self.remote_pubkey = remote_pubkey token = self.token_by_pubkey.get(remote_pubkey) if not token: # new ecdh_shared_secret = self.ecc.get_ecdh_key(remote_pubkey) token = ecdh_shared_secret flag = 0x0 else: flag = 0x1 self.initiator_nonce = nonce or sha3(ienc(random.randint(0, 2 ** 256 - 1))) assert len(self.initiator_nonce) == 32 token_xor_nonce = sxor(token, self.initiator_nonce) assert len(token_xor_nonce) == 32 ephemeral_pubkey = self.ephemeral_ecc.raw_pubkey assert len(ephemeral_pubkey) == 512 / 8 if not self.ecc.is_valid_key(ephemeral_pubkey): raise InvalidKeyError('invalid ephemeral pubkey') # S(ephemeral-privk, ecdh-shared-secret ^ nonce) S = self.ephemeral_ecc.sign(token_xor_nonce) assert len(S) == 65 # S || H(ephemeral-pubk) || pubk || nonce || 0x0 auth_message = S + sha3(ephemeral_pubkey) + self.ecc.raw_pubkey + \ self.initiator_nonce + chr(flag) assert len(auth_message) == 65 + 32 + 64 + 32 + 1 == 194 return auth_message
def create_auth_ack_message(self, ephemeral_pubkey=None, nonce=None, token_found=False): """ authRecipient = E(remote-pubk, remote-ephemeral-pubk || nonce || 0x1) // token found authRecipient = E(remote-pubk, remote-ephemeral-pubk || nonce || 0x0) // token not found nonce and empehemeral-pubk are local! """ assert not self.is_initiator ephemeral_pubkey = ephemeral_pubkey or self.ephemeral_ecc.raw_pubkey self.responder_nonce = nonce or sha3( ienc(random.randint(0, 2**256 - 1))) flag = chr(1 if token_found else 0) msg = ephemeral_pubkey + self.responder_nonce + flag assert len(msg) == 64 + 32 + 1 == 97 == self.auth_ack_message_length return msg
def create_auth_ack_message(self, version=supported_rlpx_version, eip8=False, ephemeral_pubkey=None, nonce=None): """ authRecipient = E(remote-pubk, remote-ephemeral-pubk || nonce || 0x1) // token found authRecipient = E(remote-pubk, remote-ephemeral-pubk || nonce || 0x0) // token not found nonce, ephemeral_pubkey, version are local! """ assert not self.is_initiator ephemeral_pubkey = ephemeral_pubkey or self.ephemeral_ecc.raw_pubkey self.responder_nonce = nonce or sha3( ienc(random.randint(0, 2**256 - 1))) if eip8 or self.got_eip8_auth: msg = self.create_eip8_auth_ack_message(ephemeral_pubkey, self.responder_nonce, version) assert len(msg) > 97 else: msg = ephemeral_pubkey + self.responder_nonce + b'\x00' assert len(msg) == 97 return msg
def to_binary(self): return list((self._ip.packed, utils.ienc(self.port)))