def key_get_exchange(self): nonce = '\0' * self.nonce_bytes authpkt = nacl.crypto_stream_xor(data, nonce, self.key) try: peer_dhpk = nacl.crypto_sign_open(authpkt, self.peer_public_key) except Exception: print("Invalid signature from peer \"%s\" from %s" % \ (name, addr[0])) sys.exit(0) if self.kex_init: self.key = nacl.crypto_scalarmult(self.dhsk, peer_dhpk) self.nonce_prefix = nacl.crypto_auth(config.get("netshrink", "nonce_prefix"), self.key)[:23-self.nonce_bytes] self.dhsk = None self.kex_init = False return dhpk, dhsk = nacl.crypto_box_keypair() authpkt = nacl.crypto_sign(dhpk, self.secret_key) crypted_data = nonce_out + nacl.crypto_stream_xor(authpkt, '\x01' + self.nonce_prefix + nonce, self.key) mac = nacl.crypto_auth(crypted_data, self.key)[:self.mac_bytes] c_sendto(self.sock, mac + crypted_data, self.addr) self.key = nacl.crypto_scalarmult(dhsk, peer_dhpk) print("New key is %s"%repr(self.key))
def key_exchange(self): self.peer_nonce = 0 self.kex_init = True nonce_out = '\0' * self.nonce_bytes dhpk, self.dhsk = nacl.crypto_box_keypair() authpkt = nacl.crypto_sign(dhpk, self.secret_key) crypted_data = nonce_out + nacl.crypto_stream_xor(authpkt, '\x01' + self.nonce_prefix + nonce_out, self.key) mac = nacl.crypto_auth(crypted_data, self.key)[:self.mac_bytes] c_sendto(self.sock, mac + crypted_data, self.addr)
def send(self, data): if self.nonce_bytes: self.nonce += 1 nonce_out = struct.pack("!Q", self.nonce)[-self.nonce_bytes:] else: nonce_out = '' crypted_data = nonce_out + nacl.crypto_stream_xor(data, '\x01' + self.nonce_prefix + nonce_out, self.key) mac = nacl.crypto_auth(crypted_data, self.key)[:self.mac_bytes] c_sendto(self.sock, mac + crypted_data, self.addr) if nonce_out == '\xff' * self.nonce_bytes: # about to wrap around self.nonce = 0 #nonce 0 should only be used for key exchanges
def raw_recv(self, data): if self.mac_bytes > 0: mac = data[:self.mac_bytes] if not nacl.crypto_auth(data[self.mac_bytes:], self.key)[:self.mac_bytes] == mac: print("Failed MAC verification") return if self.nonce_bytes: nonce_in = data[self.mac_bytes:self.mac_bytes+self.nonce_bytes] else: nonce_in = '' if nonce_in == '\0' * self.nonce_bytes: #print("Key re-exchange time! In") #self.key_get_exchange(data[self.mac_bytes+self.nonce_bytes:]) # Disabled because I am incompetent at key re-exchanges return nonce = '\0' + self.nonce_prefix # 1 if client, 0 if server nonce += data[self.mac_bytes:self.mac_bytes+self.nonce_bytes] in_data = data[self.mac_bytes+self.nonce_bytes:] self.recv(nacl.crypto_stream_xor(in_data, nonce, self.key))
def test_stream_xor(self): nonce = nacl.randombytes(nacl.crypto_stream_NONCEBYTES) c = nacl.crypto_stream_xor(self.msg, nonce, self.k) m = nacl.crypto_stream_xor(c, nonce, self.k) self.assertEqual(m, self.msg)