List of commits:
Subject Hash Author Date (UTC)
Routing request/response packets c83174c60801774bbf1dc0820959d6d0159f0cd2 GDR! 2017-11-27 19:03:33
Clean up PFS handshake procedure fc23e9ffe4fad4555ef384f29b11153e75aa3497 GDR! 2017-11-27 18:06:48
Proper handling of incoming packets f254c2e022a905b3d52d87cc3bfa731d6279e2fb GDR! 2017-11-12 18:31:13
Working parsing of pong header 67373af393e3c7c412b495655ba7934e4e3dffb5 GDR! 2017-11-09 22:13:57
Use correct incoming/outgoing terminology for nonces 1ba500936c9f190bdd4dd1a02e648ad19ee610c9 GDR! 2017-11-09 20:51:34
util db7db2d7fcccbb320f7c041272a0f708f846d850 GDR! 2017-11-09 20:30:47
Working ping 090854611163edc23aec1b460b285770c6f5b806 GDR! 2017-11-09 20:30:37
Initial 5492ec94c8cab618b3e617e0ac2f8d5b27335f83 GDR! 2017-11-09 17:41:55
Commit c83174c60801774bbf1dc0820959d6d0159f0cd2 - Routing request/response packets
Author: GDR!
Author date (UTC): 2017-11-27 19:03
Committer name: GDR!
Committer date (UTC): 2017-11-27 19:03
Parent(s): fc23e9ffe4fad4555ef384f29b11153e75aa3497
Signer:
Signing key:
Signing status: N
Tree: 674aff6c2072e4fef9b281e9582566c58cf3e1da
File Lines added Lines deleted
crap.py 13 4
tcp.py 58 6
File crap.py changed (mode: 100755) (index 99a0c93..4f6aae1)
... ... import time
5 5
6 6 from identity import Identity from identity import Identity
7 7 from session import Session from session import Session
8 from tcp import TcpPacket, TcpRelay, TcpServerHelloPacket, TcpPingPacket, TcpPongPacket, IncomingStreamHandler, h
8 from tcp import TcpPacket, TcpRelay, TcpServerHelloPacket, TcpPingPacket, TcpPongPacket, IncomingStreamHandler, TcpRoutingRequestPacket, h
9 9
10 10 if __name__ == "__main__": if __name__ == "__main__":
11 11 identity = Identity() identity = Identity()
 
... ... if __name__ == "__main__":
22 22
23 23 relay.negotiate_forward_secret_keys(session, identity) relay.negotiate_forward_secret_keys(session, identity)
24 24
25 print("=== PFS established ===")
26
25 27 def on_ping_recvd(packet): def on_ping_recvd(packet):
26 28 print ("<<< PING", packet) print ("<<< PING", packet)
27 29 def on_pong_recvd(packet): def on_pong_recvd(packet):
 
... ... if __name__ == "__main__":
42 44 time.sleep(0.1) time.sleep(0.1)
43 45 tick += 1 tick += 1
44 46
45 if tick % 30 == 0:
47 if tick == 10:
48 packet = TcpRoutingRequestPacket(
49 relay=relay,
50 public_key=bytearray.fromhex("E702791968D0DFB5C1B0AF5F7EAD1A457F29CC01FD9A07F754E6A621B041F001"),
51 )
52 packet.send()
53
54 if tick % 50 == 1:
46 55 print (">>> PING") print (">>> PING")
47 ping = TcpPingPacket(relay=relay)
48 ping.send()
56 payload = "%dpytox!!" % tick
57 relay.ping(payload[:8].encode())
49 58
50 59 s.close() s.close()
File tcp.py changed (mode: 100644) (index 0b4efe4..f97354f)
... ... class TcpPacket:
49 49 """ """
50 50 return data return data
51 51
52 def prepare_bytes(self):
53 """
54 Fill self.bytes pre-encryption if necessary
55 To be overridden
56 """
57 pass
58
52 59 def serialize(self): def serialize(self):
53 60 """ """
54 61 Return wire-ready serialized packet Return wire-ready serialized packet
55 62 """ """
63 self.prepare_bytes()
56 64 serialized_b = self.encrypt(self.bytes) serialized_b = self.encrypt(self.bytes)
57 65 if len(serialized_b) >= 2**16: if len(serialized_b) >= 2**16:
58 66 raise SerializationError('TCP packet too long: %d' % len(serialized_b)) raise SerializationError('TCP packet too long: %d' % len(serialized_b))
 
