zerolib.protocol - Helpers for common data structures

This module offers functions for parsing packets and classes representing common data structures used in the ZeroNet protocol.

It defines the following public functions and classes.

TLS certificate

make_cert()

Generate and return a public key PEM and a secret key PEM. The return value is a tuple (publickey_pem, secretkey_pem) containing the bytes of the public PEM file and the bytes of the secret PEM file.

Return type:(bytes, bytes)

User certificate

recover_cert(user_btc, portal, name)

Recover the certificate from the user’s Bitcoin address (string), the portal type (string) and the user’s name (string). Returns the recovered certificate, as a bytes-like string.

Parameters:
  • user_btc (str) – the user’s Bitcoin address.
  • portal (str) – the portal type, usually defined by the certificate issuer.
  • name (str) – the user’s name.
Returns:

the recovered certificate.

Return type:

bytes

Routing

class Peer(object)

The data structure of a peer.

Variables:
  • dest (AddrPort) – the destination of the peer.
  • address – property. The address of a peer, exclusing the port number. It could be an IPv4Address, an IPv6Address, an OnionAddress, or an I2PAddress.
  • port (int) – property. The port number.
  • last_seen – the time when the last request from the peer is received.
  • sites (set of str) – the set of sites the peer is hosting.
  • score (int) – the score rating of the peer.
__init__(self, dest, last_seen, sites = None, dht = None, score = None)

Packets

unpack_stream(stream, sender = None)

Unpack a stream, and indicate that it was sent from the sender. Only unpacks one packet at a time.

Parameters:
  • stream (BytesIO) – the stream to read data from and unpack.
  • sender (AddrPort or None) – where the packet is from.
Raises:
  • KeyError – when a key it is looking for is missing from the packet.
  • TypeError – when the type of a value is wrong and cannot be accepted.
  • ValueError – when a value looks wrong.
unpack_dict(packet, sender = None)

Unpack a dictionary, and indicate that it was sent from sender.

Parameters:
  • packet (dict) – the dictionary to unpack.
  • sender (AddrPort or None) – where the packet is from.
Raises:
  • KeyError – when a key it is looking for is missing from the packet.
  • TypeError – when the type of a value is wrong and cannot be accepted.
  • ValueError – when a value looks wrong.
unpack(data, sender = None)

Unpack a byte string, and indicate that it was sent from a network address. Only unpacks one packet at a time.

Parameters:
  • data (bytes) – the data to unpack.
  • sender (AddrPort or None) – where the packet is from.
Raises:
  • KeyError – when a key it is looking for is missing from the packet.
  • TypeError – when the type of a value is wrong and cannot be accepted.
  • ValueError – when a value looks wrong.
class AddrPort(object)

A named (address, port) tuple.

Variables:
  • address – could be an IPv4Address, an IPv6Address, an OnionAddress, or an I2PAddress.
  • port (int) – the port number.
class OnionAddress(Address)

A Tor Onion Service address, either v2 or v3.

packed

The packed representation of the address, either 10 bytes or 35 bytes long.

__str__(self)

Returns the human readable, base-32 encoded representation of the address, with the .onion suffix.

Return type:str
class I2PAddress(Address)

An I2P address, the SHA-256 hash of an I2P Destination.

packed

The packed representation of the address, a SHA-256 hash.

__str__(self)

Returns the human readable, base-32 encoded representation of the address, with the .b32.i2p suffix.

Return type:str
class Packet(object)

The base class for a packet. Every class below for parsed packets is inherited from this base class.

Variables:
  • req_id (int) – the request ID (sequence number) as indicated on the packet. Since the value of this attribute is taken directly from the packet, request ID is for reference purposes only.
  • sender (AddrPort or None) – where the packet is from.
class PrefixIter(object)

The base class for a packet that has the prefixes attribute. It provides helper methods for easier iteration through the prefixes.

__iter__(self)
__contains__(self, item)

A packet class inherited from PrefixIter supports iteration.

>>> from protocol import unpack_dict
>>> packet = unpack_dict({b'cmd': b'response', b'to': 0,
... b'hashfield_raw': b'\x10\x11ABCDef12'})
>>> packet
<protocol.packets.RespHashSet object at 0x7fc6b1b5ad58>
>>> iter(packet)
<set_iterator object at 0x7fc6b3753990>
>>> list(iter(packet))
[b'\x10\x11', b'12', b'ef', b'AB', b'CD']
>>> b'\x10\x11' in packet
True
>>> b'\xA0\xB1' in packet
False
class PacketInterp(object)

The packet interpreter. This state machine is used to figure out the contextual meaning of each response packet and translate it. Consider the following example.

>>> from protocol import unpack_dict, PacketInterp
>>> request = unpack_dict({b'req_id': 0, b'cmd': b'actionCheckport',
... b'params': {b'port': 15441}})
>>> response = unpack_dict({b'cmd': b'response', b'to': 0,
... b'status': b'open', b'ip_external': b'1.2.3.4'})
>>> request
<protocol.packets.CheckPort object at 0x7f71ca453cc8>
>>> response
<protocol.packets.RespPort object at 0x7f71c9cd2948>
>>> request.port
15441
>>> response.open
True
>>> response.port
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: port
>>>
>>> state_machine = PacketInterp()
>>> state_machine.register(request)
>>> state_machine.interpret(response)
>>> response.port
15441
register(self, packet)

Register a request packet. If the packet is a symmetrical packet, or is not a request packet, do nothing.

interpret(self, packet)

Interpret a response packet and inject necessary atrtibutes into the packet instance. After that, the response packet and the corresponding request packet will be forgotten by the packet interpreter.

If the packet is a symmetrical packet, or is not a response packet, do nothing.

Raises:
  • TypeError – when the type of the packet is unexpected.
  • KeyError – when it cannot find any registered request packet that has the same sequence number.
static new_id()

Returns a new usable sequence number. The sequence number is a random unsigned 32-bit integer.