... ... class TcpPingPacket(EncryptedPacket):
97 105 Ping packet (0x04) Ping packet (0x04)
98 106 """ """
99 107 packet_id = 0x04 packet_id = 0x04
100 def __init__(self, relay=None):
108 def __init__(self, relay=None, payload=None):
101 109 super().__init__(relay) super().__init__(relay)
102 self.bytes = b"\x04puretoxc"
110 if payload:
111 self.bytes = b"\x04" + payload
112 print ("PING BYTES SEND", self.bytes)
113 else:
114 self.bytes = b"\x04puretoxc"
115
116 if len(self.bytes) != 9:
117 raise ValueError("Ping payload is %d bytes long - must be 8" % (len(self.bytes)-1))
103 118
104 119 @classmethod @classmethod
105 120 def from_bytes(cls, packet_bytes): def from_bytes(cls, packet_bytes):
 
... ... class TcpRoutingRequestPacket(EncryptedPacket):
136 151 Routing request (0x00) Routing request (0x00)
137 152 """ """
138 153 packet_id = 0x00 packet_id = 0x00
154 def __init__(self, relay=None, public_key=None):
155 """
156 public_key: 32-byte bytes object public key
157 """
158 super().__init__(relay)
159 if public_key:
160 self.public_key = public_key
161 if len(public_key) != 32:
162 raise ValueError("Public key %s is not a 32-byte array" % str(public_key))
163
164 def prepare_bytes(self):
165 self.bytes = b"\x00" + self.public_key
166
167 class TcpRoutingResponsePacket(EncryptedPacket):
168 packet_id = 0x01
139 169 def __init__(self, relay=None): def __init__(self, relay=None):
140 170 super().__init__(relay) super().__init__(relay)
141
171
172 @classmethod
173 def from_bytes(cls, packet_bytes):
174 self = TcpRoutingResponsePacket()
175 assert (len(packet_bytes) == 34), "Packet length is not 34 bytes"
176 assert (packet_bytes[0] == self.packet_id), "First byte does not equal to packet id"
177 self.connection_id = int(packet_bytes[1])
178 self.public_key = packet_bytes[2:]
179
180 self.bytes = packet_bytes
181
182 return self
183
184 def __repr__(self):
185 return "<TcpRoutingResponse for %s, connection #%d>" % (h(self.public_key), self.connection_id)
142 186
143 187 class TcpClientHelloPacket(TcpPacket): class TcpClientHelloPacket(TcpPacket):
144 188 """ """
 
... ... class TcpRelay:
308 352 self.set_outgoing_public_key(packet.relay_public_key) self.set_outgoing_public_key(packet.relay_public_key)
309 353 self._socket.setblocking(0) self._socket.setblocking(0)
310 354
355 def ping(self, payload=None):
356 """
357 Construct and send a ping packet to relay
358 """
359 packet = TcpPingPacket(relay=self, payload=payload)
360 packet.send()
361
311 362 class IncomingStreamHandler: class IncomingStreamHandler:
312 363 """ """
313 364 Split incoming TCP stream into packets Split incoming TCP stream into packets
 
... ... class IncomingStreamHandler:
349 400 def decrypt(self, ciphertext): def decrypt(self, ciphertext):
350 401 combined = nacl.bindings.crypto_box_beforenm(bytes(self.relay.get_outgoing_public_key()), bytes(self.relay.get_private_key())) combined = nacl.bindings.crypto_box_beforenm(bytes(self.relay.get_outgoing_public_key()), bytes(self.relay.get_private_key()))
351 402 nonce = self.relay.get_incoming_nonce() nonce = self.relay.get_incoming_nonce()
352 print ("IncomingStreamHandler.decrypt:")
353 print ("combined key", binascii.hexlify(combined))
354 print ("incoming nonce", h(nonce))
403 # print ("IncomingStreamHandler.decrypt:")
404 # print ("combined key", binascii.hexlify(combined))
405 # print ("incoming nonce", h(nonce))
355 406 plaintext = nacl.bindings.crypto_box_open_afternm(ciphertext, nonce, combined) plaintext = nacl.bindings.crypto_box_open_afternm(ciphertext, nonce, combined)
356 407
357 408 return plaintext return plaintext
 
... ... class IncomingStreamHandler:
381 432 return packet return packet
382 433 else: else:
383 434 print("Unknown packet type %d" % packet_id) print("Unknown packet type %d" % packet_id)
435 print(packet_bytes)
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/gdr/PurePyTox

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/gdr/PurePyTox

Clone this repository using git:
git clone git://git.rocketgit.com/user/gdr/PurePyTox

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main