mirror of
https://github.com/markqvist/Reticulum.git
synced 2026-07-17 22:08:11 -07:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 719764fd81 | |||
| 5ccbc825fd | |||
| ad67c553d7 | |||
| d68cfaa8f7 | |||
| cf9934810b | |||
| e8ca88377a | |||
| bf410e006f | |||
| db527b6759 | |||
| 9c995b33dd | |||
| f18fb35aba | |||
| ce405b9252 | |||
| 7f5625a526 | |||
| e8fb435f00 | |||
| f880edbeb8 | |||
| 2b97c89566 |
@@ -39,7 +39,7 @@ def program_setup(configpath, channel=None):
|
|||||||
|
|
||||||
# We specify a callback that will get called every time
|
# We specify a callback that will get called every time
|
||||||
# the destination receives data.
|
# the destination receives data.
|
||||||
broadcast_destination.packet_callback(packet_callback)
|
broadcast_destination.set_packet_callback(packet_callback)
|
||||||
|
|
||||||
# Everything's ready!
|
# Everything's ready!
|
||||||
# Let's hand over control to the main loop
|
# Let's hand over control to the main loop
|
||||||
|
|||||||
+4
-4
@@ -52,7 +52,7 @@ def server(configpath):
|
|||||||
# Tell the destination which function in our program to
|
# Tell the destination which function in our program to
|
||||||
# run when a packet is received. We do this so we can
|
# run when a packet is received. We do this so we can
|
||||||
# print a log message when the server receives a request
|
# print a log message when the server receives a request
|
||||||
echo_destination.packet_callback(server_callback)
|
echo_destination.set_packet_callback(server_callback)
|
||||||
|
|
||||||
# Everything's ready!
|
# Everything's ready!
|
||||||
# Let's Wait for client requests or user input
|
# Let's Wait for client requests or user input
|
||||||
@@ -170,12 +170,12 @@ def client(destination_hexhash, configpath, timeout=None):
|
|||||||
# the packet times out.
|
# the packet times out.
|
||||||
if timeout != None:
|
if timeout != None:
|
||||||
packet_receipt.set_timeout(timeout)
|
packet_receipt.set_timeout(timeout)
|
||||||
packet_receipt.timeout_callback(packet_timed_out)
|
packet_receipt.set_timeout_callback(packet_timed_out)
|
||||||
|
|
||||||
# We can then set a delivery callback on the receipt.
|
# We can then set a delivery callback on the receipt.
|
||||||
# This will get automatically called when a proof for
|
# This will get automatically called when a proof for
|
||||||
# this specific packet is received from the destination.
|
# this specific packet is received from the destination.
|
||||||
packet_receipt.delivery_callback(packet_delivered)
|
packet_receipt.set_delivery_callback(packet_delivered)
|
||||||
|
|
||||||
# Tell the user that the echo request was sent
|
# Tell the user that the echo request was sent
|
||||||
RNS.log("Sent echo request to "+RNS.prettyhexrep(request_destination.hash))
|
RNS.log("Sent echo request to "+RNS.prettyhexrep(request_destination.hash))
|
||||||
@@ -189,7 +189,7 @@ def client(destination_hexhash, configpath, timeout=None):
|
|||||||
# receives a proof packet.
|
# receives a proof packet.
|
||||||
def packet_delivered(receipt):
|
def packet_delivered(receipt):
|
||||||
if receipt.status == RNS.PacketReceipt.DELIVERED:
|
if receipt.status == RNS.PacketReceipt.DELIVERED:
|
||||||
rtt = receipt.rtt()
|
rtt = receipt.get_rtt()
|
||||||
if (rtt >= 1):
|
if (rtt >= 1):
|
||||||
rtt = round(rtt, 3)
|
rtt = round(rtt, 3)
|
||||||
rttstring = str(rtt)+" seconds"
|
rttstring = str(rtt)+" seconds"
|
||||||
|
|||||||
+10
-10
@@ -65,7 +65,7 @@ def server(configpath, path):
|
|||||||
|
|
||||||
# We configure a function that will get called every time
|
# We configure a function that will get called every time
|
||||||
# a new client creates a link to this destination.
|
# a new client creates a link to this destination.
|
||||||
server_destination.link_established_callback(client_connected)
|
server_destination.set_link_established_callback(client_connected)
|
||||||
|
|
||||||
# Everything's ready!
|
# Everything's ready!
|
||||||
# Let's Wait for client requests or user input
|
# Let's Wait for client requests or user input
|
||||||
@@ -102,7 +102,7 @@ def client_connected(link):
|
|||||||
if os.path.isdir(serve_path):
|
if os.path.isdir(serve_path):
|
||||||
RNS.log("Client connected, sending file list...")
|
RNS.log("Client connected, sending file list...")
|
||||||
|
|
||||||
link.link_closed_callback(client_disconnected)
|
link.set_link_closed_callback(client_disconnected)
|
||||||
|
|
||||||
# We pack a list of files for sending in a packet
|
# We pack a list of files for sending in a packet
|
||||||
data = umsgpack.packb(list_files())
|
data = umsgpack.packb(list_files())
|
||||||
@@ -114,8 +114,8 @@ def client_connected(link):
|
|||||||
list_packet = RNS.Packet(link, data)
|
list_packet = RNS.Packet(link, data)
|
||||||
list_receipt = list_packet.send()
|
list_receipt = list_packet.send()
|
||||||
list_receipt.set_timeout(APP_TIMEOUT)
|
list_receipt.set_timeout(APP_TIMEOUT)
|
||||||
list_receipt.delivery_callback(list_delivered)
|
list_receipt.set_delivery_callback(list_delivered)
|
||||||
list_receipt.timeout_callback(list_timeout)
|
list_receipt.set_timeout_callback(list_timeout)
|
||||||
else:
|
else:
|
||||||
RNS.log("Too many files in served directory!", RNS.LOG_ERROR)
|
RNS.log("Too many files in served directory!", RNS.LOG_ERROR)
|
||||||
RNS.log("You should implement a function to split the filelist over multiple packets.", RNS.LOG_ERROR)
|
RNS.log("You should implement a function to split the filelist over multiple packets.", RNS.LOG_ERROR)
|
||||||
@@ -125,7 +125,7 @@ def client_connected(link):
|
|||||||
# open until the client requests a file. We'll
|
# open until the client requests a file. We'll
|
||||||
# configure a function that get's called when
|
# configure a function that get's called when
|
||||||
# the client sends a packet with a file request.
|
# the client sends a packet with a file request.
|
||||||
link.packet_callback(client_request)
|
link.set_packet_callback(client_request)
|
||||||
else:
|
else:
|
||||||
RNS.log("Client connected, but served path no longer exists!", RNS.LOG_ERROR)
|
RNS.log("Client connected, but served path no longer exists!", RNS.LOG_ERROR)
|
||||||
link.teardown()
|
link.teardown()
|
||||||
@@ -254,18 +254,18 @@ def client(destination_hexhash, configpath):
|
|||||||
# We expect any normal data packets on the link
|
# We expect any normal data packets on the link
|
||||||
# to contain a list of served files, so we set
|
# to contain a list of served files, so we set
|
||||||
# a callback accordingly
|
# a callback accordingly
|
||||||
link.packet_callback(filelist_received)
|
link.set_packet_callback(filelist_received)
|
||||||
|
|
||||||
# We'll also set up functions to inform the
|
# We'll also set up functions to inform the
|
||||||
# user when the link is established or closed
|
# user when the link is established or closed
|
||||||
link.link_established_callback(link_established)
|
link.set_link_established_callback(link_established)
|
||||||
link.link_closed_callback(link_closed)
|
link.set_link_closed_callback(link_closed)
|
||||||
|
|
||||||
# And set the link to automatically begin
|
# And set the link to automatically begin
|
||||||
# downloading advertised resources
|
# downloading advertised resources
|
||||||
link.set_resource_strategy(RNS.Link.ACCEPT_ALL)
|
link.set_resource_strategy(RNS.Link.ACCEPT_ALL)
|
||||||
link.resource_started_callback(download_began)
|
link.set_resource_started_callback(download_began)
|
||||||
link.resource_concluded_callback(download_concluded)
|
link.set_resource_concluded_callback(download_concluded)
|
||||||
|
|
||||||
menu()
|
menu()
|
||||||
|
|
||||||
|
|||||||
+16
-6
@@ -44,7 +44,7 @@ def server(configpath):
|
|||||||
|
|
||||||
# We configure a function that will get called every time
|
# We configure a function that will get called every time
|
||||||
# a new client creates a link to this destination.
|
# a new client creates a link to this destination.
|
||||||
server_destination.link_established_callback(client_connected)
|
server_destination.set_link_established_callback(client_connected)
|
||||||
|
|
||||||
# Everything's ready!
|
# Everything's ready!
|
||||||
# Let's Wait for client requests or user input
|
# Let's Wait for client requests or user input
|
||||||
@@ -76,8 +76,8 @@ def client_connected(link):
|
|||||||
global latest_client_link
|
global latest_client_link
|
||||||
|
|
||||||
RNS.log("Client connected")
|
RNS.log("Client connected")
|
||||||
link.link_closed_callback(client_disconnected)
|
link.set_link_closed_callback(client_disconnected)
|
||||||
link.packet_callback(server_packet_received)
|
link.set_packet_callback(server_packet_received)
|
||||||
latest_client_link = link
|
latest_client_link = link
|
||||||
|
|
||||||
def client_disconnected(link):
|
def client_disconnected(link):
|
||||||
@@ -149,12 +149,12 @@ def client(destination_hexhash, configpath):
|
|||||||
# We set a callback that will get executed
|
# We set a callback that will get executed
|
||||||
# every time a packet is received over the
|
# every time a packet is received over the
|
||||||
# link
|
# link
|
||||||
link.packet_callback(client_packet_received)
|
link.set_packet_callback(client_packet_received)
|
||||||
|
|
||||||
# We'll also set up functions to inform the
|
# We'll also set up functions to inform the
|
||||||
# user when the link is established or closed
|
# user when the link is established or closed
|
||||||
link.link_established_callback(link_established)
|
link.set_link_established_callback(link_established)
|
||||||
link.link_closed_callback(link_closed)
|
link.set_link_closed_callback(link_closed)
|
||||||
|
|
||||||
# Everything is set up, so let's enter a loop
|
# Everything is set up, so let's enter a loop
|
||||||
# for the user to interact with the example
|
# for the user to interact with the example
|
||||||
@@ -181,8 +181,18 @@ def client_loop():
|
|||||||
# If not, send the entered text over the link
|
# If not, send the entered text over the link
|
||||||
if text != "":
|
if text != "":
|
||||||
data = text.encode("utf-8")
|
data = text.encode("utf-8")
|
||||||
|
if len(data) <= RNS.Link.MDU:
|
||||||
RNS.Packet(server_link, data).send()
|
RNS.Packet(server_link, data).send()
|
||||||
|
else:
|
||||||
|
RNS.log(
|
||||||
|
"Cannot send this packet, the data size of "+
|
||||||
|
str(len(data))+" bytes exceeds the link packet MDU of "+
|
||||||
|
str(RNS.Link.MDU)+" bytes",
|
||||||
|
RNS.LOG_ERROR
|
||||||
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
RNS.log("Error while sending data over the link: "+str(e))
|
||||||
should_quit = True
|
should_quit = True
|
||||||
server_link.teardown()
|
server_link.teardown()
|
||||||
|
|
||||||
|
|||||||
@@ -18,12 +18,13 @@ For more info, see [unsigned.io/projects/reticulum](https://unsigned.io/projects
|
|||||||
## Notable Features
|
## Notable Features
|
||||||
- Coordination-less globally unique adressing and identification
|
- Coordination-less globally unique adressing and identification
|
||||||
- Fully self-configuring multi-hop routing
|
- Fully self-configuring multi-hop routing
|
||||||
- Asymmetric RSA encryption and signatures as basis for all communication
|
- Asymmetric X25519 encryption and Ed25519 signatures as a basis for all communication
|
||||||
- Perfect Forward Secrecy on links with ephemereal Elliptic Curve Diffie-Hellman keys (on Curve25519)
|
- Forward Secrecy with ephemereal Elliptic Curve Diffie-Hellman keys on Curve25519
|
||||||
- Reticulum uses the [Fernet](https://github.com/fernet/spec/blob/master/Spec.md) specification for encryption on links and to group destinations
|
- Reticulum uses the [Fernet](https://github.com/fernet/spec/blob/master/Spec.md) specification for encryption
|
||||||
- AES-128 in CBC mode with PKCS7 padding
|
- AES-128 in CBC mode with PKCS7 padding
|
||||||
- HMAC using SHA256 for authentication
|
- HMAC using SHA256 for authentication
|
||||||
- IVs are generated through os.urandom()
|
- IVs are generated through os.urandom()
|
||||||
|
- Keys are ephemeral and derived from an ECDH key exchange on Curve25519
|
||||||
- Unforgeable packet delivery confirmations
|
- Unforgeable packet delivery confirmations
|
||||||
- A variety of supported interface types
|
- A variety of supported interface types
|
||||||
- An intuitive and easy-to-use API
|
- An intuitive and easy-to-use API
|
||||||
@@ -31,9 +32,12 @@ For more info, see [unsigned.io/projects/reticulum](https://unsigned.io/projects
|
|||||||
- Reticulum can handle a few bytes of data or files of many gigabytes
|
- Reticulum can handle a few bytes of data or files of many gigabytes
|
||||||
- Sequencing, transfer coordination and checksumming is automatic
|
- Sequencing, transfer coordination and checksumming is automatic
|
||||||
- The API is very easy to use, and provides transfer progress
|
- The API is very easy to use, and provides transfer progress
|
||||||
|
- Efficient link establishment
|
||||||
|
- Total bandwidth cost of setting up a link is 3 packets totalling 240 bytes
|
||||||
|
- Low cost of keeping links open at only 0.62 bits per second
|
||||||
|
|
||||||
## Where can Reticulum be used?
|
## Where can Reticulum be used?
|
||||||
On practically any hardware that can support at least a half-duplex channel with 1.000 bits per second throughput, and an MTU of 500 bytes. Data radios, modems, LoRa radios, serial lines, AX.25 TNCs, amateur radio digital modes, ad-hoc WiFi, free-space optical links and similar systems are all examples of the types of interfaces Reticulum was designed for.
|
Over practically any medium that can support at least a half-duplex channel with 1.000 bits per second throughput, and an MTU of 500 bytes. Data radios, modems, LoRa radios, serial lines, AX.25 TNCs, amateur radio digital modes, ad-hoc WiFi, free-space optical links and similar systems are all examples of the types of interfaces Reticulum was designed for.
|
||||||
|
|
||||||
An open-source LoRa-based interface called [RNode](https://unsigned.io/projects/rnode/) has been designed specifically for use with Reticulum. It is possible to build yourself, or it can be purchased as a complete transceiver that just needs a USB connection to the host.
|
An open-source LoRa-based interface called [RNode](https://unsigned.io/projects/rnode/) has been designed specifically for use with Reticulum. It is possible to build yourself, or it can be purchased as a complete transceiver that just needs a USB connection to the host.
|
||||||
|
|
||||||
|
|||||||
+13
-21
@@ -5,9 +5,6 @@ import RNS
|
|||||||
from cryptography.fernet import Fernet
|
from cryptography.fernet import Fernet
|
||||||
from cryptography.hazmat.primitives import hashes
|
from cryptography.hazmat.primitives import hashes
|
||||||
from cryptography.hazmat.backends import default_backend
|
from cryptography.hazmat.backends import default_backend
|
||||||
from cryptography.hazmat.primitives import serialization
|
|
||||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
|
||||||
from cryptography.hazmat.primitives.asymmetric import padding
|
|
||||||
|
|
||||||
class Callbacks:
|
class Callbacks:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -31,9 +28,6 @@ class Destination:
|
|||||||
:param \*aspects: Any non-zero number of string arguments.
|
:param \*aspects: Any non-zero number of string arguments.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
KEYSIZE = RNS.Identity.KEYSIZE;
|
|
||||||
PADDINGSIZE= RNS.Identity.PADDINGSIZE;
|
|
||||||
|
|
||||||
# Constants
|
# Constants
|
||||||
SINGLE = 0x00
|
SINGLE = 0x00
|
||||||
GROUP = 0x01
|
GROUP = 0x01
|
||||||
@@ -139,8 +133,8 @@ class Destination:
|
|||||||
|
|
||||||
def announce(self, app_data=None, path_response=False):
|
def announce(self, app_data=None, path_response=False):
|
||||||
"""
|
"""
|
||||||
Creates an announce packet for this destination and broadcasts it on
|
Creates an announce packet for this destination and broadcasts it on all
|
||||||
all interfaces. Application specific data can be added to the announce.
|
relevant interfaces. Application specific data can be added to the announce.
|
||||||
|
|
||||||
:param app_data: *bytes* containing the app_data.
|
:param app_data: *bytes* containing the app_data.
|
||||||
:param path_response: Internal flag used by :ref:`RNS.Transport<api-transport>`. Ignore.
|
:param path_response: Internal flag used by :ref:`RNS.Transport<api-transport>`. Ignore.
|
||||||
@@ -162,10 +156,7 @@ class Destination:
|
|||||||
|
|
||||||
signature = self.identity.sign(signed_data)
|
signature = self.identity.sign(signed_data)
|
||||||
|
|
||||||
# TODO: Check if this could be optimised by only
|
announce_data = self.identity.get_public_key()+random_hash+signature
|
||||||
# carrying the hash in the destination field, not
|
|
||||||
# also redundantly inside the signed blob as here
|
|
||||||
announce_data = self.hash+self.identity.get_public_key()+random_hash+signature
|
|
||||||
|
|
||||||
if app_data != None:
|
if app_data != None:
|
||||||
announce_data += app_data
|
announce_data += app_data
|
||||||
@@ -178,7 +169,7 @@ class Destination:
|
|||||||
RNS.Packet(self, announce_data, RNS.Packet.ANNOUNCE, context = announce_context).send()
|
RNS.Packet(self, announce_data, RNS.Packet.ANNOUNCE, context = announce_context).send()
|
||||||
|
|
||||||
|
|
||||||
def link_established_callback(self, callback):
|
def set_link_established_callback(self, callback):
|
||||||
"""
|
"""
|
||||||
Registers a function to be called when a link has been established to
|
Registers a function to be called when a link has been established to
|
||||||
this destination.
|
this destination.
|
||||||
@@ -187,7 +178,7 @@ class Destination:
|
|||||||
"""
|
"""
|
||||||
self.callbacks.link_established = callback
|
self.callbacks.link_established = callback
|
||||||
|
|
||||||
def packet_callback(self, callback):
|
def set_packet_callback(self, callback):
|
||||||
"""
|
"""
|
||||||
Registers a function to be called when a packet has been received by
|
Registers a function to be called when a packet has been received by
|
||||||
this destination.
|
this destination.
|
||||||
@@ -196,7 +187,7 @@ class Destination:
|
|||||||
"""
|
"""
|
||||||
self.callbacks.packet = callback
|
self.callbacks.packet = callback
|
||||||
|
|
||||||
def proof_requested_callback(self, callback):
|
def set_proof_requested_callback(self, callback):
|
||||||
"""
|
"""
|
||||||
Registers a function to be called when a proof has been requested for
|
Registers a function to be called when a proof has been requested for
|
||||||
a packet sent to this destination. Allows control over when and if
|
a packet sent to this destination. Allows control over when and if
|
||||||
@@ -218,11 +209,12 @@ class Destination:
|
|||||||
self.proof_strategy = proof_strategy
|
self.proof_strategy = proof_strategy
|
||||||
|
|
||||||
def receive(self, packet):
|
def receive(self, packet):
|
||||||
|
if packet.packet_type == RNS.Packet.LINKREQUEST:
|
||||||
|
plaintext = packet.data
|
||||||
|
self.incoming_link_request(plaintext, packet)
|
||||||
|
else:
|
||||||
plaintext = self.decrypt(packet.data)
|
plaintext = self.decrypt(packet.data)
|
||||||
if plaintext != None:
|
if plaintext != None:
|
||||||
if packet.packet_type == RNS.Packet.LINKREQUEST:
|
|
||||||
self.incoming_link_request(plaintext, packet)
|
|
||||||
|
|
||||||
if packet.packet_type == RNS.Packet.DATA:
|
if packet.packet_type == RNS.Packet.DATA:
|
||||||
if self.callbacks.packet != None:
|
if self.callbacks.packet != None:
|
||||||
self.callbacks.packet(plaintext, packet)
|
self.callbacks.packet(plaintext, packet)
|
||||||
@@ -245,8 +237,8 @@ class Destination:
|
|||||||
raise TypeError("A single destination holds keys through an Identity instance")
|
raise TypeError("A single destination holds keys through an Identity instance")
|
||||||
|
|
||||||
if self.type == Destination.GROUP:
|
if self.type == Destination.GROUP:
|
||||||
self.prv_bytes = Fernet.generate_key()
|
self.prv_bytes = base64.urlsafe_b64decode(Fernet.generate_key())
|
||||||
self.prv = Fernet(self.prv_bytes)
|
self.prv = Fernet(base64.urlsafe_b64encode(self.prv_bytes))
|
||||||
|
|
||||||
|
|
||||||
def get_private_key(self):
|
def get_private_key(self):
|
||||||
@@ -278,7 +270,7 @@ class Destination:
|
|||||||
|
|
||||||
if self.type == Destination.GROUP:
|
if self.type == Destination.GROUP:
|
||||||
self.prv_bytes = key
|
self.prv_bytes = key
|
||||||
self.prv = Fernet(self.prv_bytes)
|
self.prv = Fernet(base64.urlsafe_b64encode(self.prv_bytes))
|
||||||
|
|
||||||
def load_public_key(self, key):
|
def load_public_key(self, key):
|
||||||
if self.type != Destination.SINGLE:
|
if self.type != Destination.SINGLE:
|
||||||
|
|||||||
+157
-113
@@ -4,14 +4,15 @@ import os
|
|||||||
import RNS
|
import RNS
|
||||||
import time
|
import time
|
||||||
import atexit
|
import atexit
|
||||||
|
import base64
|
||||||
from .vendor import umsgpack as umsgpack
|
from .vendor import umsgpack as umsgpack
|
||||||
from cryptography.hazmat.primitives import hashes
|
|
||||||
from cryptography.hazmat.backends import default_backend
|
from cryptography.hazmat.backends import default_backend
|
||||||
|
from cryptography.hazmat.primitives import hashes
|
||||||
from cryptography.hazmat.primitives import serialization
|
from cryptography.hazmat.primitives import serialization
|
||||||
from cryptography.hazmat.primitives.serialization import load_der_public_key
|
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey, Ed25519PublicKey
|
||||||
from cryptography.hazmat.primitives.serialization import load_der_private_key
|
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey, X25519PublicKey
|
||||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
|
||||||
from cryptography.hazmat.primitives.asymmetric import padding
|
from cryptography.fernet import Fernet
|
||||||
|
|
||||||
class Identity:
|
class Identity:
|
||||||
"""
|
"""
|
||||||
@@ -19,26 +20,29 @@ class Identity:
|
|||||||
for encryption, decryption, signatures and verification, and is the basis
|
for encryption, decryption, signatures and verification, and is the basis
|
||||||
for all encrypted communication over Reticulum networks.
|
for all encrypted communication over Reticulum networks.
|
||||||
|
|
||||||
:param public_only: Specifies whether this destination only holds a public key.
|
:param create_keys: Specifies whether new encryption and signing keys should be generated.
|
||||||
"""
|
"""
|
||||||
KEYSIZE = 1024
|
|
||||||
|
CURVE = "Curve25519"
|
||||||
"""
|
"""
|
||||||
RSA key size in bits.
|
The curve used for Elliptic Curve DH key exchanges
|
||||||
|
"""
|
||||||
|
|
||||||
|
KEYSIZE = 256*2
|
||||||
|
"""
|
||||||
|
X25519 key size in bits. A complete key is the concatenation of a 256 bit encryption key, and a 256 bit signing key.
|
||||||
"""
|
"""
|
||||||
DERKEYSIZE = KEYSIZE+272
|
|
||||||
|
|
||||||
# Non-configurable constants
|
# Non-configurable constants
|
||||||
PADDINGSIZE = 336 # In bits
|
AES_HMAC_OVERHEAD = 58 # In bytes
|
||||||
|
AES128_BLOCKSIZE = 16 # In bytes
|
||||||
HASHLENGTH = 256 # In bits
|
HASHLENGTH = 256 # In bits
|
||||||
SIGLENGTH = KEYSIZE
|
SIGLENGTH = KEYSIZE # In bits
|
||||||
|
|
||||||
ENCRYPT_CHUNKSIZE = (KEYSIZE-PADDINGSIZE)//8
|
|
||||||
DECRYPT_CHUNKSIZE = KEYSIZE//8
|
|
||||||
|
|
||||||
TRUNCATED_HASHLENGTH = 80 # In bits
|
TRUNCATED_HASHLENGTH = 80 # In bits
|
||||||
"""
|
"""
|
||||||
Constant specifying the truncated hash length (in bits) used by Reticulum
|
Constant specifying the truncated hash length (in bits) used by Reticulum
|
||||||
for addressable hashes. Non-configurable.
|
for addressable hashes and other purposes. Non-configurable.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Storage
|
# Storage
|
||||||
@@ -46,6 +50,9 @@ class Identity:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def remember(packet_hash, destination_hash, public_key, app_data = None):
|
def remember(packet_hash, destination_hash, public_key, app_data = None):
|
||||||
|
if len(public_key) != Identity.KEYSIZE//8:
|
||||||
|
raise TypeError("Can't remember "+RNS.prettyhexrep(destination_hash)+", the public key size of "+str(len(public_key))+" is not valid.", RNS.LOG_ERROR)
|
||||||
|
else:
|
||||||
Identity.known_destinations[destination_hash] = [time.time(), packet_hash, public_key, app_data]
|
Identity.known_destinations[destination_hash] = [time.time(), packet_hash, public_key, app_data]
|
||||||
|
|
||||||
|
|
||||||
@@ -60,7 +67,7 @@ class Identity:
|
|||||||
RNS.log("Searching for "+RNS.prettyhexrep(destination_hash)+"...", RNS.LOG_EXTREME)
|
RNS.log("Searching for "+RNS.prettyhexrep(destination_hash)+"...", RNS.LOG_EXTREME)
|
||||||
if destination_hash in Identity.known_destinations:
|
if destination_hash in Identity.known_destinations:
|
||||||
identity_data = Identity.known_destinations[destination_hash]
|
identity_data = Identity.known_destinations[destination_hash]
|
||||||
identity = Identity(public_only=True)
|
identity = Identity(create_keys=False)
|
||||||
identity.load_public_key(identity_data[2])
|
identity.load_public_key(identity_data[2])
|
||||||
identity.app_data = identity_data[3]
|
identity.app_data = identity_data[3]
|
||||||
RNS.log("Found "+RNS.prettyhexrep(destination_hash)+" in known destinations", RNS.LOG_EXTREME)
|
RNS.log("Found "+RNS.prettyhexrep(destination_hash)+" in known destinations", RNS.LOG_EXTREME)
|
||||||
@@ -145,19 +152,19 @@ class Identity:
|
|||||||
if packet.packet_type == RNS.Packet.ANNOUNCE:
|
if packet.packet_type == RNS.Packet.ANNOUNCE:
|
||||||
RNS.log("Validating announce from "+RNS.prettyhexrep(packet.destination_hash), RNS.LOG_DEBUG)
|
RNS.log("Validating announce from "+RNS.prettyhexrep(packet.destination_hash), RNS.LOG_DEBUG)
|
||||||
destination_hash = packet.destination_hash
|
destination_hash = packet.destination_hash
|
||||||
public_key = packet.data[10:Identity.DERKEYSIZE//8+10]
|
public_key = packet.data[:Identity.KEYSIZE//8]
|
||||||
random_hash = packet.data[Identity.DERKEYSIZE//8+10:Identity.DERKEYSIZE//8+20]
|
random_hash = packet.data[Identity.KEYSIZE//8:Identity.KEYSIZE//8+10]
|
||||||
signature = packet.data[Identity.DERKEYSIZE//8+20:Identity.DERKEYSIZE//8+20+Identity.KEYSIZE//8]
|
signature = packet.data[Identity.KEYSIZE//8+10:Identity.KEYSIZE//8+10+Identity.KEYSIZE//8]
|
||||||
app_data = b""
|
app_data = b""
|
||||||
if len(packet.data) > Identity.DERKEYSIZE//8+20+Identity.KEYSIZE//8:
|
if len(packet.data) > Identity.KEYSIZE//8+10+Identity.KEYSIZE//8:
|
||||||
app_data = packet.data[Identity.DERKEYSIZE//8+20+Identity.KEYSIZE//8:]
|
app_data = packet.data[Identity.KEYSIZE//8+10+Identity.KEYSIZE//8:]
|
||||||
|
|
||||||
signed_data = destination_hash+public_key+random_hash+app_data
|
signed_data = destination_hash+public_key+random_hash+app_data
|
||||||
|
|
||||||
if not len(packet.data) > Identity.DERKEYSIZE//8+20+Identity.KEYSIZE//8:
|
if not len(packet.data) > Identity.KEYSIZE//8+10+Identity.KEYSIZE//8:
|
||||||
app_data = None
|
app_data = None
|
||||||
|
|
||||||
announced_identity = Identity(public_only=True)
|
announced_identity = Identity(create_keys=False)
|
||||||
announced_identity.load_public_key(public_key)
|
announced_identity.load_public_key(public_key)
|
||||||
|
|
||||||
if announced_identity.pub != None and announced_identity.validate(signature, signed_data):
|
if announced_identity.pub != None and announced_identity.validate(signature, signed_data):
|
||||||
@@ -184,40 +191,71 @@ class Identity:
|
|||||||
:param path: The full path to the saved :ref:`RNS.Identity<api-identity>` data
|
:param path: The full path to the saved :ref:`RNS.Identity<api-identity>` data
|
||||||
:returns: A :ref:`RNS.Identity<api-identity>` instance, or *None* if the loaded data was invalid.
|
:returns: A :ref:`RNS.Identity<api-identity>` instance, or *None* if the loaded data was invalid.
|
||||||
"""
|
"""
|
||||||
identity = Identity(public_only=True)
|
identity = Identity(create_keys=False)
|
||||||
if identity.load(path):
|
if identity.load(path):
|
||||||
return identity
|
return identity
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_bytes(prv_bytes):
|
||||||
|
"""
|
||||||
|
Create a new :ref:`RNS.Identity<api-identity>` instance from *bytes* of private key.
|
||||||
|
Can be used to load previously created and saved identities into Reticulum.
|
||||||
|
|
||||||
def __init__(self,public_only=False):
|
:param prv_bytes: The *bytes* of private a saved private key. **HAZARD!** Never not use this to generate a new key by feeding random data in prv_bytes.
|
||||||
|
:returns: A :ref:`RNS.Identity<api-identity>` instance, or *None* if the *bytes* data was invalid.
|
||||||
|
"""
|
||||||
|
identity = Identity(create_keys=False)
|
||||||
|
if identity.load_private_key(prv_bytes):
|
||||||
|
return identity
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self,create_keys=True):
|
||||||
# Initialize keys to none
|
# Initialize keys to none
|
||||||
self.prv = None
|
self.prv = None
|
||||||
self.pub = None
|
|
||||||
self.prv_bytes = None
|
self.prv_bytes = None
|
||||||
|
self.sig_prv = None
|
||||||
|
self.sig_prv_bytes = None
|
||||||
|
|
||||||
|
self.pub = None
|
||||||
self.pub_bytes = None
|
self.pub_bytes = None
|
||||||
|
self.sig_pub = None
|
||||||
|
self.sig_pub_bytes = None
|
||||||
|
|
||||||
self.hash = None
|
self.hash = None
|
||||||
self.hexhash = None
|
self.hexhash = None
|
||||||
|
|
||||||
if not public_only:
|
if create_keys:
|
||||||
self.create_keys()
|
self.create_keys()
|
||||||
|
|
||||||
def create_keys(self):
|
def create_keys(self):
|
||||||
self.prv = rsa.generate_private_key(
|
self.prv = X25519PrivateKey.generate()
|
||||||
public_exponent=65537,
|
|
||||||
key_size=Identity.KEYSIZE,
|
|
||||||
backend=default_backend()
|
|
||||||
)
|
|
||||||
self.prv_bytes = self.prv.private_bytes(
|
self.prv_bytes = self.prv.private_bytes(
|
||||||
encoding=serialization.Encoding.DER,
|
encoding=serialization.Encoding.Raw,
|
||||||
format=serialization.PrivateFormat.PKCS8,
|
format=serialization.PrivateFormat.Raw,
|
||||||
encryption_algorithm=serialization.NoEncryption()
|
encryption_algorithm=serialization.NoEncryption()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.sig_prv = Ed25519PrivateKey.generate()
|
||||||
|
self.sig_prv_bytes = self.sig_prv.private_bytes(
|
||||||
|
encoding=serialization.Encoding.Raw,
|
||||||
|
format=serialization.PrivateFormat.Raw,
|
||||||
|
encryption_algorithm=serialization.NoEncryption()
|
||||||
|
)
|
||||||
|
|
||||||
self.pub = self.prv.public_key()
|
self.pub = self.prv.public_key()
|
||||||
self.pub_bytes = self.pub.public_bytes(
|
self.pub_bytes = self.pub.public_bytes(
|
||||||
encoding=serialization.Encoding.DER,
|
encoding=serialization.Encoding.Raw,
|
||||||
format=serialization.PublicFormat.SubjectPublicKeyInfo
|
format=serialization.PublicFormat.Raw
|
||||||
|
)
|
||||||
|
|
||||||
|
self.sig_pub = self.sig_prv.public_key()
|
||||||
|
self.sig_pub_bytes = self.sig_pub.public_bytes(
|
||||||
|
encoding=serialization.Encoding.Raw,
|
||||||
|
format=serialization.PublicFormat.Raw
|
||||||
)
|
)
|
||||||
|
|
||||||
self.update_hashes()
|
self.update_hashes()
|
||||||
@@ -228,13 +266,13 @@ class Identity:
|
|||||||
"""
|
"""
|
||||||
:returns: The private key as *bytes*
|
:returns: The private key as *bytes*
|
||||||
"""
|
"""
|
||||||
return self.prv_bytes
|
return self.prv_bytes+self.sig_prv_bytes
|
||||||
|
|
||||||
def get_public_key(self):
|
def get_public_key(self):
|
||||||
"""
|
"""
|
||||||
:returns: The public key as *bytes*
|
:returns: The public key as *bytes*
|
||||||
"""
|
"""
|
||||||
return self.pub_bytes
|
return self.pub_bytes+self.sig_pub_bytes
|
||||||
|
|
||||||
def load_private_key(self, prv_bytes):
|
def load_private_key(self, prv_bytes):
|
||||||
"""
|
"""
|
||||||
@@ -244,42 +282,53 @@ class Identity:
|
|||||||
:returns: True if the key was loaded, otherwise False.
|
:returns: True if the key was loaded, otherwise False.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
self.prv_bytes = prv_bytes
|
self.prv_bytes = prv_bytes[:Identity.KEYSIZE//8//2]
|
||||||
self.prv = serialization.load_der_private_key(
|
self.prv = X25519PrivateKey.from_private_bytes(self.prv_bytes)
|
||||||
self.prv_bytes,
|
self.sig_prv_bytes = prv_bytes[Identity.KEYSIZE//8//2:]
|
||||||
password=None,
|
self.sig_prv = Ed25519PrivateKey.from_private_bytes(self.sig_prv_bytes)
|
||||||
backend=default_backend()
|
|
||||||
)
|
|
||||||
self.pub = self.prv.public_key()
|
self.pub = self.prv.public_key()
|
||||||
self.pub_bytes = self.pub.public_bytes(
|
self.pub_bytes = self.pub.public_bytes(
|
||||||
encoding=serialization.Encoding.DER,
|
encoding=serialization.Encoding.Raw,
|
||||||
format=serialization.PublicFormat.SubjectPublicKeyInfo
|
format=serialization.PublicFormat.Raw
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.sig_pub = self.sig_prv.public_key()
|
||||||
|
self.sig_pub_bytes = self.sig_pub.public_bytes(
|
||||||
|
encoding=serialization.Encoding.Raw,
|
||||||
|
format=serialization.PublicFormat.Raw
|
||||||
|
)
|
||||||
|
|
||||||
self.update_hashes()
|
self.update_hashes()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
raise e
|
||||||
RNS.log("Failed to load identity key", RNS.LOG_ERROR)
|
RNS.log("Failed to load identity key", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def load_public_key(self, key):
|
def load_public_key(self, pub_bytes):
|
||||||
"""
|
"""
|
||||||
Load a public key into the instance.
|
Load a public key into the instance.
|
||||||
|
|
||||||
:param prv_bytes: The public key as *bytes*.
|
:param pub_bytes: The public key as *bytes*.
|
||||||
:returns: True if the key was loaded, otherwise False.
|
:returns: True if the key was loaded, otherwise False.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
self.pub_bytes = key
|
self.pub_bytes = pub_bytes[:Identity.KEYSIZE//8//2]
|
||||||
self.pub = load_der_public_key(self.pub_bytes, backend=default_backend())
|
self.sig_pub_bytes = pub_bytes[Identity.KEYSIZE//8//2:]
|
||||||
|
|
||||||
|
self.pub = X25519PublicKey.from_public_bytes(self.pub_bytes)
|
||||||
|
self.sig_pub = Ed25519PublicKey.from_public_bytes(self.sig_pub_bytes)
|
||||||
|
|
||||||
self.update_hashes()
|
self.update_hashes()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while loading public key, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log("Error while loading public key, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
|
|
||||||
def update_hashes(self):
|
def update_hashes(self):
|
||||||
self.hash = Identity.truncated_hash(self.pub_bytes)
|
self.hash = Identity.truncated_hash(self.get_public_key())
|
||||||
self.hexhash = self.hash.hex()
|
self.hexhash = self.hash.hex()
|
||||||
|
|
||||||
def to_file(self, path):
|
def to_file(self, path):
|
||||||
@@ -293,7 +342,7 @@ class Identity:
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
with open(path, "wb") as key_file:
|
with open(path, "wb") as key_file:
|
||||||
key_file.write(self.prv_bytes)
|
key_file.write(self.get_public_key())
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -310,71 +359,78 @@ class Identity:
|
|||||||
RNS.log("Error while loading identity from "+str(path), RNS.LOG_ERROR)
|
RNS.log("Error while loading identity from "+str(path), RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e))
|
RNS.log("The contained exception was: "+str(e))
|
||||||
|
|
||||||
|
def get_salt(self):
|
||||||
|
return self.hash
|
||||||
|
|
||||||
|
def get_context(self):
|
||||||
|
return None
|
||||||
|
|
||||||
def encrypt(self, plaintext):
|
def encrypt(self, plaintext):
|
||||||
"""
|
"""
|
||||||
Encrypts information for the identity.
|
Encrypts information for the identity.
|
||||||
|
|
||||||
:param plaintext: The plaintext to be encrypted as *bytes*.
|
:param plaintext: The plaintext to be encrypted as *bytes*.
|
||||||
:returns: Ciphertext as *bytes*.
|
:returns: Ciphertext token as *bytes*.
|
||||||
:raises: *KeyError* if the instance does not hold a public key
|
:raises: *KeyError* if the instance does not hold a public key.
|
||||||
"""
|
"""
|
||||||
if self.pub != None:
|
if self.pub != None:
|
||||||
chunksize = Identity.ENCRYPT_CHUNKSIZE
|
ephemeral_key = X25519PrivateKey.generate()
|
||||||
chunks = int(math.ceil(len(plaintext)/(float(chunksize))))
|
ephemeral_pub_bytes = ephemeral_key.public_key().public_bytes(
|
||||||
|
encoding=serialization.Encoding.Raw,
|
||||||
ciphertext = b"";
|
format=serialization.PublicFormat.Raw
|
||||||
for chunk in range(chunks):
|
|
||||||
start = chunk*chunksize
|
|
||||||
end = (chunk+1)*chunksize
|
|
||||||
if (chunk+1)*chunksize > len(plaintext):
|
|
||||||
end = len(plaintext)
|
|
||||||
|
|
||||||
ciphertext += self.pub.encrypt(
|
|
||||||
plaintext[start:end],
|
|
||||||
padding.OAEP(
|
|
||||||
mgf=padding.MGF1(algorithm=hashes.SHA1()),
|
|
||||||
algorithm=hashes.SHA1(),
|
|
||||||
label=None
|
|
||||||
)
|
)
|
||||||
)
|
|
||||||
return ciphertext
|
shared_key = ephemeral_key.exchange(self.pub)
|
||||||
|
derived_key = derived_key = HKDF(
|
||||||
|
algorithm=hashes.SHA256(),
|
||||||
|
length=32,
|
||||||
|
salt=self.get_salt(),
|
||||||
|
info=self.get_context(),
|
||||||
|
).derive(shared_key)
|
||||||
|
|
||||||
|
fernet = Fernet(base64.urlsafe_b64encode(derived_key))
|
||||||
|
ciphertext = base64.urlsafe_b64decode(fernet.encrypt(plaintext))
|
||||||
|
token = ephemeral_pub_bytes+ciphertext
|
||||||
|
|
||||||
|
return token
|
||||||
else:
|
else:
|
||||||
raise KeyError("Encryption failed because identity does not hold a public key")
|
raise KeyError("Encryption failed because identity does not hold a public key")
|
||||||
|
|
||||||
|
|
||||||
def decrypt(self, ciphertext):
|
def decrypt(self, ciphertext_token):
|
||||||
"""
|
"""
|
||||||
Decrypts information for the identity.
|
Decrypts information for the identity.
|
||||||
|
|
||||||
:param ciphertext: The ciphertext to be decrypted as *bytes*.
|
:param ciphertext: The ciphertext to be decrypted as *bytes*.
|
||||||
:returns: Plaintext as *bytes*, or *None* if decryption fails.
|
:returns: Plaintext as *bytes*, or *None* if decryption fails.
|
||||||
:raises: *KeyError* if the instance does not hold a private key
|
:raises: *KeyError* if the instance does not hold a private key.
|
||||||
"""
|
"""
|
||||||
if self.prv != None:
|
if self.prv != None:
|
||||||
|
if len(ciphertext_token) > Identity.KEYSIZE//8//2:
|
||||||
plaintext = None
|
plaintext = None
|
||||||
try:
|
try:
|
||||||
chunksize = Identity.DECRYPT_CHUNKSIZE
|
peer_pub_bytes = ciphertext_token[:Identity.KEYSIZE//8//2]
|
||||||
chunks = int(math.ceil(len(ciphertext)/(float(chunksize))))
|
peer_pub = X25519PublicKey.from_public_bytes(peer_pub_bytes)
|
||||||
|
|
||||||
plaintext = b"";
|
shared_key = self.prv.exchange(peer_pub)
|
||||||
for chunk in range(chunks):
|
derived_key = derived_key = HKDF(
|
||||||
start = chunk*chunksize
|
algorithm=hashes.SHA256(),
|
||||||
end = (chunk+1)*chunksize
|
length=32,
|
||||||
if (chunk+1)*chunksize > len(ciphertext):
|
salt=self.get_salt(),
|
||||||
end = len(ciphertext)
|
info=self.get_context(),
|
||||||
|
).derive(shared_key)
|
||||||
|
|
||||||
plaintext += self.prv.decrypt(
|
fernet = Fernet(base64.urlsafe_b64encode(derived_key))
|
||||||
ciphertext[start:end],
|
ciphertext = ciphertext_token[Identity.KEYSIZE//8//2:]
|
||||||
padding.OAEP(
|
plaintext = fernet.decrypt(base64.urlsafe_b64encode(ciphertext))
|
||||||
mgf=padding.MGF1(algorithm=hashes.SHA1()),
|
|
||||||
algorithm=hashes.SHA1(),
|
except Exception as e:
|
||||||
label=None
|
RNS.log("Decryption by "+RNS.prettyhexrep(self.hash)+" failed: "+str(e), RNS.LOG_DEBUG)
|
||||||
)
|
|
||||||
)
|
|
||||||
except:
|
|
||||||
RNS.log("Decryption by "+RNS.prettyhexrep(self.hash)+" failed", RNS.LOG_VERBOSE)
|
|
||||||
|
|
||||||
return plaintext;
|
return plaintext;
|
||||||
|
else:
|
||||||
|
RNS.log("Decryption failed because the token size was invalid.", RNS.LOG_DEBUG)
|
||||||
|
return None
|
||||||
else:
|
else:
|
||||||
raise KeyError("Decryption failed because identity does not hold a private key")
|
raise KeyError("Decryption failed because identity does not hold a private key")
|
||||||
|
|
||||||
@@ -385,18 +441,14 @@ class Identity:
|
|||||||
|
|
||||||
:param message: The message to be signed as *bytes*.
|
:param message: The message to be signed as *bytes*.
|
||||||
:returns: Signature as *bytes*.
|
:returns: Signature as *bytes*.
|
||||||
:raises: *KeyError* if the instance does not hold a private key
|
:raises: *KeyError* if the instance does not hold a private key.
|
||||||
"""
|
"""
|
||||||
if self.prv != None:
|
if self.sig_prv != None:
|
||||||
signature = self.prv.sign(
|
try:
|
||||||
message,
|
return self.sig_prv.sign(message)
|
||||||
padding.PSS(
|
except Exception as e:
|
||||||
mgf=padding.MGF1(hashes.SHA256()),
|
RNS.log("The identity "+str(self)+" could not sign the requested message. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
salt_length=padding.PSS.MAX_LENGTH
|
raise e
|
||||||
),
|
|
||||||
hashes.SHA256()
|
|
||||||
)
|
|
||||||
return signature
|
|
||||||
else:
|
else:
|
||||||
raise KeyError("Signing failed because identity does not hold a private key")
|
raise KeyError("Signing failed because identity does not hold a private key")
|
||||||
|
|
||||||
@@ -407,19 +459,11 @@ class Identity:
|
|||||||
:param signature: The signature to be validated as *bytes*.
|
:param signature: The signature to be validated as *bytes*.
|
||||||
:param message: The message to be validated as *bytes*.
|
:param message: The message to be validated as *bytes*.
|
||||||
:returns: True if the signature is valid, otherwise False.
|
:returns: True if the signature is valid, otherwise False.
|
||||||
:raises: *KeyError* if the instance does not hold a public key
|
:raises: *KeyError* if the instance does not hold a public key.
|
||||||
"""
|
"""
|
||||||
if self.pub != None:
|
if self.pub != None:
|
||||||
try:
|
try:
|
||||||
self.pub.verify(
|
self.sig_pub.verify(signature, message)
|
||||||
signature,
|
|
||||||
message,
|
|
||||||
padding.PSS(
|
|
||||||
mgf=padding.MGF1(hashes.SHA256()),
|
|
||||||
salt_length=padding.PSS.MAX_LENGTH
|
|
||||||
),
|
|
||||||
hashes.SHA256()
|
|
||||||
)
|
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return False
|
return False
|
||||||
|
|||||||
+22
-29
@@ -33,17 +33,15 @@ class Link:
|
|||||||
:param peer_pub_bytes: Internal use, ignore this argument.
|
:param peer_pub_bytes: Internal use, ignore this argument.
|
||||||
:param peer_sig_pub_bytes: Internal use, ignore this argument.
|
:param peer_sig_pub_bytes: Internal use, ignore this argument.
|
||||||
"""
|
"""
|
||||||
CURVE = "Curve25519"
|
CURVE = RNS.Identity.CURVE
|
||||||
"""
|
"""
|
||||||
The curve used for Elliptic Curve DH key exchanges
|
The curve used for Elliptic Curve DH key exchanges
|
||||||
"""
|
"""
|
||||||
|
|
||||||
ECPUBSIZE = 32+32
|
ECPUBSIZE = 32+32
|
||||||
BLOCKSIZE = 16
|
|
||||||
KEYSIZE = 32
|
KEYSIZE = 32
|
||||||
|
|
||||||
AES_HMAC_OVERHEAD = 58
|
MDU = math.floor((RNS.Reticulum.MDU-RNS.Identity.AES_HMAC_OVERHEAD)/RNS.Identity.AES128_BLOCKSIZE)*RNS.Identity.AES128_BLOCKSIZE - 1
|
||||||
MDU = math.floor((RNS.Reticulum.MDU-AES_HMAC_OVERHEAD)/BLOCKSIZE)*BLOCKSIZE - 1
|
|
||||||
|
|
||||||
# TODO: This should not be hardcoded,
|
# TODO: This should not be hardcoded,
|
||||||
# but calculated from something like
|
# but calculated from something like
|
||||||
@@ -54,7 +52,7 @@ class Link:
|
|||||||
"""
|
"""
|
||||||
TIMEOUT_FACTOR = 3
|
TIMEOUT_FACTOR = 3
|
||||||
STALE_GRACE = 2
|
STALE_GRACE = 2
|
||||||
KEEPALIVE = 180
|
KEEPALIVE = 360
|
||||||
"""
|
"""
|
||||||
Interval for sending keep-alive packets on established links in seconds.
|
Interval for sending keep-alive packets on established links in seconds.
|
||||||
"""
|
"""
|
||||||
@@ -90,11 +88,6 @@ class Link:
|
|||||||
link.last_inbound = time.time()
|
link.last_inbound = time.time()
|
||||||
link.start_watchdog()
|
link.start_watchdog()
|
||||||
|
|
||||||
# TODO: Why was link_established callback here? Seems weird
|
|
||||||
# to call this before RTT packet has been received
|
|
||||||
#if self.owner.callbacks.link_established != None:
|
|
||||||
# self.owner.callbacks.link_established(link)
|
|
||||||
|
|
||||||
RNS.log("Incoming link request "+str(link)+" accepted", RNS.LOG_VERBOSE)
|
RNS.log("Incoming link request "+str(link)+" accepted", RNS.LOG_VERBOSE)
|
||||||
return link
|
return link
|
||||||
|
|
||||||
@@ -135,14 +128,15 @@ class Link:
|
|||||||
self.__encryption_disabled = False
|
self.__encryption_disabled = False
|
||||||
if self.destination == None:
|
if self.destination == None:
|
||||||
self.initiator = False
|
self.initiator = False
|
||||||
|
self.prv = self.owner.identity.prv
|
||||||
|
self.sig_prv = self.owner.identity.sig_prv
|
||||||
else:
|
else:
|
||||||
self.initiator = True
|
self.initiator = True
|
||||||
|
|
||||||
self.fernet = None
|
|
||||||
|
|
||||||
self.prv = X25519PrivateKey.generate()
|
self.prv = X25519PrivateKey.generate()
|
||||||
self.sig_prv = Ed25519PrivateKey.generate()
|
self.sig_prv = Ed25519PrivateKey.generate()
|
||||||
|
|
||||||
|
self.fernet = None
|
||||||
|
|
||||||
self.pub = self.prv.public_key()
|
self.pub = self.prv.public_key()
|
||||||
self.pub_bytes = self.pub.public_bytes(
|
self.pub_bytes = self.pub.public_bytes(
|
||||||
encoding=serialization.Encoding.Raw,
|
encoding=serialization.Encoding.Raw,
|
||||||
@@ -162,10 +156,14 @@ class Link:
|
|||||||
self.load_peer(peer_pub_bytes, peer_sig_pub_bytes)
|
self.load_peer(peer_pub_bytes, peer_sig_pub_bytes)
|
||||||
|
|
||||||
if (self.initiator):
|
if (self.initiator):
|
||||||
|
peer_pub_bytes = self.destination.identity.get_public_key()[:Link.ECPUBSIZE//2]
|
||||||
|
peer_sig_pub_bytes = self.destination.identity.get_public_key()[Link.ECPUBSIZE//2:Link.ECPUBSIZE]
|
||||||
self.request_data = self.pub_bytes+self.sig_pub_bytes
|
self.request_data = self.pub_bytes+self.sig_pub_bytes
|
||||||
self.packet = RNS.Packet(destination, self.request_data, packet_type=RNS.Packet.LINKREQUEST)
|
self.packet = RNS.Packet(destination, self.request_data, packet_type=RNS.Packet.LINKREQUEST)
|
||||||
self.packet.pack()
|
self.packet.pack()
|
||||||
self.set_link_id(self.packet)
|
self.set_link_id(self.packet)
|
||||||
|
self.load_peer(peer_pub_bytes, peer_sig_pub_bytes)
|
||||||
|
self.handshake()
|
||||||
RNS.Transport.register_link(self)
|
RNS.Transport.register_link(self)
|
||||||
self.request_time = time.time()
|
self.request_time = time.time()
|
||||||
self.start_watchdog()
|
self.start_watchdog()
|
||||||
@@ -202,7 +200,7 @@ class Link:
|
|||||||
signed_data = self.link_id+self.pub_bytes+self.sig_pub_bytes
|
signed_data = self.link_id+self.pub_bytes+self.sig_pub_bytes
|
||||||
signature = self.owner.identity.sign(signed_data)
|
signature = self.owner.identity.sign(signed_data)
|
||||||
|
|
||||||
proof_data = self.pub_bytes+self.sig_pub_bytes+signature
|
proof_data = signature
|
||||||
proof = RNS.Packet(self, proof_data, packet_type=RNS.Packet.PROOF, context=RNS.Packet.LRPROOF)
|
proof = RNS.Packet(self, proof_data, packet_type=RNS.Packet.PROOF, context=RNS.Packet.LRPROOF)
|
||||||
proof.send()
|
proof.send()
|
||||||
self.had_outbound()
|
self.had_outbound()
|
||||||
@@ -221,15 +219,11 @@ class Link:
|
|||||||
self.had_outbound()
|
self.had_outbound()
|
||||||
|
|
||||||
def validate_proof(self, packet):
|
def validate_proof(self, packet):
|
||||||
if self.initiator and len(packet.data) == Link.ECPUBSIZE+RNS.Identity.KEYSIZE//8:
|
if self.initiator and len(packet.data) == RNS.Identity.SIGLENGTH//8:
|
||||||
peer_pub_bytes = packet.data[:Link.ECPUBSIZE//2]
|
signed_data = self.link_id+self.peer_pub_bytes+self.peer_sig_pub_bytes
|
||||||
peer_sig_pub_bytes = packet.data[Link.ECPUBSIZE//2:Link.ECPUBSIZE]
|
signature = packet.data[:RNS.Identity.SIGLENGTH//8]
|
||||||
signed_data = self.link_id+peer_pub_bytes+peer_sig_pub_bytes
|
|
||||||
signature = packet.data[Link.ECPUBSIZE:RNS.Identity.KEYSIZE//8+Link.ECPUBSIZE]
|
|
||||||
|
|
||||||
if self.destination.identity.validate(signature, signed_data):
|
if self.destination.identity.validate(signature, signed_data):
|
||||||
self.load_peer(peer_pub_bytes, peer_sig_pub_bytes)
|
|
||||||
self.handshake()
|
|
||||||
self.rtt = time.time() - self.request_time
|
self.rtt = time.time() - self.request_time
|
||||||
self.attached_interface = packet.receiving_interface
|
self.attached_interface = packet.receiving_interface
|
||||||
RNS.Transport.activate_link(self)
|
RNS.Transport.activate_link(self)
|
||||||
@@ -265,8 +259,7 @@ class Link:
|
|||||||
if self.owner.callbacks.link_established != None:
|
if self.owner.callbacks.link_established != None:
|
||||||
self.owner.callbacks.link_established(self)
|
self.owner.callbacks.link_established(self)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error occurred while processing RTT packet, tearing down link", RNS.LOG_ERROR)
|
RNS.log("Error occurred while processing RTT packet, tearing down link. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
traceback.print_exc()
|
|
||||||
self.teardown()
|
self.teardown()
|
||||||
|
|
||||||
def get_salt(self):
|
def get_salt(self):
|
||||||
@@ -537,13 +530,13 @@ class Link:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def link_established_callback(self, callback):
|
def set_link_established_callback(self, callback):
|
||||||
self.callbacks.link_established = callback
|
self.callbacks.link_established = callback
|
||||||
|
|
||||||
def link_closed_callback(self, callback):
|
def set_link_closed_callback(self, callback):
|
||||||
self.callbacks.link_closed = callback
|
self.callbacks.link_closed = callback
|
||||||
|
|
||||||
def packet_callback(self, callback):
|
def set_packet_callback(self, callback):
|
||||||
"""
|
"""
|
||||||
Registers a function to be called when a packet has been
|
Registers a function to be called when a packet has been
|
||||||
received over this link.
|
received over this link.
|
||||||
@@ -552,7 +545,7 @@ class Link:
|
|||||||
"""
|
"""
|
||||||
self.callbacks.packet = callback
|
self.callbacks.packet = callback
|
||||||
|
|
||||||
def resource_callback(self, callback):
|
def set_resource_callback(self, callback):
|
||||||
"""
|
"""
|
||||||
Registers a function to be called when a resource has been
|
Registers a function to be called when a resource has been
|
||||||
advertised over this link. If the function returns *True*
|
advertised over this link. If the function returns *True*
|
||||||
@@ -563,7 +556,7 @@ class Link:
|
|||||||
"""
|
"""
|
||||||
self.callbacks.resource = callback
|
self.callbacks.resource = callback
|
||||||
|
|
||||||
def resource_started_callback(self, callback):
|
def set_resource_started_callback(self, callback):
|
||||||
"""
|
"""
|
||||||
Registers a function to be called when a resource has begun
|
Registers a function to be called when a resource has begun
|
||||||
transferring over this link.
|
transferring over this link.
|
||||||
@@ -572,7 +565,7 @@ class Link:
|
|||||||
"""
|
"""
|
||||||
self.callbacks.resource_started = callback
|
self.callbacks.resource_started = callback
|
||||||
|
|
||||||
def resource_concluded_callback(self, callback):
|
def set_resource_concluded_callback(self, callback):
|
||||||
"""
|
"""
|
||||||
Registers a function to be called when a resource has concluded
|
Registers a function to be called when a resource has concluded
|
||||||
transferring over this link.
|
transferring over this link.
|
||||||
|
|||||||
+29
-10
@@ -6,8 +6,16 @@ import RNS
|
|||||||
|
|
||||||
class Packet:
|
class Packet:
|
||||||
"""
|
"""
|
||||||
The Packet class is used to create packet instances that can be
|
The Packet class is used to create packet instances that can be sent
|
||||||
sent over a Reticulum network.
|
over a Reticulum network. Packets to will automatically be encrypted if
|
||||||
|
they are adressed to a ``RNS.Destination.SINGLE`` destination,
|
||||||
|
``RNS.Destination.GROUP`` destination or a :ref:`RNS.Link<api-link>`.
|
||||||
|
|
||||||
|
For ``RNS.Destination.GROUP`` destinations, Reticulum will use the
|
||||||
|
pre-shared key configured for the destination.
|
||||||
|
|
||||||
|
For ``RNS.Destination.SINGLE`` destinations and :ref:`RNS.Link<api-link>`
|
||||||
|
destinations, reticulum will use ephemeral keys, and offers **Forward Secrecy**.
|
||||||
|
|
||||||
:param destination: A :ref:`RNS.Destination<api-destination>` instance to which the packet will be sent.
|
:param destination: A :ref:`RNS.Destination<api-destination>` instance to which the packet will be sent.
|
||||||
:param data: The data payload to be included in the packet as *bytes*.
|
:param data: The data payload to be included in the packet as *bytes*.
|
||||||
@@ -56,14 +64,21 @@ class Packet:
|
|||||||
|
|
||||||
# This is used to calculate allowable
|
# This is used to calculate allowable
|
||||||
# payload sizes
|
# payload sizes
|
||||||
HEADER_MAXSIZE = 23
|
HEADER_MAXSIZE = RNS.Reticulum.HEADER_MAXSIZE
|
||||||
MDU = RNS.Reticulum.MDU
|
MDU = RNS.Reticulum.MDU
|
||||||
|
|
||||||
# With an MTU of 500, the maximum RSA-encrypted
|
# TODO: Update this
|
||||||
# amount of data we can send in a single packet
|
# With an MTU of 500, the maximum of data we can
|
||||||
# is given by the below calculation; 258 bytes.
|
# send in a single encrypted packet is given by
|
||||||
RSA_MDU = math.floor(MDU/RNS.Identity.DECRYPT_CHUNKSIZE)*RNS.Identity.ENCRYPT_CHUNKSIZE
|
# the below calculation; 383 bytes.
|
||||||
|
ENCRYPTED_MDU = math.floor((RNS.Reticulum.MDU-RNS.Identity.AES_HMAC_OVERHEAD-RNS.Identity.KEYSIZE//16)/RNS.Identity.AES128_BLOCKSIZE)*RNS.Identity.AES128_BLOCKSIZE - 1
|
||||||
|
"""
|
||||||
|
The maximum size of the payload data in a single encrypted packet
|
||||||
|
"""
|
||||||
PLAIN_MDU = MDU
|
PLAIN_MDU = MDU
|
||||||
|
"""
|
||||||
|
The maximum size of the payload data in a single unencrypted packet
|
||||||
|
"""
|
||||||
|
|
||||||
# TODO: This should be calculated
|
# TODO: This should be calculated
|
||||||
# more intelligently
|
# more intelligently
|
||||||
@@ -128,6 +143,9 @@ class Packet:
|
|||||||
if self.packet_type == Packet.ANNOUNCE:
|
if self.packet_type == Packet.ANNOUNCE:
|
||||||
# Announce packets are not encrypted
|
# Announce packets are not encrypted
|
||||||
self.ciphertext = self.data
|
self.ciphertext = self.data
|
||||||
|
elif self.packet_type == Packet.LINKREQUEST:
|
||||||
|
# Link request packets are not encrypted
|
||||||
|
self.ciphertext = self.data
|
||||||
elif self.packet_type == Packet.PROOF and self.context == Packet.RESOURCE_PRF:
|
elif self.packet_type == Packet.PROOF and self.context == Packet.RESOURCE_PRF:
|
||||||
# Resource proofs are not encrypted
|
# Resource proofs are not encrypted
|
||||||
self.ciphertext = self.data
|
self.ciphertext = self.data
|
||||||
@@ -171,6 +189,7 @@ class Packet:
|
|||||||
self.packed = True
|
self.packed = True
|
||||||
self.update_hash()
|
self.update_hash()
|
||||||
|
|
||||||
|
|
||||||
def unpack(self):
|
def unpack(self):
|
||||||
self.flags = self.raw[0]
|
self.flags = self.raw[0]
|
||||||
self.hops = self.raw[1]
|
self.hops = self.raw[1]
|
||||||
@@ -406,7 +425,7 @@ class PacketReceipt:
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def rtt(self):
|
def get_rtt(self):
|
||||||
"""
|
"""
|
||||||
:returns: The round-trip-time in seconds
|
:returns: The round-trip-time in seconds
|
||||||
"""
|
"""
|
||||||
@@ -439,7 +458,7 @@ class PacketReceipt:
|
|||||||
"""
|
"""
|
||||||
self.timeout = float(timeout)
|
self.timeout = float(timeout)
|
||||||
|
|
||||||
def delivery_callback(self, callback):
|
def set_delivery_callback(self, callback):
|
||||||
"""
|
"""
|
||||||
Sets a function that gets called if a successfull delivery has been proven.
|
Sets a function that gets called if a successfull delivery has been proven.
|
||||||
|
|
||||||
@@ -449,7 +468,7 @@ class PacketReceipt:
|
|||||||
|
|
||||||
# Set a function that gets called if the
|
# Set a function that gets called if the
|
||||||
# delivery times out
|
# delivery times out
|
||||||
def timeout_callback(self, callback):
|
def set_timeout_callback(self, callback):
|
||||||
"""
|
"""
|
||||||
Sets a function that gets called if the delivery times out.
|
Sets a function that gets called if the delivery times out.
|
||||||
|
|
||||||
|
|||||||
+2
-5
@@ -17,7 +17,6 @@ class Resource:
|
|||||||
:param link: The :ref:`RNS.Link<api-link>` instance on which to transfer the data.
|
:param link: The :ref:`RNS.Link<api-link>` instance on which to transfer the data.
|
||||||
:param advertise: Whether to automatically advertise the resource. Can be *True* or *False*.
|
:param advertise: Whether to automatically advertise the resource. Can be *True* or *False*.
|
||||||
:param auto_compress: Whether to auto-compress the resource. Can be *True* or *False*.
|
:param auto_compress: Whether to auto-compress the resource. Can be *True* or *False*.
|
||||||
:param auto_compress: Whether the resource must be compressed. Can be *True* or *False*. Used for debugging, will disappear in the future.
|
|
||||||
:param callback: A *callable* with the signature *callback(resource)*. Will be called when the resource transfer concludes.
|
:param callback: A *callable* with the signature *callback(resource)*. Will be called when the resource transfer concludes.
|
||||||
:param progress_callback: A *callable* with the signature *callback(resource)*. Will be called whenever the resource transfer progress is updated.
|
:param progress_callback: A *callable* with the signature *callback(resource)*. Will be called whenever the resource transfer progress is updated.
|
||||||
:param segment_index: Internal use, ignore.
|
:param segment_index: Internal use, ignore.
|
||||||
@@ -134,7 +133,7 @@ class Resource:
|
|||||||
# Create a resource for transmission to a remote destination
|
# Create a resource for transmission to a remote destination
|
||||||
# The data passed can be either a bytes-array or a file opened
|
# The data passed can be either a bytes-array or a file opened
|
||||||
# in binary read mode.
|
# in binary read mode.
|
||||||
def __init__(self, data, link, advertise=True, auto_compress=True, must_compress=False, callback=None, progress_callback=None, segment_index = 1, original_hash = None):
|
def __init__(self, data, link, advertise=True, auto_compress=True, callback=None, progress_callback=None, segment_index = 1, original_hash = None):
|
||||||
data_size = None
|
data_size = None
|
||||||
resource_data = None
|
resource_data = None
|
||||||
if hasattr(data, "read"):
|
if hasattr(data, "read"):
|
||||||
@@ -198,7 +197,7 @@ class Resource:
|
|||||||
self.uncompressed_data = data
|
self.uncompressed_data = data
|
||||||
|
|
||||||
compression_began = time.time()
|
compression_began = time.time()
|
||||||
if must_compress or (auto_compress and len(self.uncompressed_data) < Resource.AUTO_COMPRESS_MAX_SIZE):
|
if (auto_compress and len(self.uncompressed_data) < Resource.AUTO_COMPRESS_MAX_SIZE):
|
||||||
RNS.log("Compressing resource data...", RNS.LOG_DEBUG)
|
RNS.log("Compressing resource data...", RNS.LOG_DEBUG)
|
||||||
self.compressed_data = bz2.compress(self.uncompressed_data)
|
self.compressed_data = bz2.compress(self.uncompressed_data)
|
||||||
RNS.log("Compression completed in "+str(round(time.time()-compression_began, 3))+" seconds", RNS.LOG_DEBUG)
|
RNS.log("Compression completed in "+str(round(time.time()-compression_began, 3))+" seconds", RNS.LOG_DEBUG)
|
||||||
@@ -748,8 +747,6 @@ class Resource:
|
|||||||
:returns: The current progress of the resource transfer as a *float* between 0.0 and 1.0.
|
:returns: The current progress of the resource transfer as a *float* between 0.0 and 1.0.
|
||||||
"""
|
"""
|
||||||
if self.initiator:
|
if self.initiator:
|
||||||
# TODO: Remove
|
|
||||||
# progress = self.sent_parts / len(self.parts)
|
|
||||||
self.processed_parts = (self.segment_index-1)*math.ceil(Resource.MAX_EFFICIENT_SIZE/Resource.SDU)
|
self.processed_parts = (self.segment_index-1)*math.ceil(Resource.MAX_EFFICIENT_SIZE/Resource.SDU)
|
||||||
self.processed_parts += self.sent_parts
|
self.processed_parts += self.sent_parts
|
||||||
self.progress_total_parts = float(self.grand_total_parts)
|
self.progress_total_parts = float(self.grand_total_parts)
|
||||||
|
|||||||
+2
-4
@@ -22,8 +22,6 @@ class Transport:
|
|||||||
|
|
||||||
APP_NAME = "rnstransport"
|
APP_NAME = "rnstransport"
|
||||||
|
|
||||||
# TODO: Document the addition of random windows
|
|
||||||
# and max local rebroadcasts.
|
|
||||||
PATHFINDER_M = 18 # Max hops
|
PATHFINDER_M = 18 # Max hops
|
||||||
PATHFINDER_C = 2.0 # Decay constant
|
PATHFINDER_C = 2.0 # Decay constant
|
||||||
PATHFINDER_R = 1 # Retransmit retries
|
PATHFINDER_R = 1 # Retransmit retries
|
||||||
@@ -108,7 +106,7 @@ class Transport:
|
|||||||
|
|
||||||
# Create transport-specific destinations
|
# Create transport-specific destinations
|
||||||
Transport.path_request_destination = RNS.Destination(None, RNS.Destination.IN, RNS.Destination.PLAIN, Transport.APP_NAME, "path", "request")
|
Transport.path_request_destination = RNS.Destination(None, RNS.Destination.IN, RNS.Destination.PLAIN, Transport.APP_NAME, "path", "request")
|
||||||
Transport.path_request_destination.packet_callback(Transport.path_request_handler)
|
Transport.path_request_destination.set_packet_callback(Transport.path_request_handler)
|
||||||
Transport.control_destinations.append(Transport.path_request_destination)
|
Transport.control_destinations.append(Transport.path_request_destination)
|
||||||
Transport.control_hashes.append(Transport.path_request_destination.hash)
|
Transport.control_hashes.append(Transport.path_request_destination.hash)
|
||||||
|
|
||||||
@@ -652,7 +650,7 @@ class Transport:
|
|||||||
# First, check that the announce is not for a destination
|
# First, check that the announce is not for a destination
|
||||||
# local to this system, and that hops are less than the max
|
# local to this system, and that hops are less than the max
|
||||||
if (not any(packet.destination_hash == d.hash for d in Transport.destinations) and packet.hops < Transport.PATHFINDER_M+1):
|
if (not any(packet.destination_hash == d.hash for d in Transport.destinations) and packet.hops < Transport.PATHFINDER_M+1):
|
||||||
random_blob = packet.data[RNS.Identity.DERKEYSIZE//8+10:RNS.Identity.DERKEYSIZE//8+20]
|
random_blob = packet.data[RNS.Identity.KEYSIZE//8+10:RNS.Identity.KEYSIZE//8+20]
|
||||||
random_blobs = []
|
random_blobs = []
|
||||||
if packet.destination_hash in Transport.destination_table:
|
if packet.destination_hash in Transport.destination_table:
|
||||||
random_blobs = Transport.destination_table[packet.destination_hash][4]
|
random_blobs = Transport.destination_table[packet.destination_hash][4]
|
||||||
|
|||||||
Binary file not shown.
@@ -1,4 +1,4 @@
|
|||||||
# Sphinx build info version 1
|
# Sphinx build info version 1
|
||||||
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
|
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
|
||||||
config: 010a10c5bc670583cef4151858e38839
|
config: 205a0b937612ce08d1a58b1cbb471256
|
||||||
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 108 KiB |
@@ -1,7 +1,6 @@
|
|||||||
********************
|
********************
|
||||||
Getting Started Fast
|
Getting Started Fast
|
||||||
********************
|
********************
|
||||||
What do we want to do? Something! When do we want to do it? Right now! Let's go.
|
|
||||||
|
|
||||||
The best way to get started with the Reticulum Network Stack depends on what
|
The best way to get started with the Reticulum Network Stack depends on what
|
||||||
you want to do. This guide will outline sensible starting paths for different
|
you want to do. This guide will outline sensible starting paths for different
|
||||||
@@ -23,7 +22,7 @@ in the development for the messaging and information-sharing protocol
|
|||||||
Develop a Program with Reticulum
|
Develop a Program with Reticulum
|
||||||
===========================================
|
===========================================
|
||||||
If you want to develop programs that use Reticulum, the easiest way to get
|
If you want to develop programs that use Reticulum, the easiest way to get
|
||||||
started is to install Reticulum via pip:
|
started is to install the latest release of Reticulum via pip:
|
||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ the development of Reticulum itself.
|
|||||||
|
|
||||||
whatis
|
whatis
|
||||||
gettingstartedfast
|
gettingstartedfast
|
||||||
examples
|
|
||||||
reference
|
|
||||||
understanding
|
understanding
|
||||||
|
reference
|
||||||
|
examples
|
||||||
|
|
||||||
|
|
||||||
Indices and Tables
|
Indices and Tables
|
||||||
|
|||||||
@@ -160,9 +160,13 @@ Destination Naming
|
|||||||
Destinations are created and named in an easy to understand dotted notation of *aspects*, and
|
Destinations are created and named in an easy to understand dotted notation of *aspects*, and
|
||||||
represented on the network as a hash of this value. The hash is a SHA-256 truncated to 80 bits. The
|
represented on the network as a hash of this value. The hash is a SHA-256 truncated to 80 bits. The
|
||||||
top level aspect should always be a unique identifier for the application using the destination.
|
top level aspect should always be a unique identifier for the application using the destination.
|
||||||
The next levels of aspects can be defined in any way by the creator of the application. For example,
|
The next levels of aspects can be defined in any way by the creator of the application.
|
||||||
a destination for a environmental monitoring application could be made up of the application name, a
|
|
||||||
device type and measurement type, like this:
|
Aspects can be as long and as plentiful as required, and a resulting long destination name will not
|
||||||
|
impact efficiency, as names are always represented as truncated SHA-256 hashes on the network.
|
||||||
|
|
||||||
|
As an example, a destination for a environmental monitoring application could be made up of the
|
||||||
|
application name, a device type and measurement type, like this:
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
@@ -201,9 +205,8 @@ To recap, the different destination types should be used in the following situat
|
|||||||
* **Single**
|
* **Single**
|
||||||
When private communication between two endpoints is needed. Supports multiple hops.
|
When private communication between two endpoints is needed. Supports multiple hops.
|
||||||
* **Group**
|
* **Group**
|
||||||
When private communication between two or more endpoints is needed. More efficient in
|
When private communication between two or more endpoints is needed. Supports multiple hops
|
||||||
data usage than *single* destinations. Supports multiple hops indirectly, but must first be
|
indirectly, but must first be established through a *single* destination.
|
||||||
established through a *single* destination.
|
|
||||||
* **Plain**
|
* **Plain**
|
||||||
When plain-text communication is desirable, for example when broadcasting information.
|
When plain-text communication is desirable, for example when broadcasting information.
|
||||||
|
|
||||||
@@ -214,9 +217,9 @@ an unknown public key from the network, as all participating nodes serve as a di
|
|||||||
of public keys.
|
of public keys.
|
||||||
|
|
||||||
Note that public key information can be shared and verified in many other ways than using the
|
Note that public key information can be shared and verified in many other ways than using the
|
||||||
built-in methodology, and that it is therefore not required to use the announce/request functionality.
|
built-in *announce* functionality, and that it is therefore not required to use the announce/request
|
||||||
It is by far the easiest though, and should definitely be used if there is not a good reason for
|
functionality to obtain public keys. It is by far the easiest though, and should definitely be used
|
||||||
doing it differently.
|
if there is not a good reason for doing it differently.
|
||||||
|
|
||||||
.. _understanding-keyannouncements:
|
.. _understanding-keyannouncements:
|
||||||
|
|
||||||
@@ -235,7 +238,7 @@ contain the following information:
|
|||||||
* The announcers public key
|
* The announcers public key
|
||||||
* Application specific data, in this case the users nickname and availability status
|
* Application specific data, in this case the users nickname and availability status
|
||||||
* A random blob, making each new announce unique
|
* A random blob, making each new announce unique
|
||||||
* A signature of the above information, verifying authenticity
|
* An Ed25519 signature of the above information, verifying authenticity
|
||||||
|
|
||||||
With this information, any Reticulum node that receives it will be able to reconstruct an outgoing
|
With this information, any Reticulum node that receives it will be able to reconstruct an outgoing
|
||||||
destination to securely communicate with that destination. You might have noticed that there is one
|
destination to securely communicate with that destination. You might have noticed that there is one
|
||||||
@@ -244,8 +247,9 @@ the aspect names of the destination. These are intentionally left out to save ba
|
|||||||
will be implicit in almost all cases. If a destination name is not entirely implicit, information can be
|
will be implicit in almost all cases. If a destination name is not entirely implicit, information can be
|
||||||
included in the application specific data part that will allow the receiver to infer the naming.
|
included in the application specific data part that will allow the receiver to infer the naming.
|
||||||
|
|
||||||
It is important to note that announcements will be forwarded throughout the network according to a
|
It is important to note that announces will be forwarded throughout the network according to a
|
||||||
certain pattern. This will be detailed later.
|
certain pattern. This will be detailed in the section
|
||||||
|
:ref:`The Announce Mechanism in Detail<understanding-announce>`.
|
||||||
|
|
||||||
Seeing how *single* destinations are always tied to a private/public key pair leads us to the next topic.
|
Seeing how *single* destinations are always tied to a private/public key pair leads us to the next topic.
|
||||||
|
|
||||||
@@ -268,8 +272,8 @@ the identity first, and then link it to created destinations.
|
|||||||
|
|
||||||
Building upon the simple messenger example, we could use an identity to represent the user of the
|
Building upon the simple messenger example, we could use an identity to represent the user of the
|
||||||
application. Destinations created will then be linked to this identity to allow communication to
|
application. Destinations created will then be linked to this identity to allow communication to
|
||||||
reach the user. In such a case it is of great importance to store the user’s identity securely and
|
reach the user. In all cases it is of great importance to store the private keys associated with any
|
||||||
privately.
|
Reticulum Identity securely and privately.
|
||||||
|
|
||||||
.. _understanding-gettingfurther:
|
.. _understanding-gettingfurther:
|
||||||
|
|
||||||
@@ -279,8 +283,9 @@ Getting Further
|
|||||||
The above functions and principles form the core of Reticulum, and would suffice to create
|
The above functions and principles form the core of Reticulum, and would suffice to create
|
||||||
functional networked applications in local clusters, for example over radio links where all interested
|
functional networked applications in local clusters, for example over radio links where all interested
|
||||||
nodes can directly hear each other. But to be truly useful, we need a way to direct traffic over multiple
|
nodes can directly hear each other. But to be truly useful, we need a way to direct traffic over multiple
|
||||||
hops in the network. In the next sections, two concepts that allow this will be introduced, *paths* and
|
hops in the network.
|
||||||
*links*.
|
|
||||||
|
In the following sections, two concepts that allow this will be introduced, *paths* and *links*.
|
||||||
|
|
||||||
.. _understanding-transport:
|
.. _understanding-transport:
|
||||||
|
|
||||||
@@ -298,70 +303,28 @@ useable over bandwidth-limited, high-latency links.
|
|||||||
|
|
||||||
To overcome such challenges, Reticulum’s *Transport* system uses public-key cryptography to
|
To overcome such challenges, Reticulum’s *Transport* system uses public-key cryptography to
|
||||||
implement the concept of *paths* that allow discovery of how to get information to a certain
|
implement the concept of *paths* that allow discovery of how to get information to a certain
|
||||||
destination, and *resources* that help make reliable data transfer more efficient.
|
destination. It is important to note that no single node in a Reticulum network knows the complete
|
||||||
|
path to a destination. Every Transport node participating in a Reticulum network will only
|
||||||
|
know what the most direct way to get a packet one hop closer to it's destination is.
|
||||||
|
|
||||||
.. _understanding-paths:
|
.. _understanding-announce:
|
||||||
|
|
||||||
Reaching the Destination
|
The Announce Mechanism in Detail
|
||||||
------------------------
|
--------------------------------
|
||||||
|
|
||||||
In networks with changing topology and trustless connectivity, nodes need a way to establish
|
When an *announce* is transmitted by a node, it will be forwarded by any node receiving it, but
|
||||||
*verified connectivity* with each other. Since the network is assumed to be trustless, Reticulum
|
according to some specific rules:
|
||||||
must provide a way to guarantee that the peer you are communicating with is actually who you
|
|
||||||
expect. To do this, the following process is employed:
|
|
||||||
|
|
||||||
|
|
||||||
* | First, the node that wishes to establish connectivity will send out a special packet, that
|
* | If this exact announce has already been received before, ignore it.
|
||||||
traverses the network and locates the desired destination. Along the way, the nodes that
|
|
||||||
forward the packet will take note of this *link request*.
|
|
||||||
|
|
||||||
* | Second, if the destination accepts the *link request* , it will send back a packet that proves the
|
* | If not, record into a table which node the announce was received from, and how many times in
|
||||||
authenticity of it’s identity (and the receipt of the link request) to the initiating node. All
|
|
||||||
nodes that initially forwarded the packet will also be able to verify this proof, and thus
|
|
||||||
accept the validity of the *link* throughout the network.
|
|
||||||
|
|
||||||
* | When the validity of the *link* has been accepted by forwarding nodes, these nodes will
|
|
||||||
remember the *link* , and it can subsequently be used by referring to a hash representing it.
|
|
||||||
|
|
||||||
* | As a part of the *link request* , a Diffie-Hellman key exchange takes place, that sets up an
|
|
||||||
efficient symmetrically encrypted tunnel between the two nodes, using elliptic curve
|
|
||||||
cryptography. As such, this mode of communication is preferred, even for situations when
|
|
||||||
nodes can directly communicate, when the amount of data to be exchanged numbers in the
|
|
||||||
tens of packets.
|
|
||||||
|
|
||||||
* | When a *link* has been set up, it automatically provides message receipt functionality, so the
|
|
||||||
sending node can obtain verified confirmation that the information reached the intended
|
|
||||||
recipient.
|
|
||||||
|
|
||||||
In a moment, we will discuss the specifics of how this methodology is implemented, but let’s first
|
|
||||||
recap what purposes this serves. We first ensure that the node answering our request is actually the
|
|
||||||
one we want to communicate with, and not a malicious actor pretending to be so. At the same time
|
|
||||||
we establish an efficient encrypted channel. The setup of this is relatively cheap in terms of
|
|
||||||
bandwidth, so it can be used just for a short exchange, and then recreated as needed, which will also
|
|
||||||
rotate encryption keys, but the link can also be kept alive for longer periods of time, if this is
|
|
||||||
more suitable to the application. The amount of bandwidth used on keeping a link open is practically
|
|
||||||
negligible. The procedure also inserts the *link id* , a hash calculated from the link request packet,
|
|
||||||
into the memory of forwarding nodes, which means that the communicating nodes can thereafter reach each
|
|
||||||
other simply by referring to this *link id*.
|
|
||||||
|
|
||||||
Step 1: Pathfinding
|
|
||||||
^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
The pathfinding method builds on the *announce* functionality discussed earlier. When an announce
|
|
||||||
is sent out by a node, it will be forwarded by any node receiving it, but according to some specific
|
|
||||||
rules:
|
|
||||||
|
|
||||||
|
|
||||||
* | If this announce has already been received before, ignore it.
|
|
||||||
|
|
||||||
* | Record into a table which node the announce was received from, and how many times in
|
|
||||||
total it has been retransmitted to get here.
|
total it has been retransmitted to get here.
|
||||||
|
|
||||||
* | If the announce has been retransmitted *m+1* times, it will not be forwarded. By default, *m* is
|
* | If the announce has been retransmitted *m+1* times, it will not be forwarded. By default, *m* is
|
||||||
set to 18.
|
set to 18.
|
||||||
|
|
||||||
* | The announce will be assigned a delay *d* = c\ :sup:`h` seconds, where *c* is a decay constant, by
|
* | The announce will be assigned a delay *d* = c\ :sup:`h` seconds, where *c* is a decay constant, and *h* is the amount of times this packet has already been forwarded.
|
||||||
default 2, and *h* is the amount of times this packet has already been forwarded.
|
|
||||||
|
|
||||||
* | The packet will be given a priority *p = 1/d*.
|
* | The packet will be given a priority *p = 1/d*.
|
||||||
|
|
||||||
@@ -370,10 +333,11 @@ rules:
|
|||||||
not utilized by other traffic, the announce will be forwarded.
|
not utilized by other traffic, the announce will be forwarded.
|
||||||
|
|
||||||
* | If no other nodes are heard retransmitting the announce with a greater hop count than when
|
* | If no other nodes are heard retransmitting the announce with a greater hop count than when
|
||||||
it left this node, transmitting it will be retried *r* times. By default, *r* is set to 2. Retries follow
|
it left this node, transmitting it will be retried *r* times. By default, *r* is set to 1. Retries
|
||||||
same rules as above, with the exception that it must wait for at least *d* = c\ :sup:`h+1` + t seconds, ie.,
|
follow same rules as above, with the exception that it must wait for at least *d* = c\ :sup:`h+1` +
|
||||||
the amount of time it would take the next node to retransmit the packet. By default, *t* is set to
|
t + rand(0, rw) seconds. This amount of time is equal to the amount of time it would take the next
|
||||||
10.
|
node to retransmit the packet, plus a random window. By default, *t* is set to 10 seconds, and the
|
||||||
|
random window *rw* is set to 10 seconds.
|
||||||
|
|
||||||
* | If a newer announce from the same destination arrives, while an identical one is already in
|
* | If a newer announce from the same destination arrives, while an identical one is already in
|
||||||
the queue, the newest announce is discarded. If the newest announce contains different
|
the queue, the newest announce is discarded. If the newest announce contains different
|
||||||
@@ -392,14 +356,95 @@ distance of *Lavg =* 15 kilometers, an announce will be able to propagate outwar
|
|||||||
kilometers in 34 minutes, and a *maximum announce radius* of 270 kilometers in approximately 3
|
kilometers in 34 minutes, and a *maximum announce radius* of 270 kilometers in approximately 3
|
||||||
days.
|
days.
|
||||||
|
|
||||||
Step 2: Link Establishment
|
.. _understanding-paths:
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
After seeing how the conditions for finding a path through the network are created, we will now
|
Reaching the Destination
|
||||||
explore how two nodes can establish reliable communications over multiple hops. The *link* in
|
------------------------
|
||||||
Reticulum terminology should not be viewed as a direct node-to-node link on the physical layer, but
|
|
||||||
as an abstract channel, that can be open for any amount of time, and can span an arbitrary number
|
In networks with changing topology and trustless connectivity, nodes need a way to establish
|
||||||
of hops, where information will be exchanged between two nodes.
|
*verified connectivity* with each other. Since the network is assumed to be trustless, Reticulum
|
||||||
|
must provide a way to guarantee that the peer you are communicating with is actually who you
|
||||||
|
expect. Reticulum offers two ways to do this.
|
||||||
|
|
||||||
|
For exchanges of small amounts of information, Reticulum offers the *Packet* API, which works exactly like you would expect - on a per packet level. The following process is employed when sending a packet:
|
||||||
|
|
||||||
|
* | A packet is always created with an associated destination and some payload data. When the packet is sent
|
||||||
|
to a *single* destination type, Reticulum will automatically create an ephemeral encryption key, perform
|
||||||
|
an ECDH key exchange with the destinations public key, and encrypt the information.
|
||||||
|
|
||||||
|
* | It is important to note that this key exchange does not require any network traffic. The sender already
|
||||||
|
knows the public key of the destination from an earlier received *announce*, and can thus perform the ECDH
|
||||||
|
key exchange locally, before sending the packet.
|
||||||
|
|
||||||
|
* | The public part of the newly generated ephemeral key-pair is included with the encrypted token, and sent
|
||||||
|
along with the encrypted payload data in the packet.
|
||||||
|
|
||||||
|
* | When the destination receives the packet, it can itself perform an ECDH key exchange and decrypt the
|
||||||
|
packet.
|
||||||
|
|
||||||
|
* | A new ephemeral key is used for every packet sent in this way, and forward secrecy is guaranteed on a
|
||||||
|
per packet level.
|
||||||
|
|
||||||
|
* | Once the packet has been received and decrypted by the addressed destination, that destination can opt
|
||||||
|
to *prove* its receipt of the packet. It does this by calculating the SHA-256 hash of the received packet,
|
||||||
|
and signing this hash with it's Ed25519 signing key. Transport nodes in the network can then direct this
|
||||||
|
*proof* back to the packets origin, where the signature can be verified against the destinations known
|
||||||
|
public signing key.
|
||||||
|
|
||||||
|
* | In case the packet is addressed to a *group* destination type, the packet will be encrypted with the
|
||||||
|
pre-shared AES-128 key associated with the destination. In case the packet is addressed to a *plain*
|
||||||
|
destination type, the payload data will not be encrypted. Neither of these two destination types offer
|
||||||
|
forward secrecy. In general, it is recommended to always use the *single* destination type, unless it is
|
||||||
|
strictly necessary to use one of the others.
|
||||||
|
|
||||||
|
|
||||||
|
For exchanges of larger amounts of data, or when longer sessions of bidirectional communication is desired, Reticulum offers the *Link* API. To establish a *link*, the following process is employed:
|
||||||
|
|
||||||
|
* | First, the node that wishes to establish a link will send out a special packet, that
|
||||||
|
traverses the network and locates the desired destination. Along the way, the nodes that
|
||||||
|
forward the packet will take note of this *link request*.
|
||||||
|
|
||||||
|
* | Second, if the destination accepts the *link request* , it will send back a packet that proves the
|
||||||
|
authenticity of it’s identity (and the receipt of the link request) to the initiating node. All
|
||||||
|
nodes that initially forwarded the packet will also be able to verify this proof, and thus
|
||||||
|
accept the validity of the *link* throughout the network.
|
||||||
|
|
||||||
|
* | When the validity of the *link* has been accepted by forwarding nodes, these nodes will
|
||||||
|
remember the *link* , and it can subsequently be used by referring to a hash representing it.
|
||||||
|
|
||||||
|
* | As a part of the *link request* , a Diffie-Hellman key exchange takes place, that sets up an
|
||||||
|
efficiently encrypted tunnel between the two nodes, using elliptic curve cryptography. As such,
|
||||||
|
this mode of communication is preferred, even for situations when nodes can directly communicate,
|
||||||
|
when the amount of data to be exchanged numbers in the tens of packets.
|
||||||
|
|
||||||
|
* | When a *link* has been set up, it automatically provides message receipt functionality, through
|
||||||
|
the same *proof* mechanism discussed before, so the sending node can obtain verified confirmation
|
||||||
|
that the information reached the intended recipient.
|
||||||
|
|
||||||
|
In a moment, we will discuss the details of how this methodology is implemented, but let’s first
|
||||||
|
recap what purposes this methodology serves. We first ensure that the node answering our request
|
||||||
|
is actually the one we want to communicate with, and not a malicious actor pretending to be so.
|
||||||
|
At the same time we establish an efficient encrypted channel. The setup of this is relatively cheap in
|
||||||
|
terms of bandwidth, so it can be used just for a short exchange, and then recreated as needed, which will
|
||||||
|
also rotate encryption keys. The link can also be kept alive for longer periods of time, if this is
|
||||||
|
more suitable to the application. The procedure also inserts the *link id* , a hash calculated from the link request packet, into the memory of forwarding nodes, which means that the communicating nodes can thereafter reach each other simply by referring to this *link id*.
|
||||||
|
|
||||||
|
The combined bandwidth cost of setting up a link is 3 packets totalling 240 bytes (more info in the
|
||||||
|
:ref:`Binary Packet Format<understanding-packetformat>` section). The amount of bandwidth used on keeping
|
||||||
|
a link open is practically negligible, at 0.62 bits per second. Even on a slow 1200 bits per second packet
|
||||||
|
radio channel, 100 concurrent links will still leave 95% channel capacity for actual data.
|
||||||
|
|
||||||
|
|
||||||
|
Link Establishment in Detail
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
After exploring the basics of the announce mechanism, finding a path through the network, and an overview
|
||||||
|
of the link establishment procedure, this section will go into greater detail about the Reticulum link
|
||||||
|
establishment process.
|
||||||
|
|
||||||
|
The *link* in Reticulum terminology should not be viewed as a direct node-to-node link on the
|
||||||
|
physical layer, but as an abstract channel, that can be open for any amount of time, and can span
|
||||||
|
an arbitrary number of hops, where information will be exchanged between two nodes.
|
||||||
|
|
||||||
|
|
||||||
* | When a node in the network wants to establish verified connectivity with another node, it
|
* | When a node in the network wants to establish verified connectivity with another node, it
|
||||||
@@ -412,25 +457,25 @@ of hops, where information will be exchanged between two nodes.
|
|||||||
considered as single public key for simplicity in this explanation.*
|
considered as single public key for simplicity in this explanation.*
|
||||||
|
|
||||||
* | The *link request* is addressed to the destination hash of the desired destination, and
|
* | The *link request* is addressed to the destination hash of the desired destination, and
|
||||||
contains the following data: The newly generated X25519 public key *LKi*. The contents
|
contains the following data: The newly generated X25519 public key *LKi*.
|
||||||
are encrypted with the RSA public key of the destination and tramsitted over the network.
|
|
||||||
|
|
||||||
* | The broadcasted packet will be directed through the network according to the rules laid out
|
* | The broadcasted packet will be directed through the network according to the rules laid out
|
||||||
previously.
|
previously.
|
||||||
|
|
||||||
* | Any node that forwards the link request will store a *link id* in it’s *link table* , along with the
|
* | Any node that forwards the link request will store a *link id* in it’s *link table* , along with the
|
||||||
amount of hops the packet had taken when received. The link id is a hash of the entire link
|
amount of hops the packet had taken when received. The link id is a hash of the entire link
|
||||||
request packet. If the path is not *proven* within some set amount of time, the entry will be
|
request packet. If the link request packet is not *proven* by the addressed destination within some
|
||||||
dropped from the *link table* again.
|
set amount of time, the entry will be dropped from the *link table* again.
|
||||||
|
|
||||||
* | When the destination receives the link request packet, it will decrypt it and decide whether to
|
* | When the destination receives the link request packet, it will decide whether to accept the request.
|
||||||
accept the request. If it is accepted, the destination will also generate a new X25519 private/public
|
If it is accepted, the destination will also generate a new X25519 private/public key pair, and
|
||||||
key pair, and perform a Diffie Hellman Key Exchange, deriving a new symmetric key that will be used
|
perform a Diffie Hellman Key Exchange, deriving a new symmetric key that will be used to encrypt the
|
||||||
to encrypt the channel, once it has been established.
|
channel, once it has been established.
|
||||||
|
|
||||||
* | A *link proof* packet is now constructed and transmitted over the network. This packet is
|
* | A *link proof* packet is now constructed and transmitted over the network. This packet is
|
||||||
addressed to the *link id* of the *link*. It contains the following data: The newly generated X25519
|
addressed to the *link id* of the *link*. It contains the following data: The newly generated X25519
|
||||||
public key *LKr* and an RSA-1024 signature of the *link id* and *LKr*.
|
public key *LKr* and an Ed25519 signature of the *link id* and *LKr* made by the signing key of
|
||||||
|
the addressed destination.
|
||||||
|
|
||||||
* | By verifying this *link proof* packet, all nodes that originally transported the *link request*
|
* | By verifying this *link proof* packet, all nodes that originally transported the *link request*
|
||||||
packet to the destination from the originator can now verify that the intended destination received
|
packet to the destination from the originator can now verify that the intended destination received
|
||||||
@@ -556,6 +601,8 @@ the light of Reticulums goal of equal access, doing so would need to be the subj
|
|||||||
investigation of the consequences first.
|
investigation of the consequences first.
|
||||||
|
|
||||||
|
|
||||||
|
.. _understanding-packetformat:
|
||||||
|
|
||||||
Binary Packet Format
|
Binary Packet Format
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
@@ -651,8 +698,8 @@ Binary Packet Format
|
|||||||
wire size including all fields.
|
wire size including all fields.
|
||||||
|
|
||||||
- Path Request : 33 bytes
|
- Path Request : 33 bytes
|
||||||
- Announce : 323 bytes
|
- Announce : 151 bytes
|
||||||
- Link Request : 141 bytes
|
- Link Request : 77 bytes
|
||||||
- Link Proof : 205 bytes
|
- Link Proof : 77 bytes
|
||||||
- Link RTT packet : 86 bytes
|
- Link RTT packet : 86 bytes
|
||||||
- Link keepalive : 14 bytes
|
- Link keepalive : 14 bytes
|
||||||
@@ -25,11 +25,11 @@ What does Reticulum Offer?
|
|||||||
|
|
||||||
* Fully self-configuring multi-hop routing
|
* Fully self-configuring multi-hop routing
|
||||||
|
|
||||||
* Asymmetric RSA encryption and signatures as basis for all communication
|
* Asymmetric X25519 encryption and Ed25519 signatures as a basis for all communication
|
||||||
|
|
||||||
* Perfect Forward Secrecy on links with ephemereal Elliptic Curve Diffie-Hellman keys (on Curve25519)
|
* Forward Secrecy with ephemereal Elliptic Curve Diffie-Hellman keys on Curve25519
|
||||||
|
|
||||||
* Reticulum uses the Fernet specification for encryption on links and to group destinations
|
* Reticulum uses the `Fernet <https://github.com/fernet/spec/blob/master/Spec.md>`_ specification for encryption
|
||||||
|
|
||||||
* AES-128 in CBC mode with PKCS7 padding
|
* AES-128 in CBC mode with PKCS7 padding
|
||||||
|
|
||||||
@@ -37,6 +37,8 @@ What does Reticulum Offer?
|
|||||||
|
|
||||||
* IVs are generated through os.urandom()
|
* IVs are generated through os.urandom()
|
||||||
|
|
||||||
|
* Keys are ephemeral and derived from an ECDH key exchange on Curve25519
|
||||||
|
|
||||||
* Unforgeable packet delivery confirmations
|
* Unforgeable packet delivery confirmations
|
||||||
|
|
||||||
* A variety of supported interface types
|
* A variety of supported interface types
|
||||||
@@ -51,10 +53,16 @@ What does Reticulum Offer?
|
|||||||
|
|
||||||
* The API is very easy to use, and provides transfer progress
|
* The API is very easy to use, and provides transfer progress
|
||||||
|
|
||||||
|
* Efficient link establishment
|
||||||
|
|
||||||
|
* Total bandwidth cost of setting up a link is only 3 packets, totalling 240 bytes
|
||||||
|
|
||||||
|
* Low cost of keeping links open at only 0.62 bits per second
|
||||||
|
|
||||||
|
|
||||||
Where can Reticulum be Used?
|
Where can Reticulum be Used?
|
||||||
============================
|
============================
|
||||||
On practically any hardware that can support at least a half-duplex channel
|
Over practically any medium that can support at least a half-duplex channel
|
||||||
with 1.000 bits per second throughput, and an MTU of 500 bytes. Data radios,
|
with 1.000 bits per second throughput, and an MTU of 500 bytes. Data radios,
|
||||||
modems, LoRa radios, serial lines, AX.25 TNCs, amateur radio digital modes,
|
modems, LoRa radios, serial lines, AX.25 TNCs, amateur radio digital modes,
|
||||||
ad-hoc WiFi, free-space optical links and similar systems are all examples
|
ad-hoc WiFi, free-space optical links and similar systems are all examples
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
var DOCUMENTATION_OPTIONS = {
|
var DOCUMENTATION_OPTIONS = {
|
||||||
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
|
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
|
||||||
VERSION: '0.2.0 beta',
|
VERSION: '0.2.1 beta',
|
||||||
LANGUAGE: 'None',
|
LANGUAGE: 'None',
|
||||||
COLLAPSE_INDEX: false,
|
COLLAPSE_INDEX: false,
|
||||||
BUILDER: 'html',
|
BUILDER: 'html',
|
||||||
|
|||||||
+36
-36
@@ -5,7 +5,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Examples — Reticulum Network Stack 0.2.0 beta documentation</title>
|
<title>Examples — Reticulum Network Stack 0.2.1 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/classic.css" />
|
<link rel="stylesheet" type="text/css" href="_static/classic.css" />
|
||||||
|
|
||||||
@@ -16,8 +16,7 @@
|
|||||||
|
|
||||||
<link rel="index" title="Index" href="genindex.html" />
|
<link rel="index" title="Index" href="genindex.html" />
|
||||||
<link rel="search" title="Search" href="search.html" />
|
<link rel="search" title="Search" href="search.html" />
|
||||||
<link rel="next" title="API Reference" href="reference.html" />
|
<link rel="prev" title="API Reference" href="reference.html" />
|
||||||
<link rel="prev" title="Getting Started Fast" href="gettingstartedfast.html" />
|
|
||||||
</head><body>
|
</head><body>
|
||||||
<div class="related" role="navigation" aria-label="related navigation">
|
<div class="related" role="navigation" aria-label="related navigation">
|
||||||
<h3>Navigation</h3>
|
<h3>Navigation</h3>
|
||||||
@@ -27,11 +26,8 @@
|
|||||||
accesskey="I">index</a></li>
|
accesskey="I">index</a></li>
|
||||||
<li class="right" >
|
<li class="right" >
|
||||||
<a href="reference.html" title="API Reference"
|
<a href="reference.html" title="API Reference"
|
||||||
accesskey="N">next</a> |</li>
|
|
||||||
<li class="right" >
|
|
||||||
<a href="gettingstartedfast.html" title="Getting Started Fast"
|
|
||||||
accesskey="P">previous</a> |</li>
|
accesskey="P">previous</a> |</li>
|
||||||
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li>
|
||||||
<li class="nav-item nav-item-this"><a href="">Examples</a></li>
|
<li class="nav-item nav-item-this"><a href="">Examples</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -380,7 +376,7 @@ over the network.</p>
|
|||||||
|
|
||||||
<span class="c1"># We specify a callback that will get called every time</span>
|
<span class="c1"># We specify a callback that will get called every time</span>
|
||||||
<span class="c1"># the destination receives data.</span>
|
<span class="c1"># the destination receives data.</span>
|
||||||
<span class="n">broadcast_destination</span><span class="o">.</span><span class="n">packet_callback</span><span class="p">(</span><span class="n">packet_callback</span><span class="p">)</span>
|
<span class="n">broadcast_destination</span><span class="o">.</span><span class="n">set_packet_callback</span><span class="p">(</span><span class="n">packet_callback</span><span class="p">)</span>
|
||||||
|
|
||||||
<span class="c1"># Everything's ready!</span>
|
<span class="c1"># Everything's ready!</span>
|
||||||
<span class="c1"># Let's hand over control to the main loop</span>
|
<span class="c1"># Let's hand over control to the main loop</span>
|
||||||
@@ -522,7 +518,7 @@ the Packet interface.</p>
|
|||||||
<span class="c1"># Tell the destination which function in our program to</span>
|
<span class="c1"># Tell the destination which function in our program to</span>
|
||||||
<span class="c1"># run when a packet is received. We do this so we can</span>
|
<span class="c1"># run when a packet is received. We do this so we can</span>
|
||||||
<span class="c1"># print a log message when the server receives a request</span>
|
<span class="c1"># print a log message when the server receives a request</span>
|
||||||
<span class="n">echo_destination</span><span class="o">.</span><span class="n">packet_callback</span><span class="p">(</span><span class="n">server_callback</span><span class="p">)</span>
|
<span class="n">echo_destination</span><span class="o">.</span><span class="n">set_packet_callback</span><span class="p">(</span><span class="n">server_callback</span><span class="p">)</span>
|
||||||
|
|
||||||
<span class="c1"># Everything's ready!</span>
|
<span class="c1"># Everything's ready!</span>
|
||||||
<span class="c1"># Let's Wait for client requests or user input</span>
|
<span class="c1"># Let's Wait for client requests or user input</span>
|
||||||
@@ -640,12 +636,12 @@ the Packet interface.</p>
|
|||||||
<span class="c1"># the packet times out.</span>
|
<span class="c1"># the packet times out.</span>
|
||||||
<span class="k">if</span> <span class="n">timeout</span> <span class="o">!=</span> <span class="kc">None</span><span class="p">:</span>
|
<span class="k">if</span> <span class="n">timeout</span> <span class="o">!=</span> <span class="kc">None</span><span class="p">:</span>
|
||||||
<span class="n">packet_receipt</span><span class="o">.</span><span class="n">set_timeout</span><span class="p">(</span><span class="n">timeout</span><span class="p">)</span>
|
<span class="n">packet_receipt</span><span class="o">.</span><span class="n">set_timeout</span><span class="p">(</span><span class="n">timeout</span><span class="p">)</span>
|
||||||
<span class="n">packet_receipt</span><span class="o">.</span><span class="n">timeout_callback</span><span class="p">(</span><span class="n">packet_timed_out</span><span class="p">)</span>
|
<span class="n">packet_receipt</span><span class="o">.</span><span class="n">set_timeout_callback</span><span class="p">(</span><span class="n">packet_timed_out</span><span class="p">)</span>
|
||||||
|
|
||||||
<span class="c1"># We can then set a delivery callback on the receipt.</span>
|
<span class="c1"># We can then set a delivery callback on the receipt.</span>
|
||||||
<span class="c1"># This will get automatically called when a proof for</span>
|
<span class="c1"># This will get automatically called when a proof for</span>
|
||||||
<span class="c1"># this specific packet is received from the destination.</span>
|
<span class="c1"># this specific packet is received from the destination.</span>
|
||||||
<span class="n">packet_receipt</span><span class="o">.</span><span class="n">delivery_callback</span><span class="p">(</span><span class="n">packet_delivered</span><span class="p">)</span>
|
<span class="n">packet_receipt</span><span class="o">.</span><span class="n">set_delivery_callback</span><span class="p">(</span><span class="n">packet_delivered</span><span class="p">)</span>
|
||||||
|
|
||||||
<span class="c1"># Tell the user that the echo request was sent</span>
|
<span class="c1"># Tell the user that the echo request was sent</span>
|
||||||
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"Sent echo request to "</span><span class="o">+</span><span class="n">RNS</span><span class="o">.</span><span class="n">prettyhexrep</span><span class="p">(</span><span class="n">request_destination</span><span class="o">.</span><span class="n">hash</span><span class="p">))</span>
|
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"Sent echo request to "</span><span class="o">+</span><span class="n">RNS</span><span class="o">.</span><span class="n">prettyhexrep</span><span class="p">(</span><span class="n">request_destination</span><span class="o">.</span><span class="n">hash</span><span class="p">))</span>
|
||||||
@@ -659,7 +655,7 @@ the Packet interface.</p>
|
|||||||
<span class="c1"># receives a proof packet.</span>
|
<span class="c1"># receives a proof packet.</span>
|
||||||
<span class="k">def</span> <span class="nf">packet_delivered</span><span class="p">(</span><span class="n">receipt</span><span class="p">):</span>
|
<span class="k">def</span> <span class="nf">packet_delivered</span><span class="p">(</span><span class="n">receipt</span><span class="p">):</span>
|
||||||
<span class="k">if</span> <span class="n">receipt</span><span class="o">.</span><span class="n">status</span> <span class="o">==</span> <span class="n">RNS</span><span class="o">.</span><span class="n">PacketReceipt</span><span class="o">.</span><span class="n">DELIVERED</span><span class="p">:</span>
|
<span class="k">if</span> <span class="n">receipt</span><span class="o">.</span><span class="n">status</span> <span class="o">==</span> <span class="n">RNS</span><span class="o">.</span><span class="n">PacketReceipt</span><span class="o">.</span><span class="n">DELIVERED</span><span class="p">:</span>
|
||||||
<span class="n">rtt</span> <span class="o">=</span> <span class="n">receipt</span><span class="o">.</span><span class="n">rtt</span><span class="p">()</span>
|
<span class="n">rtt</span> <span class="o">=</span> <span class="n">receipt</span><span class="o">.</span><span class="n">get_rtt</span><span class="p">()</span>
|
||||||
<span class="k">if</span> <span class="p">(</span><span class="n">rtt</span> <span class="o">>=</span> <span class="mi">1</span><span class="p">):</span>
|
<span class="k">if</span> <span class="p">(</span><span class="n">rtt</span> <span class="o">>=</span> <span class="mi">1</span><span class="p">):</span>
|
||||||
<span class="n">rtt</span> <span class="o">=</span> <span class="nb">round</span><span class="p">(</span><span class="n">rtt</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
|
<span class="n">rtt</span> <span class="o">=</span> <span class="nb">round</span><span class="p">(</span><span class="n">rtt</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
|
||||||
<span class="n">rttstring</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">rtt</span><span class="p">)</span><span class="o">+</span><span class="s2">" seconds"</span>
|
<span class="n">rttstring</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">rtt</span><span class="p">)</span><span class="o">+</span><span class="s2">" seconds"</span>
|
||||||
@@ -803,7 +799,7 @@ destination, and passing traffic back and forth over the link.</p>
|
|||||||
|
|
||||||
<span class="c1"># We configure a function that will get called every time</span>
|
<span class="c1"># We configure a function that will get called every time</span>
|
||||||
<span class="c1"># a new client creates a link to this destination.</span>
|
<span class="c1"># a new client creates a link to this destination.</span>
|
||||||
<span class="n">server_destination</span><span class="o">.</span><span class="n">link_established_callback</span><span class="p">(</span><span class="n">client_connected</span><span class="p">)</span>
|
<span class="n">server_destination</span><span class="o">.</span><span class="n">set_link_established_callback</span><span class="p">(</span><span class="n">client_connected</span><span class="p">)</span>
|
||||||
|
|
||||||
<span class="c1"># Everything's ready!</span>
|
<span class="c1"># Everything's ready!</span>
|
||||||
<span class="c1"># Let's Wait for client requests or user input</span>
|
<span class="c1"># Let's Wait for client requests or user input</span>
|
||||||
@@ -835,8 +831,8 @@ destination, and passing traffic back and forth over the link.</p>
|
|||||||
<span class="k">global</span> <span class="n">latest_client_link</span>
|
<span class="k">global</span> <span class="n">latest_client_link</span>
|
||||||
|
|
||||||
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"Client connected"</span><span class="p">)</span>
|
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"Client connected"</span><span class="p">)</span>
|
||||||
<span class="n">link</span><span class="o">.</span><span class="n">link_closed_callback</span><span class="p">(</span><span class="n">client_disconnected</span><span class="p">)</span>
|
<span class="n">link</span><span class="o">.</span><span class="n">set_link_closed_callback</span><span class="p">(</span><span class="n">client_disconnected</span><span class="p">)</span>
|
||||||
<span class="n">link</span><span class="o">.</span><span class="n">packet_callback</span><span class="p">(</span><span class="n">server_packet_received</span><span class="p">)</span>
|
<span class="n">link</span><span class="o">.</span><span class="n">set_packet_callback</span><span class="p">(</span><span class="n">server_packet_received</span><span class="p">)</span>
|
||||||
<span class="n">latest_client_link</span> <span class="o">=</span> <span class="n">link</span>
|
<span class="n">latest_client_link</span> <span class="o">=</span> <span class="n">link</span>
|
||||||
|
|
||||||
<span class="k">def</span> <span class="nf">client_disconnected</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
|
<span class="k">def</span> <span class="nf">client_disconnected</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
|
||||||
@@ -908,12 +904,12 @@ destination, and passing traffic back and forth over the link.</p>
|
|||||||
<span class="c1"># We set a callback that will get executed</span>
|
<span class="c1"># We set a callback that will get executed</span>
|
||||||
<span class="c1"># every time a packet is received over the</span>
|
<span class="c1"># every time a packet is received over the</span>
|
||||||
<span class="c1"># link</span>
|
<span class="c1"># link</span>
|
||||||
<span class="n">link</span><span class="o">.</span><span class="n">packet_callback</span><span class="p">(</span><span class="n">client_packet_received</span><span class="p">)</span>
|
<span class="n">link</span><span class="o">.</span><span class="n">set_packet_callback</span><span class="p">(</span><span class="n">client_packet_received</span><span class="p">)</span>
|
||||||
|
|
||||||
<span class="c1"># We'll also set up functions to inform the</span>
|
<span class="c1"># We'll also set up functions to inform the</span>
|
||||||
<span class="c1"># user when the link is established or closed</span>
|
<span class="c1"># user when the link is established or closed</span>
|
||||||
<span class="n">link</span><span class="o">.</span><span class="n">link_established_callback</span><span class="p">(</span><span class="n">link_established</span><span class="p">)</span>
|
<span class="n">link</span><span class="o">.</span><span class="n">set_link_established_callback</span><span class="p">(</span><span class="n">link_established</span><span class="p">)</span>
|
||||||
<span class="n">link</span><span class="o">.</span><span class="n">link_closed_callback</span><span class="p">(</span><span class="n">link_closed</span><span class="p">)</span>
|
<span class="n">link</span><span class="o">.</span><span class="n">set_link_closed_callback</span><span class="p">(</span><span class="n">link_closed</span><span class="p">)</span>
|
||||||
|
|
||||||
<span class="c1"># Everything is set up, so let's enter a loop</span>
|
<span class="c1"># Everything is set up, so let's enter a loop</span>
|
||||||
<span class="c1"># for the user to interact with the example</span>
|
<span class="c1"># for the user to interact with the example</span>
|
||||||
@@ -940,8 +936,18 @@ destination, and passing traffic back and forth over the link.</p>
|
|||||||
<span class="c1"># If not, send the entered text over the link</span>
|
<span class="c1"># If not, send the entered text over the link</span>
|
||||||
<span class="k">if</span> <span class="n">text</span> <span class="o">!=</span> <span class="s2">""</span><span class="p">:</span>
|
<span class="k">if</span> <span class="n">text</span> <span class="o">!=</span> <span class="s2">""</span><span class="p">:</span>
|
||||||
<span class="n">data</span> <span class="o">=</span> <span class="n">text</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"utf-8"</span><span class="p">)</span>
|
<span class="n">data</span> <span class="o">=</span> <span class="n">text</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"utf-8"</span><span class="p">)</span>
|
||||||
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> <span class="o"><=</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Link</span><span class="o">.</span><span class="n">MDU</span><span class="p">:</span>
|
||||||
<span class="n">RNS</span><span class="o">.</span><span class="n">Packet</span><span class="p">(</span><span class="n">server_link</span><span class="p">,</span> <span class="n">data</span><span class="p">)</span><span class="o">.</span><span class="n">send</span><span class="p">()</span>
|
<span class="n">RNS</span><span class="o">.</span><span class="n">Packet</span><span class="p">(</span><span class="n">server_link</span><span class="p">,</span> <span class="n">data</span><span class="p">)</span><span class="o">.</span><span class="n">send</span><span class="p">()</span>
|
||||||
|
<span class="k">else</span><span class="p">:</span>
|
||||||
|
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span>
|
||||||
|
<span class="s2">"Cannot send this packet, the data size of "</span><span class="o">+</span>
|
||||||
|
<span class="nb">str</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">))</span><span class="o">+</span><span class="s2">" bytes exceeds the link packet MDU of "</span><span class="o">+</span>
|
||||||
|
<span class="nb">str</span><span class="p">(</span><span class="n">RNS</span><span class="o">.</span><span class="n">Link</span><span class="o">.</span><span class="n">MDU</span><span class="p">)</span><span class="o">+</span><span class="s2">" bytes"</span><span class="p">,</span>
|
||||||
|
<span class="n">RNS</span><span class="o">.</span><span class="n">LOG_ERROR</span>
|
||||||
|
<span class="p">)</span>
|
||||||
|
|
||||||
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
||||||
|
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"Error while sending data over the link: "</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">))</span>
|
||||||
<span class="n">should_quit</span> <span class="o">=</span> <span class="kc">True</span>
|
<span class="n">should_quit</span> <span class="o">=</span> <span class="kc">True</span>
|
||||||
<span class="n">server_link</span><span class="o">.</span><span class="n">teardown</span><span class="p">()</span>
|
<span class="n">server_link</span><span class="o">.</span><span class="n">teardown</span><span class="p">()</span>
|
||||||
|
|
||||||
@@ -1110,7 +1116,7 @@ interface to efficiently pass files of any size over a Reticulum <a class="refer
|
|||||||
|
|
||||||
<span class="c1"># We configure a function that will get called every time</span>
|
<span class="c1"># We configure a function that will get called every time</span>
|
||||||
<span class="c1"># a new client creates a link to this destination.</span>
|
<span class="c1"># a new client creates a link to this destination.</span>
|
||||||
<span class="n">server_destination</span><span class="o">.</span><span class="n">link_established_callback</span><span class="p">(</span><span class="n">client_connected</span><span class="p">)</span>
|
<span class="n">server_destination</span><span class="o">.</span><span class="n">set_link_established_callback</span><span class="p">(</span><span class="n">client_connected</span><span class="p">)</span>
|
||||||
|
|
||||||
<span class="c1"># Everything's ready!</span>
|
<span class="c1"># Everything's ready!</span>
|
||||||
<span class="c1"># Let's Wait for client requests or user input</span>
|
<span class="c1"># Let's Wait for client requests or user input</span>
|
||||||
@@ -1147,7 +1153,7 @@ interface to efficiently pass files of any size over a Reticulum <a class="refer
|
|||||||
<span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">serve_path</span><span class="p">):</span>
|
<span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">serve_path</span><span class="p">):</span>
|
||||||
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"Client connected, sending file list..."</span><span class="p">)</span>
|
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"Client connected, sending file list..."</span><span class="p">)</span>
|
||||||
|
|
||||||
<span class="n">link</span><span class="o">.</span><span class="n">link_closed_callback</span><span class="p">(</span><span class="n">client_disconnected</span><span class="p">)</span>
|
<span class="n">link</span><span class="o">.</span><span class="n">set_link_closed_callback</span><span class="p">(</span><span class="n">client_disconnected</span><span class="p">)</span>
|
||||||
|
|
||||||
<span class="c1"># We pack a list of files for sending in a packet</span>
|
<span class="c1"># We pack a list of files for sending in a packet</span>
|
||||||
<span class="n">data</span> <span class="o">=</span> <span class="n">umsgpack</span><span class="o">.</span><span class="n">packb</span><span class="p">(</span><span class="n">list_files</span><span class="p">())</span>
|
<span class="n">data</span> <span class="o">=</span> <span class="n">umsgpack</span><span class="o">.</span><span class="n">packb</span><span class="p">(</span><span class="n">list_files</span><span class="p">())</span>
|
||||||
@@ -1159,8 +1165,8 @@ interface to efficiently pass files of any size over a Reticulum <a class="refer
|
|||||||
<span class="n">list_packet</span> <span class="o">=</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Packet</span><span class="p">(</span><span class="n">link</span><span class="p">,</span> <span class="n">data</span><span class="p">)</span>
|
<span class="n">list_packet</span> <span class="o">=</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Packet</span><span class="p">(</span><span class="n">link</span><span class="p">,</span> <span class="n">data</span><span class="p">)</span>
|
||||||
<span class="n">list_receipt</span> <span class="o">=</span> <span class="n">list_packet</span><span class="o">.</span><span class="n">send</span><span class="p">()</span>
|
<span class="n">list_receipt</span> <span class="o">=</span> <span class="n">list_packet</span><span class="o">.</span><span class="n">send</span><span class="p">()</span>
|
||||||
<span class="n">list_receipt</span><span class="o">.</span><span class="n">set_timeout</span><span class="p">(</span><span class="n">APP_TIMEOUT</span><span class="p">)</span>
|
<span class="n">list_receipt</span><span class="o">.</span><span class="n">set_timeout</span><span class="p">(</span><span class="n">APP_TIMEOUT</span><span class="p">)</span>
|
||||||
<span class="n">list_receipt</span><span class="o">.</span><span class="n">delivery_callback</span><span class="p">(</span><span class="n">list_delivered</span><span class="p">)</span>
|
<span class="n">list_receipt</span><span class="o">.</span><span class="n">set_delivery_callback</span><span class="p">(</span><span class="n">list_delivered</span><span class="p">)</span>
|
||||||
<span class="n">list_receipt</span><span class="o">.</span><span class="n">timeout_callback</span><span class="p">(</span><span class="n">list_timeout</span><span class="p">)</span>
|
<span class="n">list_receipt</span><span class="o">.</span><span class="n">set_timeout_callback</span><span class="p">(</span><span class="n">list_timeout</span><span class="p">)</span>
|
||||||
<span class="k">else</span><span class="p">:</span>
|
<span class="k">else</span><span class="p">:</span>
|
||||||
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"Too many files in served directory!"</span><span class="p">,</span> <span class="n">RNS</span><span class="o">.</span><span class="n">LOG_ERROR</span><span class="p">)</span>
|
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"Too many files in served directory!"</span><span class="p">,</span> <span class="n">RNS</span><span class="o">.</span><span class="n">LOG_ERROR</span><span class="p">)</span>
|
||||||
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"You should implement a function to split the filelist over multiple packets."</span><span class="p">,</span> <span class="n">RNS</span><span class="o">.</span><span class="n">LOG_ERROR</span><span class="p">)</span>
|
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"You should implement a function to split the filelist over multiple packets."</span><span class="p">,</span> <span class="n">RNS</span><span class="o">.</span><span class="n">LOG_ERROR</span><span class="p">)</span>
|
||||||
@@ -1170,7 +1176,7 @@ interface to efficiently pass files of any size over a Reticulum <a class="refer
|
|||||||
<span class="c1"># open until the client requests a file. We'll</span>
|
<span class="c1"># open until the client requests a file. We'll</span>
|
||||||
<span class="c1"># configure a function that get's called when</span>
|
<span class="c1"># configure a function that get's called when</span>
|
||||||
<span class="c1"># the client sends a packet with a file request.</span>
|
<span class="c1"># the client sends a packet with a file request.</span>
|
||||||
<span class="n">link</span><span class="o">.</span><span class="n">packet_callback</span><span class="p">(</span><span class="n">client_request</span><span class="p">)</span>
|
<span class="n">link</span><span class="o">.</span><span class="n">set_packet_callback</span><span class="p">(</span><span class="n">client_request</span><span class="p">)</span>
|
||||||
<span class="k">else</span><span class="p">:</span>
|
<span class="k">else</span><span class="p">:</span>
|
||||||
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"Client connected, but served path no longer exists!"</span><span class="p">,</span> <span class="n">RNS</span><span class="o">.</span><span class="n">LOG_ERROR</span><span class="p">)</span>
|
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"Client connected, but served path no longer exists!"</span><span class="p">,</span> <span class="n">RNS</span><span class="o">.</span><span class="n">LOG_ERROR</span><span class="p">)</span>
|
||||||
<span class="n">link</span><span class="o">.</span><span class="n">teardown</span><span class="p">()</span>
|
<span class="n">link</span><span class="o">.</span><span class="n">teardown</span><span class="p">()</span>
|
||||||
@@ -1299,18 +1305,18 @@ interface to efficiently pass files of any size over a Reticulum <a class="refer
|
|||||||
<span class="c1"># We expect any normal data packets on the link</span>
|
<span class="c1"># We expect any normal data packets on the link</span>
|
||||||
<span class="c1"># to contain a list of served files, so we set</span>
|
<span class="c1"># to contain a list of served files, so we set</span>
|
||||||
<span class="c1"># a callback accordingly</span>
|
<span class="c1"># a callback accordingly</span>
|
||||||
<span class="n">link</span><span class="o">.</span><span class="n">packet_callback</span><span class="p">(</span><span class="n">filelist_received</span><span class="p">)</span>
|
<span class="n">link</span><span class="o">.</span><span class="n">set_packet_callback</span><span class="p">(</span><span class="n">filelist_received</span><span class="p">)</span>
|
||||||
|
|
||||||
<span class="c1"># We'll also set up functions to inform the</span>
|
<span class="c1"># We'll also set up functions to inform the</span>
|
||||||
<span class="c1"># user when the link is established or closed</span>
|
<span class="c1"># user when the link is established or closed</span>
|
||||||
<span class="n">link</span><span class="o">.</span><span class="n">link_established_callback</span><span class="p">(</span><span class="n">link_established</span><span class="p">)</span>
|
<span class="n">link</span><span class="o">.</span><span class="n">set_link_established_callback</span><span class="p">(</span><span class="n">link_established</span><span class="p">)</span>
|
||||||
<span class="n">link</span><span class="o">.</span><span class="n">link_closed_callback</span><span class="p">(</span><span class="n">link_closed</span><span class="p">)</span>
|
<span class="n">link</span><span class="o">.</span><span class="n">set_link_closed_callback</span><span class="p">(</span><span class="n">link_closed</span><span class="p">)</span>
|
||||||
|
|
||||||
<span class="c1"># And set the link to automatically begin</span>
|
<span class="c1"># And set the link to automatically begin</span>
|
||||||
<span class="c1"># downloading advertised resources</span>
|
<span class="c1"># downloading advertised resources</span>
|
||||||
<span class="n">link</span><span class="o">.</span><span class="n">set_resource_strategy</span><span class="p">(</span><span class="n">RNS</span><span class="o">.</span><span class="n">Link</span><span class="o">.</span><span class="n">ACCEPT_ALL</span><span class="p">)</span>
|
<span class="n">link</span><span class="o">.</span><span class="n">set_resource_strategy</span><span class="p">(</span><span class="n">RNS</span><span class="o">.</span><span class="n">Link</span><span class="o">.</span><span class="n">ACCEPT_ALL</span><span class="p">)</span>
|
||||||
<span class="n">link</span><span class="o">.</span><span class="n">resource_started_callback</span><span class="p">(</span><span class="n">download_began</span><span class="p">)</span>
|
<span class="n">link</span><span class="o">.</span><span class="n">set_resource_started_callback</span><span class="p">(</span><span class="n">download_began</span><span class="p">)</span>
|
||||||
<span class="n">link</span><span class="o">.</span><span class="n">resource_concluded_callback</span><span class="p">(</span><span class="n">download_concluded</span><span class="p">)</span>
|
<span class="n">link</span><span class="o">.</span><span class="n">set_resource_concluded_callback</span><span class="p">(</span><span class="n">download_concluded</span><span class="p">)</span>
|
||||||
|
|
||||||
<span class="n">menu</span><span class="p">()</span>
|
<span class="n">menu</span><span class="p">()</span>
|
||||||
|
|
||||||
@@ -1667,11 +1673,8 @@ interface to efficiently pass files of any size over a Reticulum <a class="refer
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h4>Previous topic</h4>
|
<h4>Previous topic</h4>
|
||||||
<p class="topless"><a href="gettingstartedfast.html"
|
|
||||||
title="previous chapter">Getting Started Fast</a></p>
|
|
||||||
<h4>Next topic</h4>
|
|
||||||
<p class="topless"><a href="reference.html"
|
<p class="topless"><a href="reference.html"
|
||||||
title="next chapter">API Reference</a></p>
|
title="previous chapter">API Reference</a></p>
|
||||||
<div role="note" aria-label="source link">
|
<div role="note" aria-label="source link">
|
||||||
<h3>This Page</h3>
|
<h3>This Page</h3>
|
||||||
<ul class="this-page-menu">
|
<ul class="this-page-menu">
|
||||||
@@ -1701,11 +1704,8 @@ interface to efficiently pass files of any size over a Reticulum <a class="refer
|
|||||||
>index</a></li>
|
>index</a></li>
|
||||||
<li class="right" >
|
<li class="right" >
|
||||||
<a href="reference.html" title="API Reference"
|
<a href="reference.html" title="API Reference"
|
||||||
>next</a> |</li>
|
|
||||||
<li class="right" >
|
|
||||||
<a href="gettingstartedfast.html" title="Getting Started Fast"
|
|
||||||
>previous</a> |</li>
|
>previous</a> |</li>
|
||||||
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li>
|
||||||
<li class="nav-item nav-item-this"><a href="">Examples</a></li>
|
<li class="nav-item nav-item-this"><a href="">Examples</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+49
-37
@@ -5,7 +5,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Index — Reticulum Network Stack 0.2.0 beta documentation</title>
|
<title>Index — Reticulum Network Stack 0.2.1 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/classic.css" />
|
<link rel="stylesheet" type="text/css" href="_static/classic.css" />
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
<li class="right" style="margin-right: 10px">
|
<li class="right" style="margin-right: 10px">
|
||||||
<a href="#" title="General Index"
|
<a href="#" title="General Index"
|
||||||
accesskey="I">index</a></li>
|
accesskey="I">index</a></li>
|
||||||
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li>
|
||||||
<li class="nav-item nav-item-this"><a href="">Index</a></li>
|
<li class="nav-item nav-item-this"><a href="">Index</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -80,8 +80,12 @@
|
|||||||
<td style="width: 33%; vertical-align: top;"><ul>
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
<li><a href="reference.html#RNS.Destination.create_keys">create_keys() (RNS.Destination method)</a>
|
<li><a href="reference.html#RNS.Destination.create_keys">create_keys() (RNS.Destination method)</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="reference.html#RNS.Link.CURVE">CURVE (RNS.Link attribute)</a>
|
<li><a href="reference.html#RNS.Identity.CURVE">CURVE (RNS.Identity attribute)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="reference.html#RNS.Link.CURVE">(RNS.Link attribute)</a>
|
||||||
</li>
|
</li>
|
||||||
|
</ul></li>
|
||||||
</ul></td>
|
</ul></td>
|
||||||
</tr></table>
|
</tr></table>
|
||||||
|
|
||||||
@@ -98,8 +102,6 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul></td>
|
</ul></td>
|
||||||
<td style="width: 33%; vertical-align: top;"><ul>
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
<li><a href="reference.html#RNS.PacketReceipt.delivery_callback">delivery_callback() (RNS.PacketReceipt method)</a>
|
|
||||||
</li>
|
|
||||||
<li><a href="reference.html#RNS.Transport.deregister_announce_handler">deregister_announce_handler() (RNS.Transport static method)</a>
|
<li><a href="reference.html#RNS.Transport.deregister_announce_handler">deregister_announce_handler() (RNS.Transport static method)</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="reference.html#RNS.Destination">Destination (class in RNS)</a>
|
<li><a href="reference.html#RNS.Destination">Destination (class in RNS)</a>
|
||||||
@@ -119,11 +121,17 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul></li>
|
</ul></li>
|
||||||
</ul></td>
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Packet.ENCRYPTED_MDU">ENCRYPTED_MDU (RNS.Packet attribute)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
</tr></table>
|
</tr></table>
|
||||||
|
|
||||||
<h2 id="F">F</h2>
|
<h2 id="F">F</h2>
|
||||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
<td style="width: 33%; vertical-align: top;"><ul>
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Identity.from_bytes">from_bytes() (RNS.Identity static method)</a>
|
||||||
|
</li>
|
||||||
<li><a href="reference.html#RNS.Identity.from_file">from_file() (RNS.Identity static method)</a>
|
<li><a href="reference.html#RNS.Identity.from_file">from_file() (RNS.Identity static method)</a>
|
||||||
</li>
|
</li>
|
||||||
</ul></td>
|
</ul></td>
|
||||||
@@ -144,11 +152,13 @@
|
|||||||
<li><a href="reference.html#RNS.Identity.get_private_key">(RNS.Identity method)</a>
|
<li><a href="reference.html#RNS.Identity.get_private_key">(RNS.Identity method)</a>
|
||||||
</li>
|
</li>
|
||||||
</ul></li>
|
</ul></li>
|
||||||
</ul></td>
|
|
||||||
<td style="width: 33%; vertical-align: top;"><ul>
|
|
||||||
<li><a href="reference.html#RNS.Identity.get_public_key">get_public_key() (RNS.Identity method)</a>
|
<li><a href="reference.html#RNS.Identity.get_public_key">get_public_key() (RNS.Identity method)</a>
|
||||||
</li>
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
<li><a href="reference.html#RNS.Identity.get_random_hash">get_random_hash() (RNS.Identity static method)</a>
|
<li><a href="reference.html#RNS.Identity.get_random_hash">get_random_hash() (RNS.Identity static method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.PacketReceipt.get_rtt">get_rtt() (RNS.PacketReceipt method)</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="reference.html#RNS.PacketReceipt.get_status">get_status() (RNS.PacketReceipt method)</a>
|
<li><a href="reference.html#RNS.PacketReceipt.get_status">get_status() (RNS.PacketReceipt method)</a>
|
||||||
</li>
|
</li>
|
||||||
@@ -198,16 +208,14 @@
|
|||||||
<td style="width: 33%; vertical-align: top;"><ul>
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
<li><a href="reference.html#RNS.Link">Link (class in RNS)</a>
|
<li><a href="reference.html#RNS.Link">Link (class in RNS)</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="reference.html#RNS.Destination.link_established_callback">link_established_callback() (RNS.Destination method)</a>
|
|
||||||
</li>
|
|
||||||
</ul></td>
|
|
||||||
<td style="width: 33%; vertical-align: top;"><ul>
|
|
||||||
<li><a href="reference.html#RNS.Destination.load_private_key">load_private_key() (RNS.Destination method)</a>
|
<li><a href="reference.html#RNS.Destination.load_private_key">load_private_key() (RNS.Destination method)</a>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="reference.html#RNS.Identity.load_private_key">(RNS.Identity method)</a>
|
<li><a href="reference.html#RNS.Identity.load_private_key">(RNS.Identity method)</a>
|
||||||
</li>
|
</li>
|
||||||
</ul></li>
|
</ul></li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
<li><a href="reference.html#RNS.Identity.load_public_key">load_public_key() (RNS.Identity method)</a>
|
<li><a href="reference.html#RNS.Identity.load_public_key">load_public_key() (RNS.Identity method)</a>
|
||||||
</li>
|
</li>
|
||||||
</ul></td>
|
</ul></td>
|
||||||
@@ -230,19 +238,13 @@
|
|||||||
<td style="width: 33%; vertical-align: top;"><ul>
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
<li><a href="reference.html#RNS.Packet">Packet (class in RNS)</a>
|
<li><a href="reference.html#RNS.Packet">Packet (class in RNS)</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="reference.html#RNS.Destination.packet_callback">packet_callback() (RNS.Destination method)</a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="reference.html#RNS.Link.packet_callback">(RNS.Link method)</a>
|
|
||||||
</li>
|
|
||||||
</ul></li>
|
|
||||||
</ul></td>
|
|
||||||
<td style="width: 33%; vertical-align: top;"><ul>
|
|
||||||
<li><a href="reference.html#RNS.PacketReceipt">PacketReceipt (class in RNS)</a>
|
<li><a href="reference.html#RNS.PacketReceipt">PacketReceipt (class in RNS)</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="reference.html#RNS.Resource.progress">progress() (RNS.Resource method)</a>
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Packet.PLAIN_MDU">PLAIN_MDU (RNS.Packet attribute)</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="reference.html#RNS.Destination.proof_requested_callback">proof_requested_callback() (RNS.Destination method)</a>
|
<li><a href="reference.html#RNS.Resource.progress">progress() (RNS.Resource method)</a>
|
||||||
</li>
|
</li>
|
||||||
</ul></td>
|
</ul></td>
|
||||||
</tr></table>
|
</tr></table>
|
||||||
@@ -256,23 +258,15 @@
|
|||||||
</li>
|
</li>
|
||||||
<li><a href="reference.html#RNS.Transport.register_announce_handler">register_announce_handler() (RNS.Transport static method)</a>
|
<li><a href="reference.html#RNS.Transport.register_announce_handler">register_announce_handler() (RNS.Transport static method)</a>
|
||||||
</li>
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
<li><a href="reference.html#RNS.Transport.request_path">request_path() (RNS.Transport static method)</a>
|
<li><a href="reference.html#RNS.Transport.request_path">request_path() (RNS.Transport static method)</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="reference.html#RNS.Packet.resend">resend() (RNS.Packet method)</a>
|
<li><a href="reference.html#RNS.Packet.resend">resend() (RNS.Packet method)</a>
|
||||||
</li>
|
</li>
|
||||||
</ul></td>
|
|
||||||
<td style="width: 33%; vertical-align: top;"><ul>
|
|
||||||
<li><a href="reference.html#RNS.Resource">Resource (class in RNS)</a>
|
<li><a href="reference.html#RNS.Resource">Resource (class in RNS)</a>
|
||||||
</li>
|
|
||||||
<li><a href="reference.html#RNS.Link.resource_callback">resource_callback() (RNS.Link method)</a>
|
|
||||||
</li>
|
|
||||||
<li><a href="reference.html#RNS.Link.resource_concluded_callback">resource_concluded_callback() (RNS.Link method)</a>
|
|
||||||
</li>
|
|
||||||
<li><a href="reference.html#RNS.Link.resource_started_callback">resource_started_callback() (RNS.Link method)</a>
|
|
||||||
</li>
|
</li>
|
||||||
<li><a href="reference.html#RNS.Reticulum">Reticulum (class in RNS)</a>
|
<li><a href="reference.html#RNS.Reticulum">Reticulum (class in RNS)</a>
|
||||||
</li>
|
|
||||||
<li><a href="reference.html#RNS.PacketReceipt.rtt">rtt() (RNS.PacketReceipt method)</a>
|
|
||||||
</li>
|
</li>
|
||||||
</ul></td>
|
</ul></td>
|
||||||
</tr></table>
|
</tr></table>
|
||||||
@@ -283,14 +277,34 @@
|
|||||||
<li><a href="reference.html#RNS.Packet.send">send() (RNS.Packet method)</a>
|
<li><a href="reference.html#RNS.Packet.send">send() (RNS.Packet method)</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="reference.html#RNS.Destination.set_default_app_data">set_default_app_data() (RNS.Destination method)</a>
|
<li><a href="reference.html#RNS.Destination.set_default_app_data">set_default_app_data() (RNS.Destination method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.PacketReceipt.set_delivery_callback">set_delivery_callback() (RNS.PacketReceipt method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Destination.set_link_established_callback">set_link_established_callback() (RNS.Destination method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Destination.set_packet_callback">set_packet_callback() (RNS.Destination method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="reference.html#RNS.Link.set_packet_callback">(RNS.Link method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
<li><a href="reference.html#RNS.Destination.set_proof_requested_callback">set_proof_requested_callback() (RNS.Destination method)</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="reference.html#RNS.Destination.set_proof_strategy">set_proof_strategy() (RNS.Destination method)</a>
|
<li><a href="reference.html#RNS.Destination.set_proof_strategy">set_proof_strategy() (RNS.Destination method)</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="reference.html#RNS.Link.set_resource_strategy">set_resource_strategy() (RNS.Link method)</a>
|
<li><a href="reference.html#RNS.Link.set_resource_callback">set_resource_callback() (RNS.Link method)</a>
|
||||||
</li>
|
</li>
|
||||||
</ul></td>
|
</ul></td>
|
||||||
<td style="width: 33%; vertical-align: top;"><ul>
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Link.set_resource_concluded_callback">set_resource_concluded_callback() (RNS.Link method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Link.set_resource_started_callback">set_resource_started_callback() (RNS.Link method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Link.set_resource_strategy">set_resource_strategy() (RNS.Link method)</a>
|
||||||
|
</li>
|
||||||
<li><a href="reference.html#RNS.PacketReceipt.set_timeout">set_timeout() (RNS.PacketReceipt method)</a>
|
<li><a href="reference.html#RNS.PacketReceipt.set_timeout">set_timeout() (RNS.PacketReceipt method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.PacketReceipt.set_timeout_callback">set_timeout_callback() (RNS.PacketReceipt method)</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="reference.html#RNS.Reticulum.should_allow_unencrypted">should_allow_unencrypted() (RNS.Reticulum static method)</a>
|
<li><a href="reference.html#RNS.Reticulum.should_allow_unencrypted">should_allow_unencrypted() (RNS.Reticulum static method)</a>
|
||||||
</li>
|
</li>
|
||||||
@@ -309,15 +323,13 @@
|
|||||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
<td style="width: 33%; vertical-align: top;"><ul>
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
<li><a href="reference.html#RNS.Link.teardown">teardown() (RNS.Link method)</a>
|
<li><a href="reference.html#RNS.Link.teardown">teardown() (RNS.Link method)</a>
|
||||||
</li>
|
|
||||||
<li><a href="reference.html#RNS.PacketReceipt.timeout_callback">timeout_callback() (RNS.PacketReceipt method)</a>
|
|
||||||
</li>
|
</li>
|
||||||
<li><a href="reference.html#RNS.Identity.to_file">to_file() (RNS.Identity method)</a>
|
<li><a href="reference.html#RNS.Identity.to_file">to_file() (RNS.Identity method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Transport">Transport (class in RNS)</a>
|
||||||
</li>
|
</li>
|
||||||
</ul></td>
|
</ul></td>
|
||||||
<td style="width: 33%; vertical-align: top;"><ul>
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
<li><a href="reference.html#RNS.Transport">Transport (class in RNS)</a>
|
|
||||||
</li>
|
|
||||||
<li><a href="reference.html#RNS.Reticulum.transport_enabled">transport_enabled() (RNS.Reticulum static method)</a>
|
<li><a href="reference.html#RNS.Reticulum.transport_enabled">transport_enabled() (RNS.Reticulum static method)</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="reference.html#RNS.Identity.truncated_hash">truncated_hash() (RNS.Identity static method)</a>
|
<li><a href="reference.html#RNS.Identity.truncated_hash">truncated_hash() (RNS.Identity static method)</a>
|
||||||
@@ -363,7 +375,7 @@
|
|||||||
<li class="right" style="margin-right: 10px">
|
<li class="right" style="margin-right: 10px">
|
||||||
<a href="#" title="General Index"
|
<a href="#" title="General Index"
|
||||||
>index</a></li>
|
>index</a></li>
|
||||||
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li>
|
||||||
<li class="nav-item nav-item-this"><a href="">Index</a></li>
|
<li class="nav-item nav-item-this"><a href="">Index</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Getting Started Fast — Reticulum Network Stack 0.2.0 beta documentation</title>
|
<title>Getting Started Fast — Reticulum Network Stack 0.2.1 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/classic.css" />
|
<link rel="stylesheet" type="text/css" href="_static/classic.css" />
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
<li class="right" >
|
<li class="right" >
|
||||||
<a href="whatis.html" title="What is Reticulum?"
|
<a href="whatis.html" title="What is Reticulum?"
|
||||||
accesskey="P">previous</a> |</li>
|
accesskey="P">previous</a> |</li>
|
||||||
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li>
|
||||||
<li class="nav-item nav-item-this"><a href="">Getting Started Fast</a></li>
|
<li class="nav-item nav-item-this"><a href="">Getting Started Fast</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -43,7 +43,6 @@
|
|||||||
|
|
||||||
<div class="section" id="getting-started-fast">
|
<div class="section" id="getting-started-fast">
|
||||||
<h1>Getting Started Fast<a class="headerlink" href="#getting-started-fast" title="Permalink to this headline">¶</a></h1>
|
<h1>Getting Started Fast<a class="headerlink" href="#getting-started-fast" title="Permalink to this headline">¶</a></h1>
|
||||||
<p>What do we want to do? Something! When do we want to do it? Right now! Let’s go.</p>
|
|
||||||
<p>The best way to get started with the Reticulum Network Stack depends on what
|
<p>The best way to get started with the Reticulum Network Stack depends on what
|
||||||
you want to do. This guide will outline sensible starting paths for different
|
you want to do. This guide will outline sensible starting paths for different
|
||||||
scenarios.</p>
|
scenarios.</p>
|
||||||
@@ -60,7 +59,7 @@ in the development for the messaging and information-sharing protocol
|
|||||||
<div class="section" id="develop-a-program-with-reticulum">
|
<div class="section" id="develop-a-program-with-reticulum">
|
||||||
<h2>Develop a Program with Reticulum<a class="headerlink" href="#develop-a-program-with-reticulum" title="Permalink to this headline">¶</a></h2>
|
<h2>Develop a Program with Reticulum<a class="headerlink" href="#develop-a-program-with-reticulum" title="Permalink to this headline">¶</a></h2>
|
||||||
<p>If you want to develop programs that use Reticulum, the easiest way to get
|
<p>If you want to develop programs that use Reticulum, the easiest way to get
|
||||||
started is to install Reticulum via pip:</p>
|
started is to install the latest release of Reticulum via pip:</p>
|
||||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pip3</span> <span class="n">install</span> <span class="n">rns</span>
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pip3</span> <span class="n">install</span> <span class="n">rns</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -167,7 +166,7 @@ don’t use pip, but try this recipe:</p>
|
|||||||
<li class="right" >
|
<li class="right" >
|
||||||
<a href="whatis.html" title="What is Reticulum?"
|
<a href="whatis.html" title="What is Reticulum?"
|
||||||
>previous</a> |</li>
|
>previous</a> |</li>
|
||||||
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li>
|
||||||
<li class="nav-item nav-item-this"><a href="">Getting Started Fast</a></li>
|
<li class="nav-item nav-item-this"><a href="">Getting Started Fast</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+33
-32
@@ -5,7 +5,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Reticulum Network Stack Manual — Reticulum Network Stack 0.2.0 beta documentation</title>
|
<title>Reticulum Network Stack Manual — Reticulum Network Stack 0.2.1 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/classic.css" />
|
<link rel="stylesheet" type="text/css" href="_static/classic.css" />
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
<li class="right" >
|
<li class="right" >
|
||||||
<a href="whatis.html" title="What is Reticulum?"
|
<a href="whatis.html" title="What is Reticulum?"
|
||||||
accesskey="N">next</a> |</li>
|
accesskey="N">next</a> |</li>
|
||||||
<li class="nav-item nav-item-0"><a href="#">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
<li class="nav-item nav-item-0"><a href="#">Reticulum Network Stack 0.2.1 beta documentation</a> »</li>
|
||||||
<li class="nav-item nav-item-this"><a href="">Reticulum Network Stack Manual</a></li>
|
<li class="nav-item nav-item-this"><a href="">Reticulum Network Stack Manual</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -58,13 +58,29 @@ the development of Reticulum itself.</p>
|
|||||||
<li class="toctree-l2"><a class="reference internal" href="gettingstartedfast.html#participate-in-reticulum-development">Participate in Reticulum Development</a></li>
|
<li class="toctree-l2"><a class="reference internal" href="gettingstartedfast.html#participate-in-reticulum-development">Participate in Reticulum Development</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li class="toctree-l1"><a class="reference internal" href="examples.html">Examples</a><ul>
|
<li class="toctree-l1"><a class="reference internal" href="understanding.html">Understanding Reticulum</a><ul>
|
||||||
<li class="toctree-l2"><a class="reference internal" href="examples.html#minimal">Minimal</a></li>
|
<li class="toctree-l2"><a class="reference internal" href="understanding.html#motivation">Motivation</a></li>
|
||||||
<li class="toctree-l2"><a class="reference internal" href="examples.html#announce">Announce</a></li>
|
<li class="toctree-l2"><a class="reference internal" href="understanding.html#goals">Goals</a></li>
|
||||||
<li class="toctree-l2"><a class="reference internal" href="examples.html#broadcast">Broadcast</a></li>
|
<li class="toctree-l2"><a class="reference internal" href="understanding.html#introduction-basic-functionality">Introduction & Basic Functionality</a><ul>
|
||||||
<li class="toctree-l2"><a class="reference internal" href="examples.html#echo">Echo</a></li>
|
<li class="toctree-l3"><a class="reference internal" href="understanding.html#destinations">Destinations</a></li>
|
||||||
<li class="toctree-l2"><a class="reference internal" href="examples.html#link">Link</a></li>
|
<li class="toctree-l3"><a class="reference internal" href="understanding.html#public-key-announcements">Public Key Announcements</a></li>
|
||||||
<li class="toctree-l2"><a class="reference internal" href="examples.html#filetransfer">Filetransfer</a></li>
|
<li class="toctree-l3"><a class="reference internal" href="understanding.html#understanding-identities">Identities</a></li>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="understanding.html#getting-further">Getting Further</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="understanding.html#reticulum-transport">Reticulum Transport</a><ul>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="understanding.html#the-announce-mechanism-in-detail">The Announce Mechanism in Detail</a></li>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="understanding.html#reaching-the-destination">Reaching the Destination</a></li>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="understanding.html#resources">Resources</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="understanding.html#reference-system-setup">Reference System Setup</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="understanding.html#protocol-specifics">Protocol Specifics</a><ul>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="understanding.html#node-types">Node Types</a></li>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="understanding.html#packet-prioritisation">Packet Prioritisation</a></li>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="understanding.html#binary-packet-format">Binary Packet Format</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li class="toctree-l1"><a class="reference internal" href="reference.html">API Reference</a><ul>
|
<li class="toctree-l1"><a class="reference internal" href="reference.html">API Reference</a><ul>
|
||||||
@@ -81,28 +97,13 @@ the development of Reticulum itself.</p>
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li class="toctree-l1"><a class="reference internal" href="understanding.html">Understanding Reticulum</a><ul>
|
<li class="toctree-l1"><a class="reference internal" href="examples.html">Examples</a><ul>
|
||||||
<li class="toctree-l2"><a class="reference internal" href="understanding.html#motivation">Motivation</a></li>
|
<li class="toctree-l2"><a class="reference internal" href="examples.html#minimal">Minimal</a></li>
|
||||||
<li class="toctree-l2"><a class="reference internal" href="understanding.html#goals">Goals</a></li>
|
<li class="toctree-l2"><a class="reference internal" href="examples.html#announce">Announce</a></li>
|
||||||
<li class="toctree-l2"><a class="reference internal" href="understanding.html#introduction-basic-functionality">Introduction & Basic Functionality</a><ul>
|
<li class="toctree-l2"><a class="reference internal" href="examples.html#broadcast">Broadcast</a></li>
|
||||||
<li class="toctree-l3"><a class="reference internal" href="understanding.html#destinations">Destinations</a></li>
|
<li class="toctree-l2"><a class="reference internal" href="examples.html#echo">Echo</a></li>
|
||||||
<li class="toctree-l3"><a class="reference internal" href="understanding.html#public-key-announcements">Public Key Announcements</a></li>
|
<li class="toctree-l2"><a class="reference internal" href="examples.html#link">Link</a></li>
|
||||||
<li class="toctree-l3"><a class="reference internal" href="understanding.html#understanding-identities">Identities</a></li>
|
<li class="toctree-l2"><a class="reference internal" href="examples.html#filetransfer">Filetransfer</a></li>
|
||||||
<li class="toctree-l3"><a class="reference internal" href="understanding.html#getting-further">Getting Further</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li class="toctree-l2"><a class="reference internal" href="understanding.html#reticulum-transport">Reticulum Transport</a><ul>
|
|
||||||
<li class="toctree-l3"><a class="reference internal" href="understanding.html#reaching-the-destination">Reaching the Destination</a></li>
|
|
||||||
<li class="toctree-l3"><a class="reference internal" href="understanding.html#resources">Resources</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li class="toctree-l2"><a class="reference internal" href="understanding.html#reference-system-setup">Reference System Setup</a></li>
|
|
||||||
<li class="toctree-l2"><a class="reference internal" href="understanding.html#protocol-specifics">Protocol Specifics</a><ul>
|
|
||||||
<li class="toctree-l3"><a class="reference internal" href="understanding.html#node-types">Node Types</a></li>
|
|
||||||
<li class="toctree-l3"><a class="reference internal" href="understanding.html#packet-prioritisation">Packet Prioritisation</a></li>
|
|
||||||
<li class="toctree-l3"><a class="reference internal" href="understanding.html#binary-packet-format">Binary Packet Format</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -164,7 +165,7 @@ the development of Reticulum itself.</p>
|
|||||||
<li class="right" >
|
<li class="right" >
|
||||||
<a href="whatis.html" title="What is Reticulum?"
|
<a href="whatis.html" title="What is Reticulum?"
|
||||||
>next</a> |</li>
|
>next</a> |</li>
|
||||||
<li class="nav-item nav-item-0"><a href="#">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
<li class="nav-item nav-item-0"><a href="#">Reticulum Network Stack 0.2.1 beta documentation</a> »</li>
|
||||||
<li class="nav-item nav-item-this"><a href="">Reticulum Network Stack Manual</a></li>
|
<li class="nav-item nav-item-this"><a href="">Reticulum Network Stack Manual</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Binary file not shown.
+91
-53
@@ -5,7 +5,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>API Reference — Reticulum Network Stack 0.2.0 beta documentation</title>
|
<title>API Reference — Reticulum Network Stack 0.2.1 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/classic.css" />
|
<link rel="stylesheet" type="text/css" href="_static/classic.css" />
|
||||||
|
|
||||||
@@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
<link rel="index" title="Index" href="genindex.html" />
|
<link rel="index" title="Index" href="genindex.html" />
|
||||||
<link rel="search" title="Search" href="search.html" />
|
<link rel="search" title="Search" href="search.html" />
|
||||||
<link rel="next" title="Understanding Reticulum" href="understanding.html" />
|
<link rel="next" title="Examples" href="examples.html" />
|
||||||
<link rel="prev" title="Examples" href="examples.html" />
|
<link rel="prev" title="Understanding Reticulum" href="understanding.html" />
|
||||||
</head><body>
|
</head><body>
|
||||||
<div class="related" role="navigation" aria-label="related navigation">
|
<div class="related" role="navigation" aria-label="related navigation">
|
||||||
<h3>Navigation</h3>
|
<h3>Navigation</h3>
|
||||||
@@ -26,12 +26,12 @@
|
|||||||
<a href="genindex.html" title="General Index"
|
<a href="genindex.html" title="General Index"
|
||||||
accesskey="I">index</a></li>
|
accesskey="I">index</a></li>
|
||||||
<li class="right" >
|
<li class="right" >
|
||||||
<a href="understanding.html" title="Understanding Reticulum"
|
<a href="examples.html" title="Examples"
|
||||||
accesskey="N">next</a> |</li>
|
accesskey="N">next</a> |</li>
|
||||||
<li class="right" >
|
<li class="right" >
|
||||||
<a href="examples.html" title="Examples"
|
<a href="understanding.html" title="Understanding Reticulum"
|
||||||
accesskey="P">previous</a> |</li>
|
accesskey="P">previous</a> |</li>
|
||||||
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li>
|
||||||
<li class="nav-item nav-item-this"><a href="">API Reference</a></li>
|
<li class="nav-item nav-item-this"><a href="">API Reference</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -117,26 +117,32 @@ and pass announces over the network.</p>
|
|||||||
<span id="identity"></span><h3>Identity<a class="headerlink" href="#api-identity" title="Permalink to this headline">¶</a></h3>
|
<span id="identity"></span><h3>Identity<a class="headerlink" href="#api-identity" title="Permalink to this headline">¶</a></h3>
|
||||||
<dl class="py class">
|
<dl class="py class">
|
||||||
<dt class="sig sig-object py" id="RNS.Identity">
|
<dt class="sig sig-object py" id="RNS.Identity">
|
||||||
<em class="property"><span class="pre">class</span> </em><span class="sig-prename descclassname"><span class="pre">RNS.</span></span><span class="sig-name descname"><span class="pre">Identity</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">public_only</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Identity" title="Permalink to this definition">¶</a></dt>
|
<em class="property"><span class="pre">class</span> </em><span class="sig-prename descclassname"><span class="pre">RNS.</span></span><span class="sig-name descname"><span class="pre">Identity</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">create_keys</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Identity" title="Permalink to this definition">¶</a></dt>
|
||||||
<dd><p>This class is used to manage identities in Reticulum. It provides methods
|
<dd><p>This class is used to manage identities in Reticulum. It provides methods
|
||||||
for encryption, decryption, signatures and verification, and is the basis
|
for encryption, decryption, signatures and verification, and is the basis
|
||||||
for all encrypted communication over Reticulum networks.</p>
|
for all encrypted communication over Reticulum networks.</p>
|
||||||
<dl class="field-list simple">
|
<dl class="field-list simple">
|
||||||
<dt class="field-odd">Parameters</dt>
|
<dt class="field-odd">Parameters</dt>
|
||||||
<dd class="field-odd"><p><strong>public_only</strong> – Specifies whether this destination only holds a public key.</p>
|
<dd class="field-odd"><p><strong>create_keys</strong> – Specifies whether new encryption and signing keys should be generated.</p>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
<dl class="py attribute">
|
||||||
|
<dt class="sig sig-object py" id="RNS.Identity.CURVE">
|
||||||
|
<span class="sig-name descname"><span class="pre">CURVE</span></span><em class="property"> <span class="pre">=</span> <span class="pre">'Curve25519'</span></em><a class="headerlink" href="#RNS.Identity.CURVE" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>The curve used for Elliptic Curve DH key exchanges</p>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="py attribute">
|
<dl class="py attribute">
|
||||||
<dt class="sig sig-object py" id="RNS.Identity.KEYSIZE">
|
<dt class="sig sig-object py" id="RNS.Identity.KEYSIZE">
|
||||||
<span class="sig-name descname"><span class="pre">KEYSIZE</span></span><em class="property"> <span class="pre">=</span> <span class="pre">1024</span></em><a class="headerlink" href="#RNS.Identity.KEYSIZE" title="Permalink to this definition">¶</a></dt>
|
<span class="sig-name descname"><span class="pre">KEYSIZE</span></span><em class="property"> <span class="pre">=</span> <span class="pre">512</span></em><a class="headerlink" href="#RNS.Identity.KEYSIZE" title="Permalink to this definition">¶</a></dt>
|
||||||
<dd><p>RSA key size in bits.</p>
|
<dd><p>X25519 key size in bits. A complete key is the concatenation of a 256 bit encryption key, and a 256 bit signing key.</p>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="py attribute">
|
<dl class="py attribute">
|
||||||
<dt class="sig sig-object py" id="RNS.Identity.TRUNCATED_HASHLENGTH">
|
<dt class="sig sig-object py" id="RNS.Identity.TRUNCATED_HASHLENGTH">
|
||||||
<span class="sig-name descname"><span class="pre">TRUNCATED_HASHLENGTH</span></span><em class="property"> <span class="pre">=</span> <span class="pre">80</span></em><a class="headerlink" href="#RNS.Identity.TRUNCATED_HASHLENGTH" title="Permalink to this definition">¶</a></dt>
|
<span class="sig-name descname"><span class="pre">TRUNCATED_HASHLENGTH</span></span><em class="property"> <span class="pre">=</span> <span class="pre">80</span></em><a class="headerlink" href="#RNS.Identity.TRUNCATED_HASHLENGTH" title="Permalink to this definition">¶</a></dt>
|
||||||
<dd><p>Constant specifying the truncated hash length (in bits) used by Reticulum
|
<dd><p>Constant specifying the truncated hash length (in bits) used by Reticulum
|
||||||
for addressable hashes. Non-configurable.</p>
|
for addressable hashes and other purposes. Non-configurable.</p>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="py method">
|
<dl class="py method">
|
||||||
@@ -224,6 +230,21 @@ Can be used to load previously created and saved identities into Reticulum.</p>
|
|||||||
</dl>
|
</dl>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="py method">
|
||||||
|
<dt class="sig sig-object py" id="RNS.Identity.from_bytes">
|
||||||
|
<em class="property"><span class="pre">static</span> </em><span class="sig-name descname"><span class="pre">from_bytes</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">prv_bytes</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Identity.from_bytes" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>Create a new <a class="reference internal" href="#api-identity"><span class="std std-ref">RNS.Identity</span></a> instance from <em>bytes</em> of private key.
|
||||||
|
Can be used to load previously created and saved identities into Reticulum.</p>
|
||||||
|
<dl class="field-list simple">
|
||||||
|
<dt class="field-odd">Parameters</dt>
|
||||||
|
<dd class="field-odd"><p><strong>prv_bytes</strong> – The <em>bytes</em> of private a saved private key. <strong>HAZARD!</strong> Never not use this to generate a new key by feeding random data in prv_bytes.</p>
|
||||||
|
</dd>
|
||||||
|
<dt class="field-even">Returns</dt>
|
||||||
|
<dd class="field-even"><p>A <a class="reference internal" href="#api-identity"><span class="std std-ref">RNS.Identity</span></a> instance, or <em>None</em> if the <em>bytes</em> data was invalid.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="py method">
|
<dl class="py method">
|
||||||
<dt class="sig sig-object py" id="RNS.Identity.get_private_key">
|
<dt class="sig sig-object py" id="RNS.Identity.get_private_key">
|
||||||
<span class="sig-name descname"><span class="pre">get_private_key</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Identity.get_private_key" title="Permalink to this definition">¶</a></dt>
|
<span class="sig-name descname"><span class="pre">get_private_key</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Identity.get_private_key" title="Permalink to this definition">¶</a></dt>
|
||||||
@@ -260,11 +281,11 @@ Can be used to load previously created and saved identities into Reticulum.</p>
|
|||||||
|
|
||||||
<dl class="py method">
|
<dl class="py method">
|
||||||
<dt class="sig sig-object py" id="RNS.Identity.load_public_key">
|
<dt class="sig sig-object py" id="RNS.Identity.load_public_key">
|
||||||
<span class="sig-name descname"><span class="pre">load_public_key</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">key</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Identity.load_public_key" title="Permalink to this definition">¶</a></dt>
|
<span class="sig-name descname"><span class="pre">load_public_key</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">pub_bytes</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Identity.load_public_key" title="Permalink to this definition">¶</a></dt>
|
||||||
<dd><p>Load a public key into the instance.</p>
|
<dd><p>Load a public key into the instance.</p>
|
||||||
<dl class="field-list simple">
|
<dl class="field-list simple">
|
||||||
<dt class="field-odd">Parameters</dt>
|
<dt class="field-odd">Parameters</dt>
|
||||||
<dd class="field-odd"><p><strong>prv_bytes</strong> – The public key as <em>bytes</em>.</p>
|
<dd class="field-odd"><p><strong>pub_bytes</strong> – The public key as <em>bytes</em>.</p>
|
||||||
</dd>
|
</dd>
|
||||||
<dt class="field-even">Returns</dt>
|
<dt class="field-even">Returns</dt>
|
||||||
<dd class="field-even"><p>True if the key was loaded, otherwise False.</p>
|
<dd class="field-even"><p>True if the key was loaded, otherwise False.</p>
|
||||||
@@ -297,17 +318,17 @@ communication for the identity. Be very careful with this method.</p>
|
|||||||
<dd class="field-odd"><p><strong>plaintext</strong> – The plaintext to be encrypted as <em>bytes</em>.</p>
|
<dd class="field-odd"><p><strong>plaintext</strong> – The plaintext to be encrypted as <em>bytes</em>.</p>
|
||||||
</dd>
|
</dd>
|
||||||
<dt class="field-even">Returns</dt>
|
<dt class="field-even">Returns</dt>
|
||||||
<dd class="field-even"><p>Ciphertext as <em>bytes</em>.</p>
|
<dd class="field-even"><p>Ciphertext token as <em>bytes</em>.</p>
|
||||||
</dd>
|
</dd>
|
||||||
<dt class="field-odd">Raises</dt>
|
<dt class="field-odd">Raises</dt>
|
||||||
<dd class="field-odd"><p><em>KeyError</em> if the instance does not hold a public key</p>
|
<dd class="field-odd"><p><em>KeyError</em> if the instance does not hold a public key.</p>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="py method">
|
<dl class="py method">
|
||||||
<dt class="sig sig-object py" id="RNS.Identity.decrypt">
|
<dt class="sig sig-object py" id="RNS.Identity.decrypt">
|
||||||
<span class="sig-name descname"><span class="pre">decrypt</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">ciphertext</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Identity.decrypt" title="Permalink to this definition">¶</a></dt>
|
<span class="sig-name descname"><span class="pre">decrypt</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">ciphertext_token</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Identity.decrypt" title="Permalink to this definition">¶</a></dt>
|
||||||
<dd><p>Decrypts information for the identity.</p>
|
<dd><p>Decrypts information for the identity.</p>
|
||||||
<dl class="field-list simple">
|
<dl class="field-list simple">
|
||||||
<dt class="field-odd">Parameters</dt>
|
<dt class="field-odd">Parameters</dt>
|
||||||
@@ -317,7 +338,7 @@ communication for the identity. Be very careful with this method.</p>
|
|||||||
<dd class="field-even"><p>Plaintext as <em>bytes</em>, or <em>None</em> if decryption fails.</p>
|
<dd class="field-even"><p>Plaintext as <em>bytes</em>, or <em>None</em> if decryption fails.</p>
|
||||||
</dd>
|
</dd>
|
||||||
<dt class="field-odd">Raises</dt>
|
<dt class="field-odd">Raises</dt>
|
||||||
<dd class="field-odd"><p><em>KeyError</em> if the instance does not hold a private key</p>
|
<dd class="field-odd"><p><em>KeyError</em> if the instance does not hold a private key.</p>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
@@ -334,7 +355,7 @@ communication for the identity. Be very careful with this method.</p>
|
|||||||
<dd class="field-even"><p>Signature as <em>bytes</em>.</p>
|
<dd class="field-even"><p>Signature as <em>bytes</em>.</p>
|
||||||
</dd>
|
</dd>
|
||||||
<dt class="field-odd">Raises</dt>
|
<dt class="field-odd">Raises</dt>
|
||||||
<dd class="field-odd"><p><em>KeyError</em> if the instance does not hold a private key</p>
|
<dd class="field-odd"><p><em>KeyError</em> if the instance does not hold a private key.</p>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
@@ -354,7 +375,7 @@ communication for the identity. Be very careful with this method.</p>
|
|||||||
<dd class="field-even"><p>True if the signature is valid, otherwise False.</p>
|
<dd class="field-even"><p>True if the signature is valid, otherwise False.</p>
|
||||||
</dd>
|
</dd>
|
||||||
<dt class="field-odd">Raises</dt>
|
<dt class="field-odd">Raises</dt>
|
||||||
<dd class="field-odd"><p><em>KeyError</em> if the instance does not hold a public key</p>
|
<dd class="field-odd"><p><em>KeyError</em> if the instance does not hold a public key.</p>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
@@ -427,8 +448,8 @@ encrypted communication with it.</p>
|
|||||||
<dl class="py method">
|
<dl class="py method">
|
||||||
<dt class="sig sig-object py" id="RNS.Destination.announce">
|
<dt class="sig sig-object py" id="RNS.Destination.announce">
|
||||||
<span class="sig-name descname"><span class="pre">announce</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">app_data</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">path_response</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Destination.announce" title="Permalink to this definition">¶</a></dt>
|
<span class="sig-name descname"><span class="pre">announce</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">app_data</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">path_response</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Destination.announce" title="Permalink to this definition">¶</a></dt>
|
||||||
<dd><p>Creates an announce packet for this destination and broadcasts it on
|
<dd><p>Creates an announce packet for this destination and broadcasts it on all
|
||||||
all interfaces. Application specific data can be added to the announce.</p>
|
relevant interfaces. Application specific data can be added to the announce.</p>
|
||||||
<dl class="field-list simple">
|
<dl class="field-list simple">
|
||||||
<dt class="field-odd">Parameters</dt>
|
<dt class="field-odd">Parameters</dt>
|
||||||
<dd class="field-odd"><ul class="simple">
|
<dd class="field-odd"><ul class="simple">
|
||||||
@@ -440,8 +461,8 @@ all interfaces. Application specific data can be added to the announce.</p>
|
|||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="py method">
|
<dl class="py method">
|
||||||
<dt class="sig sig-object py" id="RNS.Destination.link_established_callback">
|
<dt class="sig sig-object py" id="RNS.Destination.set_link_established_callback">
|
||||||
<span class="sig-name descname"><span class="pre">link_established_callback</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">callback</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Destination.link_established_callback" title="Permalink to this definition">¶</a></dt>
|
<span class="sig-name descname"><span class="pre">set_link_established_callback</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">callback</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Destination.set_link_established_callback" title="Permalink to this definition">¶</a></dt>
|
||||||
<dd><p>Registers a function to be called when a link has been established to
|
<dd><p>Registers a function to be called when a link has been established to
|
||||||
this destination.</p>
|
this destination.</p>
|
||||||
<dl class="field-list simple">
|
<dl class="field-list simple">
|
||||||
@@ -452,8 +473,8 @@ this destination.</p>
|
|||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="py method">
|
<dl class="py method">
|
||||||
<dt class="sig sig-object py" id="RNS.Destination.packet_callback">
|
<dt class="sig sig-object py" id="RNS.Destination.set_packet_callback">
|
||||||
<span class="sig-name descname"><span class="pre">packet_callback</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">callback</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Destination.packet_callback" title="Permalink to this definition">¶</a></dt>
|
<span class="sig-name descname"><span class="pre">set_packet_callback</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">callback</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Destination.set_packet_callback" title="Permalink to this definition">¶</a></dt>
|
||||||
<dd><p>Registers a function to be called when a packet has been received by
|
<dd><p>Registers a function to be called when a packet has been received by
|
||||||
this destination.</p>
|
this destination.</p>
|
||||||
<dl class="field-list simple">
|
<dl class="field-list simple">
|
||||||
@@ -464,8 +485,8 @@ this destination.</p>
|
|||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="py method">
|
<dl class="py method">
|
||||||
<dt class="sig sig-object py" id="RNS.Destination.proof_requested_callback">
|
<dt class="sig sig-object py" id="RNS.Destination.set_proof_requested_callback">
|
||||||
<span class="sig-name descname"><span class="pre">proof_requested_callback</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">callback</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Destination.proof_requested_callback" title="Permalink to this definition">¶</a></dt>
|
<span class="sig-name descname"><span class="pre">set_proof_requested_callback</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">callback</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Destination.set_proof_requested_callback" title="Permalink to this definition">¶</a></dt>
|
||||||
<dd><p>Registers a function to be called when a proof has been requested for
|
<dd><p>Registers a function to be called when a proof has been requested for
|
||||||
a packet sent to this destination. Allows control over when and if
|
a packet sent to this destination. Allows control over when and if
|
||||||
proofs should be returned for received packets.</p>
|
proofs should be returned for received packets.</p>
|
||||||
@@ -592,8 +613,14 @@ unless other app_data is specified in the <em>announce</em> method.</p>
|
|||||||
<dl class="py class">
|
<dl class="py class">
|
||||||
<dt class="sig sig-object py" id="RNS.Packet">
|
<dt class="sig sig-object py" id="RNS.Packet">
|
||||||
<em class="property"><span class="pre">class</span> </em><span class="sig-prename descclassname"><span class="pre">RNS.</span></span><span class="sig-name descname"><span class="pre">Packet</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">destination</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">data</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">packet_type</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">context</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">transport_type</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">header_type</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">transport_id</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">attached_interface</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">create_receipt</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Packet" title="Permalink to this definition">¶</a></dt>
|
<em class="property"><span class="pre">class</span> </em><span class="sig-prename descclassname"><span class="pre">RNS.</span></span><span class="sig-name descname"><span class="pre">Packet</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">destination</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">data</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">packet_type</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">context</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">transport_type</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">header_type</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">transport_id</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">attached_interface</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">create_receipt</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Packet" title="Permalink to this definition">¶</a></dt>
|
||||||
<dd><p>The Packet class is used to create packet instances that can be
|
<dd><p>The Packet class is used to create packet instances that can be sent
|
||||||
sent over a Reticulum network.</p>
|
over a Reticulum network. Packets to will automatically be encrypted if
|
||||||
|
they are adressed to a <code class="docutils literal notranslate"><span class="pre">RNS.Destination.SINGLE</span></code> destination,
|
||||||
|
<code class="docutils literal notranslate"><span class="pre">RNS.Destination.GROUP</span></code> destination or a <a class="reference internal" href="#api-link"><span class="std std-ref">RNS.Link</span></a>.</p>
|
||||||
|
<p>For <code class="docutils literal notranslate"><span class="pre">RNS.Destination.GROUP</span></code> destinations, Reticulum will use the
|
||||||
|
pre-shared key configured for the destination.</p>
|
||||||
|
<p>For <code class="docutils literal notranslate"><span class="pre">RNS.Destination.SINGLE</span></code> destinations and <a class="reference internal" href="#api-link"><span class="std std-ref">RNS.Link</span></a>
|
||||||
|
destinations, reticulum will use ephemeral keys, and offers <strong>Forward Secrecy</strong>.</p>
|
||||||
<dl class="field-list simple">
|
<dl class="field-list simple">
|
||||||
<dt class="field-odd">Parameters</dt>
|
<dt class="field-odd">Parameters</dt>
|
||||||
<dd class="field-odd"><ul class="simple">
|
<dd class="field-odd"><ul class="simple">
|
||||||
@@ -608,6 +635,18 @@ sent over a Reticulum network.</p>
|
|||||||
</ul>
|
</ul>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
<dl class="py attribute">
|
||||||
|
<dt class="sig sig-object py" id="RNS.Packet.ENCRYPTED_MDU">
|
||||||
|
<span class="sig-name descname"><span class="pre">ENCRYPTED_MDU</span></span><em class="property"> <span class="pre">=</span> <span class="pre">383</span></em><a class="headerlink" href="#RNS.Packet.ENCRYPTED_MDU" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>The maximum size of the payload data in a single encrypted packet</p>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="py attribute">
|
||||||
|
<dt class="sig sig-object py" id="RNS.Packet.PLAIN_MDU">
|
||||||
|
<span class="sig-name descname"><span class="pre">PLAIN_MDU</span></span><em class="property"> <span class="pre">=</span> <span class="pre">477</span></em><a class="headerlink" href="#RNS.Packet.PLAIN_MDU" title="Permalink to this definition">¶</a></dt>
|
||||||
|
<dd><p>The maximum size of the payload data in a single unencrypted packet</p>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="py method">
|
<dl class="py method">
|
||||||
<dt class="sig sig-object py" id="RNS.Packet.send">
|
<dt class="sig sig-object py" id="RNS.Packet.send">
|
||||||
<span class="sig-name descname"><span class="pre">send</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Packet.send" title="Permalink to this definition">¶</a></dt>
|
<span class="sig-name descname"><span class="pre">send</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Packet.send" title="Permalink to this definition">¶</a></dt>
|
||||||
@@ -653,8 +692,8 @@ from a the <em>send()</em> method of a <a class="reference internal" href="#api-
|
|||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="py method">
|
<dl class="py method">
|
||||||
<dt class="sig sig-object py" id="RNS.PacketReceipt.rtt">
|
<dt class="sig sig-object py" id="RNS.PacketReceipt.get_rtt">
|
||||||
<span class="sig-name descname"><span class="pre">rtt</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#RNS.PacketReceipt.rtt" title="Permalink to this definition">¶</a></dt>
|
<span class="sig-name descname"><span class="pre">get_rtt</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#RNS.PacketReceipt.get_rtt" title="Permalink to this definition">¶</a></dt>
|
||||||
<dd><dl class="field-list simple">
|
<dd><dl class="field-list simple">
|
||||||
<dt class="field-odd">Returns</dt>
|
<dt class="field-odd">Returns</dt>
|
||||||
<dd class="field-odd"><p>The round-trip-time in seconds</p>
|
<dd class="field-odd"><p>The round-trip-time in seconds</p>
|
||||||
@@ -674,8 +713,8 @@ from a the <em>send()</em> method of a <a class="reference internal" href="#api-
|
|||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="py method">
|
<dl class="py method">
|
||||||
<dt class="sig sig-object py" id="RNS.PacketReceipt.delivery_callback">
|
<dt class="sig sig-object py" id="RNS.PacketReceipt.set_delivery_callback">
|
||||||
<span class="sig-name descname"><span class="pre">delivery_callback</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">callback</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.PacketReceipt.delivery_callback" title="Permalink to this definition">¶</a></dt>
|
<span class="sig-name descname"><span class="pre">set_delivery_callback</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">callback</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.PacketReceipt.set_delivery_callback" title="Permalink to this definition">¶</a></dt>
|
||||||
<dd><p>Sets a function that gets called if a successfull delivery has been proven.</p>
|
<dd><p>Sets a function that gets called if a successfull delivery has been proven.</p>
|
||||||
<dl class="field-list simple">
|
<dl class="field-list simple">
|
||||||
<dt class="field-odd">Parameters</dt>
|
<dt class="field-odd">Parameters</dt>
|
||||||
@@ -685,8 +724,8 @@ from a the <em>send()</em> method of a <a class="reference internal" href="#api-
|
|||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="py method">
|
<dl class="py method">
|
||||||
<dt class="sig sig-object py" id="RNS.PacketReceipt.timeout_callback">
|
<dt class="sig sig-object py" id="RNS.PacketReceipt.set_timeout_callback">
|
||||||
<span class="sig-name descname"><span class="pre">timeout_callback</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">callback</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.PacketReceipt.timeout_callback" title="Permalink to this definition">¶</a></dt>
|
<span class="sig-name descname"><span class="pre">set_timeout_callback</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">callback</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.PacketReceipt.set_timeout_callback" title="Permalink to this definition">¶</a></dt>
|
||||||
<dd><p>Sets a function that gets called if the delivery times out.</p>
|
<dd><p>Sets a function that gets called if the delivery times out.</p>
|
||||||
<dl class="field-list simple">
|
<dl class="field-list simple">
|
||||||
<dt class="field-odd">Parameters</dt>
|
<dt class="field-odd">Parameters</dt>
|
||||||
@@ -728,7 +767,7 @@ from a the <em>send()</em> method of a <a class="reference internal" href="#api-
|
|||||||
|
|
||||||
<dl class="py attribute">
|
<dl class="py attribute">
|
||||||
<dt class="sig sig-object py" id="RNS.Link.KEEPALIVE">
|
<dt class="sig sig-object py" id="RNS.Link.KEEPALIVE">
|
||||||
<span class="sig-name descname"><span class="pre">KEEPALIVE</span></span><em class="property"> <span class="pre">=</span> <span class="pre">180</span></em><a class="headerlink" href="#RNS.Link.KEEPALIVE" title="Permalink to this definition">¶</a></dt>
|
<span class="sig-name descname"><span class="pre">KEEPALIVE</span></span><em class="property"> <span class="pre">=</span> <span class="pre">360</span></em><a class="headerlink" href="#RNS.Link.KEEPALIVE" title="Permalink to this definition">¶</a></dt>
|
||||||
<dd><p>Interval for sending keep-alive packets on established links in seconds.</p>
|
<dd><p>Interval for sending keep-alive packets on established links in seconds.</p>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
@@ -770,8 +809,8 @@ be used if a new link to the same destination is established.</p>
|
|||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="py method">
|
<dl class="py method">
|
||||||
<dt class="sig sig-object py" id="RNS.Link.packet_callback">
|
<dt class="sig sig-object py" id="RNS.Link.set_packet_callback">
|
||||||
<span class="sig-name descname"><span class="pre">packet_callback</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">callback</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Link.packet_callback" title="Permalink to this definition">¶</a></dt>
|
<span class="sig-name descname"><span class="pre">set_packet_callback</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">callback</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Link.set_packet_callback" title="Permalink to this definition">¶</a></dt>
|
||||||
<dd><p>Registers a function to be called when a packet has been
|
<dd><p>Registers a function to be called when a packet has been
|
||||||
received over this link.</p>
|
received over this link.</p>
|
||||||
<dl class="field-list simple">
|
<dl class="field-list simple">
|
||||||
@@ -782,8 +821,8 @@ received over this link.</p>
|
|||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="py method">
|
<dl class="py method">
|
||||||
<dt class="sig sig-object py" id="RNS.Link.resource_callback">
|
<dt class="sig sig-object py" id="RNS.Link.set_resource_callback">
|
||||||
<span class="sig-name descname"><span class="pre">resource_callback</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">callback</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Link.resource_callback" title="Permalink to this definition">¶</a></dt>
|
<span class="sig-name descname"><span class="pre">set_resource_callback</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">callback</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Link.set_resource_callback" title="Permalink to this definition">¶</a></dt>
|
||||||
<dd><p>Registers a function to be called when a resource has been
|
<dd><p>Registers a function to be called when a resource has been
|
||||||
advertised over this link. If the function returns <em>True</em>
|
advertised over this link. If the function returns <em>True</em>
|
||||||
the resource will be accepted. If it returns <em>False</em> it will
|
the resource will be accepted. If it returns <em>False</em> it will
|
||||||
@@ -796,8 +835,8 @@ be ignored.</p>
|
|||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="py method">
|
<dl class="py method">
|
||||||
<dt class="sig sig-object py" id="RNS.Link.resource_started_callback">
|
<dt class="sig sig-object py" id="RNS.Link.set_resource_started_callback">
|
||||||
<span class="sig-name descname"><span class="pre">resource_started_callback</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">callback</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Link.resource_started_callback" title="Permalink to this definition">¶</a></dt>
|
<span class="sig-name descname"><span class="pre">set_resource_started_callback</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">callback</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Link.set_resource_started_callback" title="Permalink to this definition">¶</a></dt>
|
||||||
<dd><p>Registers a function to be called when a resource has begun
|
<dd><p>Registers a function to be called when a resource has begun
|
||||||
transferring over this link.</p>
|
transferring over this link.</p>
|
||||||
<dl class="field-list simple">
|
<dl class="field-list simple">
|
||||||
@@ -808,8 +847,8 @@ transferring over this link.</p>
|
|||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="py method">
|
<dl class="py method">
|
||||||
<dt class="sig sig-object py" id="RNS.Link.resource_concluded_callback">
|
<dt class="sig sig-object py" id="RNS.Link.set_resource_concluded_callback">
|
||||||
<span class="sig-name descname"><span class="pre">resource_concluded_callback</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">callback</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Link.resource_concluded_callback" title="Permalink to this definition">¶</a></dt>
|
<span class="sig-name descname"><span class="pre">set_resource_concluded_callback</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">callback</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Link.set_resource_concluded_callback" title="Permalink to this definition">¶</a></dt>
|
||||||
<dd><p>Registers a function to be called when a resource has concluded
|
<dd><p>Registers a function to be called when a resource has concluded
|
||||||
transferring over this link.</p>
|
transferring over this link.</p>
|
||||||
<dl class="field-list simple">
|
<dl class="field-list simple">
|
||||||
@@ -852,7 +891,7 @@ client application and throw an error message to the user.</p>
|
|||||||
<span id="api-resource"></span><h3>Resource<a class="headerlink" href="#resource" title="Permalink to this headline">¶</a></h3>
|
<span id="api-resource"></span><h3>Resource<a class="headerlink" href="#resource" title="Permalink to this headline">¶</a></h3>
|
||||||
<dl class="py class">
|
<dl class="py class">
|
||||||
<dt class="sig sig-object py" id="RNS.Resource">
|
<dt class="sig sig-object py" id="RNS.Resource">
|
||||||
<em class="property"><span class="pre">class</span> </em><span class="sig-prename descclassname"><span class="pre">RNS.</span></span><span class="sig-name descname"><span class="pre">Resource</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">data</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">link</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">advertise</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">auto_compress</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">must_compress</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">callback</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">progress_callback</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">segment_index</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">1</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">original_hash</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Resource" title="Permalink to this definition">¶</a></dt>
|
<em class="property"><span class="pre">class</span> </em><span class="sig-prename descclassname"><span class="pre">RNS.</span></span><span class="sig-name descname"><span class="pre">Resource</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">data</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">link</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">advertise</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">auto_compress</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">callback</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">progress_callback</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">segment_index</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">1</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">original_hash</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Resource" title="Permalink to this definition">¶</a></dt>
|
||||||
<dd><p>The Resource class allows transferring arbitrary amounts
|
<dd><p>The Resource class allows transferring arbitrary amounts
|
||||||
of data over a link. It will automatically handle sequencing,
|
of data over a link. It will automatically handle sequencing,
|
||||||
compression, coordination and checksumming.</p>
|
compression, coordination and checksumming.</p>
|
||||||
@@ -863,7 +902,6 @@ compression, coordination and checksumming.</p>
|
|||||||
<li><p><strong>link</strong> – The <a class="reference internal" href="#api-link"><span class="std std-ref">RNS.Link</span></a> instance on which to transfer the data.</p></li>
|
<li><p><strong>link</strong> – The <a class="reference internal" href="#api-link"><span class="std std-ref">RNS.Link</span></a> instance on which to transfer the data.</p></li>
|
||||||
<li><p><strong>advertise</strong> – Whether to automatically advertise the resource. Can be <em>True</em> or <em>False</em>.</p></li>
|
<li><p><strong>advertise</strong> – Whether to automatically advertise the resource. Can be <em>True</em> or <em>False</em>.</p></li>
|
||||||
<li><p><strong>auto_compress</strong> – Whether to auto-compress the resource. Can be <em>True</em> or <em>False</em>.</p></li>
|
<li><p><strong>auto_compress</strong> – Whether to auto-compress the resource. Can be <em>True</em> or <em>False</em>.</p></li>
|
||||||
<li><p><strong>auto_compress</strong> – Whether the resource must be compressed. Can be <em>True</em> or <em>False</em>. Used for debugging, will disappear in the future.</p></li>
|
|
||||||
<li><p><strong>callback</strong> – A <em>callable</em> with the signature <em>callback(resource)</em>. Will be called when the resource transfer concludes.</p></li>
|
<li><p><strong>callback</strong> – A <em>callable</em> with the signature <em>callback(resource)</em>. Will be called when the resource transfer concludes.</p></li>
|
||||||
<li><p><strong>progress_callback</strong> – A <em>callable</em> with the signature <em>callback(resource)</em>. Will be called whenever the resource transfer progress is updated.</p></li>
|
<li><p><strong>progress_callback</strong> – A <em>callable</em> with the signature <em>callback(resource)</em>. Will be called whenever the resource transfer progress is updated.</p></li>
|
||||||
<li><p><strong>segment_index</strong> – Internal use, ignore.</p></li>
|
<li><p><strong>segment_index</strong> – Internal use, ignore.</p></li>
|
||||||
@@ -982,11 +1020,11 @@ will announce it.</p>
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h4>Previous topic</h4>
|
<h4>Previous topic</h4>
|
||||||
<p class="topless"><a href="examples.html"
|
|
||||||
title="previous chapter">Examples</a></p>
|
|
||||||
<h4>Next topic</h4>
|
|
||||||
<p class="topless"><a href="understanding.html"
|
<p class="topless"><a href="understanding.html"
|
||||||
title="next chapter">Understanding Reticulum</a></p>
|
title="previous chapter">Understanding Reticulum</a></p>
|
||||||
|
<h4>Next topic</h4>
|
||||||
|
<p class="topless"><a href="examples.html"
|
||||||
|
title="next chapter">Examples</a></p>
|
||||||
<div role="note" aria-label="source link">
|
<div role="note" aria-label="source link">
|
||||||
<h3>This Page</h3>
|
<h3>This Page</h3>
|
||||||
<ul class="this-page-menu">
|
<ul class="this-page-menu">
|
||||||
@@ -1015,12 +1053,12 @@ will announce it.</p>
|
|||||||
<a href="genindex.html" title="General Index"
|
<a href="genindex.html" title="General Index"
|
||||||
>index</a></li>
|
>index</a></li>
|
||||||
<li class="right" >
|
<li class="right" >
|
||||||
<a href="understanding.html" title="Understanding Reticulum"
|
<a href="examples.html" title="Examples"
|
||||||
>next</a> |</li>
|
>next</a> |</li>
|
||||||
<li class="right" >
|
<li class="right" >
|
||||||
<a href="examples.html" title="Examples"
|
<a href="understanding.html" title="Understanding Reticulum"
|
||||||
>previous</a> |</li>
|
>previous</a> |</li>
|
||||||
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li>
|
||||||
<li class="nav-item nav-item-this"><a href="">API Reference</a></li>
|
<li class="nav-item nav-item-this"><a href="">API Reference</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Search — Reticulum Network Stack 0.2.0 beta documentation</title>
|
<title>Search — Reticulum Network Stack 0.2.1 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/classic.css" />
|
<link rel="stylesheet" type="text/css" href="_static/classic.css" />
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
<li class="right" style="margin-right: 10px">
|
<li class="right" style="margin-right: 10px">
|
||||||
<a href="genindex.html" title="General Index"
|
<a href="genindex.html" title="General Index"
|
||||||
accesskey="I">index</a></li>
|
accesskey="I">index</a></li>
|
||||||
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li>
|
||||||
<li class="nav-item nav-item-this"><a href="">Search</a></li>
|
<li class="nav-item nav-item-this"><a href="">Search</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -85,7 +85,7 @@
|
|||||||
<li class="right" style="margin-right: 10px">
|
<li class="right" style="margin-right: 10px">
|
||||||
<a href="genindex.html" title="General Index"
|
<a href="genindex.html" title="General Index"
|
||||||
>index</a></li>
|
>index</a></li>
|
||||||
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li>
|
||||||
<li class="nav-item nav-item-this"><a href="">Search</a></li>
|
<li class="nav-item nav-item-this"><a href="">Search</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
+168
-107
@@ -5,7 +5,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Understanding Reticulum — Reticulum Network Stack 0.2.0 beta documentation</title>
|
<title>Understanding Reticulum — Reticulum Network Stack 0.2.1 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/classic.css" />
|
<link rel="stylesheet" type="text/css" href="_static/classic.css" />
|
||||||
|
|
||||||
@@ -16,7 +16,8 @@
|
|||||||
|
|
||||||
<link rel="index" title="Index" href="genindex.html" />
|
<link rel="index" title="Index" href="genindex.html" />
|
||||||
<link rel="search" title="Search" href="search.html" />
|
<link rel="search" title="Search" href="search.html" />
|
||||||
<link rel="prev" title="API Reference" href="reference.html" />
|
<link rel="next" title="API Reference" href="reference.html" />
|
||||||
|
<link rel="prev" title="Getting Started Fast" href="gettingstartedfast.html" />
|
||||||
</head><body>
|
</head><body>
|
||||||
<div class="related" role="navigation" aria-label="related navigation">
|
<div class="related" role="navigation" aria-label="related navigation">
|
||||||
<h3>Navigation</h3>
|
<h3>Navigation</h3>
|
||||||
@@ -26,8 +27,11 @@
|
|||||||
accesskey="I">index</a></li>
|
accesskey="I">index</a></li>
|
||||||
<li class="right" >
|
<li class="right" >
|
||||||
<a href="reference.html" title="API Reference"
|
<a href="reference.html" title="API Reference"
|
||||||
|
accesskey="N">next</a> |</li>
|
||||||
|
<li class="right" >
|
||||||
|
<a href="gettingstartedfast.html" title="Getting Started Fast"
|
||||||
accesskey="P">previous</a> |</li>
|
accesskey="P">previous</a> |</li>
|
||||||
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li>
|
||||||
<li class="nav-item nav-item-this"><a href="">Understanding Reticulum</a></li>
|
<li class="nav-item nav-item-this"><a href="">Understanding Reticulum</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -204,9 +208,11 @@ when a node is directly reachable.</p>
|
|||||||
<p>Destinations are created and named in an easy to understand dotted notation of <em>aspects</em>, and
|
<p>Destinations are created and named in an easy to understand dotted notation of <em>aspects</em>, and
|
||||||
represented on the network as a hash of this value. The hash is a SHA-256 truncated to 80 bits. The
|
represented on the network as a hash of this value. The hash is a SHA-256 truncated to 80 bits. The
|
||||||
top level aspect should always be a unique identifier for the application using the destination.
|
top level aspect should always be a unique identifier for the application using the destination.
|
||||||
The next levels of aspects can be defined in any way by the creator of the application. For example,
|
The next levels of aspects can be defined in any way by the creator of the application.</p>
|
||||||
a destination for a environmental monitoring application could be made up of the application name, a
|
<p>Aspects can be as long and as plentiful as required, and a resulting long destination name will not
|
||||||
device type and measurement type, like this:</p>
|
impact efficiency, as names are always represented as truncated SHA-256 hashes on the network.</p>
|
||||||
|
<p>As an example, a destination for a environmental monitoring application could be made up of the
|
||||||
|
application name, a device type and measurement type, like this:</p>
|
||||||
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>app name : environmentlogger
|
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>app name : environmentlogger
|
||||||
aspects : remotesensor, temperature
|
aspects : remotesensor, temperature
|
||||||
|
|
||||||
@@ -242,9 +248,8 @@ receives.</p>
|
|||||||
</dl>
|
</dl>
|
||||||
</li>
|
</li>
|
||||||
<li><dl class="simple">
|
<li><dl class="simple">
|
||||||
<dt><strong>Group</strong></dt><dd><p>When private communication between two or more endpoints is needed. More efficient in
|
<dt><strong>Group</strong></dt><dd><p>When private communication between two or more endpoints is needed. Supports multiple hops
|
||||||
data usage than <em>single</em> destinations. Supports multiple hops indirectly, but must first be
|
indirectly, but must first be established through a <em>single</em> destination.</p>
|
||||||
established through a <em>single</em> destination.</p>
|
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</li>
|
</li>
|
||||||
@@ -260,9 +265,9 @@ nodes aware of your destinations public key, called the <em>announce</em>. It is
|
|||||||
an unknown public key from the network, as all participating nodes serve as a distributed ledger
|
an unknown public key from the network, as all participating nodes serve as a distributed ledger
|
||||||
of public keys.</p>
|
of public keys.</p>
|
||||||
<p>Note that public key information can be shared and verified in many other ways than using the
|
<p>Note that public key information can be shared and verified in many other ways than using the
|
||||||
built-in methodology, and that it is therefore not required to use the announce/request functionality.
|
built-in <em>announce</em> functionality, and that it is therefore not required to use the announce/request
|
||||||
It is by far the easiest though, and should definitely be used if there is not a good reason for
|
functionality to obtain public keys. It is by far the easiest though, and should definitely be used
|
||||||
doing it differently.</p>
|
if there is not a good reason for doing it differently.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="public-key-announcements">
|
<div class="section" id="public-key-announcements">
|
||||||
@@ -278,7 +283,7 @@ contain the following information:</p>
|
|||||||
<li><p>The announcers public key</p></li>
|
<li><p>The announcers public key</p></li>
|
||||||
<li><p>Application specific data, in this case the users nickname and availability status</p></li>
|
<li><p>Application specific data, in this case the users nickname and availability status</p></li>
|
||||||
<li><p>A random blob, making each new announce unique</p></li>
|
<li><p>A random blob, making each new announce unique</p></li>
|
||||||
<li><p>A signature of the above information, verifying authenticity</p></li>
|
<li><p>An Ed25519 signature of the above information, verifying authenticity</p></li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>With this information, any Reticulum node that receives it will be able to reconstruct an outgoing
|
<p>With this information, any Reticulum node that receives it will be able to reconstruct an outgoing
|
||||||
destination to securely communicate with that destination. You might have noticed that there is one
|
destination to securely communicate with that destination. You might have noticed that there is one
|
||||||
@@ -286,8 +291,9 @@ piece of information lacking to reconstruct full knowledge of the announced dest
|
|||||||
the aspect names of the destination. These are intentionally left out to save bandwidth, since they
|
the aspect names of the destination. These are intentionally left out to save bandwidth, since they
|
||||||
will be implicit in almost all cases. If a destination name is not entirely implicit, information can be
|
will be implicit in almost all cases. If a destination name is not entirely implicit, information can be
|
||||||
included in the application specific data part that will allow the receiver to infer the naming.</p>
|
included in the application specific data part that will allow the receiver to infer the naming.</p>
|
||||||
<p>It is important to note that announcements will be forwarded throughout the network according to a
|
<p>It is important to note that announces will be forwarded throughout the network according to a
|
||||||
certain pattern. This will be detailed later.</p>
|
certain pattern. This will be detailed in the section
|
||||||
|
<a class="reference internal" href="#understanding-announce"><span class="std std-ref">The Announce Mechanism in Detail</span></a>.</p>
|
||||||
<p>Seeing how <em>single</em> destinations are always tied to a private/public key pair leads us to the next topic.</p>
|
<p>Seeing how <em>single</em> destinations are always tied to a private/public key pair leads us to the next topic.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="understanding-identities">
|
<div class="section" id="understanding-identities">
|
||||||
@@ -304,16 +310,16 @@ automatically. This may be desirable in some situations, but often you will prob
|
|||||||
the identity first, and then link it to created destinations.</p>
|
the identity first, and then link it to created destinations.</p>
|
||||||
<p>Building upon the simple messenger example, we could use an identity to represent the user of the
|
<p>Building upon the simple messenger example, we could use an identity to represent the user of the
|
||||||
application. Destinations created will then be linked to this identity to allow communication to
|
application. Destinations created will then be linked to this identity to allow communication to
|
||||||
reach the user. In such a case it is of great importance to store the user’s identity securely and
|
reach the user. In all cases it is of great importance to store the private keys associated with any
|
||||||
privately.</p>
|
Reticulum Identity securely and privately.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="getting-further">
|
<div class="section" id="getting-further">
|
||||||
<span id="understanding-gettingfurther"></span><h3>Getting Further<a class="headerlink" href="#getting-further" title="Permalink to this headline">¶</a></h3>
|
<span id="understanding-gettingfurther"></span><h3>Getting Further<a class="headerlink" href="#getting-further" title="Permalink to this headline">¶</a></h3>
|
||||||
<p>The above functions and principles form the core of Reticulum, and would suffice to create
|
<p>The above functions and principles form the core of Reticulum, and would suffice to create
|
||||||
functional networked applications in local clusters, for example over radio links where all interested
|
functional networked applications in local clusters, for example over radio links where all interested
|
||||||
nodes can directly hear each other. But to be truly useful, we need a way to direct traffic over multiple
|
nodes can directly hear each other. But to be truly useful, we need a way to direct traffic over multiple
|
||||||
hops in the network. In the next sections, two concepts that allow this will be introduced, <em>paths</em> and
|
hops in the network.</p>
|
||||||
<em>links</em>.</p>
|
<p>In the following sections, two concepts that allow this will be introduced, <em>paths</em> and <em>links</em>.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="reticulum-transport">
|
<div class="section" id="reticulum-transport">
|
||||||
@@ -327,69 +333,20 @@ very limited. Existing routing protocols like BGP or OSPF carry too much overhea
|
|||||||
useable over bandwidth-limited, high-latency links.</p>
|
useable over bandwidth-limited, high-latency links.</p>
|
||||||
<p>To overcome such challenges, Reticulum’s <em>Transport</em> system uses public-key cryptography to
|
<p>To overcome such challenges, Reticulum’s <em>Transport</em> system uses public-key cryptography to
|
||||||
implement the concept of <em>paths</em> that allow discovery of how to get information to a certain
|
implement the concept of <em>paths</em> that allow discovery of how to get information to a certain
|
||||||
destination, and <em>resources</em> that help make reliable data transfer more efficient.</p>
|
destination. It is important to note that no single node in a Reticulum network knows the complete
|
||||||
<div class="section" id="reaching-the-destination">
|
path to a destination. Every Transport node participating in a Reticulum network will only
|
||||||
<span id="understanding-paths"></span><h3>Reaching the Destination<a class="headerlink" href="#reaching-the-destination" title="Permalink to this headline">¶</a></h3>
|
know what the most direct way to get a packet one hop closer to it’s destination is.</p>
|
||||||
<p>In networks with changing topology and trustless connectivity, nodes need a way to establish
|
<div class="section" id="the-announce-mechanism-in-detail">
|
||||||
<em>verified connectivity</em> with each other. Since the network is assumed to be trustless, Reticulum
|
<span id="understanding-announce"></span><h3>The Announce Mechanism in Detail<a class="headerlink" href="#the-announce-mechanism-in-detail" title="Permalink to this headline">¶</a></h3>
|
||||||
must provide a way to guarantee that the peer you are communicating with is actually who you
|
<p>When an <em>announce</em> is transmitted by a node, it will be forwarded by any node receiving it, but
|
||||||
expect. To do this, the following process is employed:</p>
|
according to some specific rules:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><div class="line-block">
|
<li><div class="line-block">
|
||||||
<div class="line">First, the node that wishes to establish connectivity will send out a special packet, that
|
<div class="line">If this exact announce has already been received before, ignore it.</div>
|
||||||
traverses the network and locates the desired destination. Along the way, the nodes that
|
|
||||||
forward the packet will take note of this <em>link request</em>.</div>
|
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li><div class="line-block">
|
<li><div class="line-block">
|
||||||
<div class="line">Second, if the destination accepts the <em>link request</em> , it will send back a packet that proves the
|
<div class="line">If not, record into a table which node the announce was received from, and how many times in
|
||||||
authenticity of it’s identity (and the receipt of the link request) to the initiating node. All
|
|
||||||
nodes that initially forwarded the packet will also be able to verify this proof, and thus
|
|
||||||
accept the validity of the <em>link</em> throughout the network.</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li><div class="line-block">
|
|
||||||
<div class="line">When the validity of the <em>link</em> has been accepted by forwarding nodes, these nodes will
|
|
||||||
remember the <em>link</em> , and it can subsequently be used by referring to a hash representing it.</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li><div class="line-block">
|
|
||||||
<div class="line">As a part of the <em>link request</em> , a Diffie-Hellman key exchange takes place, that sets up an
|
|
||||||
efficient symmetrically encrypted tunnel between the two nodes, using elliptic curve
|
|
||||||
cryptography. As such, this mode of communication is preferred, even for situations when
|
|
||||||
nodes can directly communicate, when the amount of data to be exchanged numbers in the
|
|
||||||
tens of packets.</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li><div class="line-block">
|
|
||||||
<div class="line">When a <em>link</em> has been set up, it automatically provides message receipt functionality, so the
|
|
||||||
sending node can obtain verified confirmation that the information reached the intended
|
|
||||||
recipient.</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<p>In a moment, we will discuss the specifics of how this methodology is implemented, but let’s first
|
|
||||||
recap what purposes this serves. We first ensure that the node answering our request is actually the
|
|
||||||
one we want to communicate with, and not a malicious actor pretending to be so. At the same time
|
|
||||||
we establish an efficient encrypted channel. The setup of this is relatively cheap in terms of
|
|
||||||
bandwidth, so it can be used just for a short exchange, and then recreated as needed, which will also
|
|
||||||
rotate encryption keys, but the link can also be kept alive for longer periods of time, if this is
|
|
||||||
more suitable to the application. The amount of bandwidth used on keeping a link open is practically
|
|
||||||
negligible. The procedure also inserts the <em>link id</em> , a hash calculated from the link request packet,
|
|
||||||
into the memory of forwarding nodes, which means that the communicating nodes can thereafter reach each
|
|
||||||
other simply by referring to this <em>link id</em>.</p>
|
|
||||||
<div class="section" id="step-1-pathfinding">
|
|
||||||
<h4>Step 1: Pathfinding<a class="headerlink" href="#step-1-pathfinding" title="Permalink to this headline">¶</a></h4>
|
|
||||||
<p>The pathfinding method builds on the <em>announce</em> functionality discussed earlier. When an announce
|
|
||||||
is sent out by a node, it will be forwarded by any node receiving it, but according to some specific
|
|
||||||
rules:</p>
|
|
||||||
<ul>
|
|
||||||
<li><div class="line-block">
|
|
||||||
<div class="line">If this announce has already been received before, ignore it.</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li><div class="line-block">
|
|
||||||
<div class="line">Record into a table which node the announce was received from, and how many times in
|
|
||||||
total it has been retransmitted to get here.</div>
|
total it has been retransmitted to get here.</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
@@ -399,8 +356,7 @@ set to 18.</div>
|
|||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li><div class="line-block">
|
<li><div class="line-block">
|
||||||
<div class="line">The announce will be assigned a delay <em>d</em> = c<sup>h</sup> seconds, where <em>c</em> is a decay constant, by
|
<div class="line">The announce will be assigned a delay <em>d</em> = c<sup>h</sup> seconds, where <em>c</em> is a decay constant, and <em>h</em> is the amount of times this packet has already been forwarded.</div>
|
||||||
default 2, and <em>h</em> is the amount of times this packet has already been forwarded.</div>
|
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li><div class="line-block">
|
<li><div class="line-block">
|
||||||
@@ -415,10 +371,11 @@ not utilized by other traffic, the announce will be forwarded.</div>
|
|||||||
</li>
|
</li>
|
||||||
<li><div class="line-block">
|
<li><div class="line-block">
|
||||||
<div class="line">If no other nodes are heard retransmitting the announce with a greater hop count than when
|
<div class="line">If no other nodes are heard retransmitting the announce with a greater hop count than when
|
||||||
it left this node, transmitting it will be retried <em>r</em> times. By default, <em>r</em> is set to 2. Retries follow
|
it left this node, transmitting it will be retried <em>r</em> times. By default, <em>r</em> is set to 1. Retries
|
||||||
same rules as above, with the exception that it must wait for at least <em>d</em> = c<sup>h+1</sup> + t seconds, ie.,
|
follow same rules as above, with the exception that it must wait for at least <em>d</em> = c<sup>h+1</sup> +
|
||||||
the amount of time it would take the next node to retransmit the packet. By default, <em>t</em> is set to
|
t + rand(0, rw) seconds. This amount of time is equal to the amount of time it would take the next
|
||||||
10.</div>
|
node to retransmit the packet, plus a random window. By default, <em>t</em> is set to 10 seconds, and the
|
||||||
|
random window <em>rw</em> is set to 10 seconds.</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li><div class="line-block">
|
<li><div class="line-block">
|
||||||
@@ -440,13 +397,111 @@ distance of <em>Lavg =</em> 15 kilometers, an announce will be able to propagate
|
|||||||
kilometers in 34 minutes, and a <em>maximum announce radius</em> of 270 kilometers in approximately 3
|
kilometers in 34 minutes, and a <em>maximum announce radius</em> of 270 kilometers in approximately 3
|
||||||
days.</p>
|
days.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="step-2-link-establishment">
|
<div class="section" id="reaching-the-destination">
|
||||||
<h4>Step 2: Link Establishment<a class="headerlink" href="#step-2-link-establishment" title="Permalink to this headline">¶</a></h4>
|
<span id="understanding-paths"></span><h3>Reaching the Destination<a class="headerlink" href="#reaching-the-destination" title="Permalink to this headline">¶</a></h3>
|
||||||
<p>After seeing how the conditions for finding a path through the network are created, we will now
|
<p>In networks with changing topology and trustless connectivity, nodes need a way to establish
|
||||||
explore how two nodes can establish reliable communications over multiple hops. The <em>link</em> in
|
<em>verified connectivity</em> with each other. Since the network is assumed to be trustless, Reticulum
|
||||||
Reticulum terminology should not be viewed as a direct node-to-node link on the physical layer, but
|
must provide a way to guarantee that the peer you are communicating with is actually who you
|
||||||
as an abstract channel, that can be open for any amount of time, and can span an arbitrary number
|
expect. Reticulum offers two ways to do this.</p>
|
||||||
of hops, where information will be exchanged between two nodes.</p>
|
<p>For exchanges of small amounts of information, Reticulum offers the <em>Packet</em> API, which works exactly like you would expect - on a per packet level. The following process is employed when sending a packet:</p>
|
||||||
|
<ul>
|
||||||
|
<li><div class="line-block">
|
||||||
|
<div class="line">A packet is always created with an associated destination and some payload data. When the packet is sent
|
||||||
|
to a <em>single</em> destination type, Reticulum will automatically create an ephemeral encryption key, perform
|
||||||
|
an ECDH key exchange with the destinations public key, and encrypt the information.</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li><div class="line-block">
|
||||||
|
<div class="line">It is important to note that this key exchange does not require any network traffic. The sender already
|
||||||
|
knows the public key of the destination from an earlier received <em>announce</em>, and can thus perform the ECDH
|
||||||
|
key exchange locally, before sending the packet.</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li><div class="line-block">
|
||||||
|
<div class="line">The public part of the newly generated ephemeral key-pair is included with the encrypted token, and sent
|
||||||
|
along with the encrypted payload data in the packet.</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li><div class="line-block">
|
||||||
|
<div class="line">When the destination receives the packet, it can itself perform an ECDH key exchange and decrypt the
|
||||||
|
packet.</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li><div class="line-block">
|
||||||
|
<div class="line">A new ephemeral key is used for every packet sent in this way, and forward secrecy is guaranteed on a
|
||||||
|
per packet level.</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li><div class="line-block">
|
||||||
|
<div class="line">Once the packet has been received and decrypted by the addressed destination, that destination can opt
|
||||||
|
to <em>prove</em> its receipt of the packet. It does this by calculating the SHA-256 hash of the received packet,
|
||||||
|
and signing this hash with it’s Ed25519 signing key. Transport nodes in the network can then direct this
|
||||||
|
<em>proof</em> back to the packets origin, where the signature can be verified against the destinations known
|
||||||
|
public signing key.</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li><div class="line-block">
|
||||||
|
<div class="line">In case the packet is addressed to a <em>group</em> destination type, the packet will be encrypted with the
|
||||||
|
pre-shared AES-128 key associated with the destination. In case the packet is addressed to a <em>plain</em>
|
||||||
|
destination type, the payload data will not be encrypted. Neither of these two destination types offer
|
||||||
|
forward secrecy. In general, it is recommended to always use the <em>single</em> destination type, unless it is
|
||||||
|
strictly necessary to use one of the others.</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>For exchanges of larger amounts of data, or when longer sessions of bidirectional communication is desired, Reticulum offers the <em>Link</em> API. To establish a <em>link</em>, the following process is employed:</p>
|
||||||
|
<ul>
|
||||||
|
<li><div class="line-block">
|
||||||
|
<div class="line">First, the node that wishes to establish a link will send out a special packet, that
|
||||||
|
traverses the network and locates the desired destination. Along the way, the nodes that
|
||||||
|
forward the packet will take note of this <em>link request</em>.</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li><div class="line-block">
|
||||||
|
<div class="line">Second, if the destination accepts the <em>link request</em> , it will send back a packet that proves the
|
||||||
|
authenticity of it’s identity (and the receipt of the link request) to the initiating node. All
|
||||||
|
nodes that initially forwarded the packet will also be able to verify this proof, and thus
|
||||||
|
accept the validity of the <em>link</em> throughout the network.</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li><div class="line-block">
|
||||||
|
<div class="line">When the validity of the <em>link</em> has been accepted by forwarding nodes, these nodes will
|
||||||
|
remember the <em>link</em> , and it can subsequently be used by referring to a hash representing it.</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li><div class="line-block">
|
||||||
|
<div class="line">As a part of the <em>link request</em> , a Diffie-Hellman key exchange takes place, that sets up an
|
||||||
|
efficiently encrypted tunnel between the two nodes, using elliptic curve cryptography. As such,
|
||||||
|
this mode of communication is preferred, even for situations when nodes can directly communicate,
|
||||||
|
when the amount of data to be exchanged numbers in the tens of packets.</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li><div class="line-block">
|
||||||
|
<div class="line">When a <em>link</em> has been set up, it automatically provides message receipt functionality, through
|
||||||
|
the same <em>proof</em> mechanism discussed before, so the sending node can obtain verified confirmation
|
||||||
|
that the information reached the intended recipient.</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>In a moment, we will discuss the details of how this methodology is implemented, but let’s first
|
||||||
|
recap what purposes this methodology serves. We first ensure that the node answering our request
|
||||||
|
is actually the one we want to communicate with, and not a malicious actor pretending to be so.
|
||||||
|
At the same time we establish an efficient encrypted channel. The setup of this is relatively cheap in
|
||||||
|
terms of bandwidth, so it can be used just for a short exchange, and then recreated as needed, which will
|
||||||
|
also rotate encryption keys. The link can also be kept alive for longer periods of time, if this is
|
||||||
|
more suitable to the application. The procedure also inserts the <em>link id</em> , a hash calculated from the link request packet, into the memory of forwarding nodes, which means that the communicating nodes can thereafter reach each other simply by referring to this <em>link id</em>.</p>
|
||||||
|
<p>The combined bandwidth cost of setting up a link is 3 packets totalling 240 bytes (more info in the
|
||||||
|
<a class="reference internal" href="#understanding-packetformat"><span class="std std-ref">Binary Packet Format</span></a> section). The amount of bandwidth used on keeping
|
||||||
|
a link open is practically negligible, at 0.62 bits per second. Even on a slow 1200 bits per second packet
|
||||||
|
radio channel, 100 concurrent links will still leave 95% channel capacity for actual data.</p>
|
||||||
|
<div class="section" id="link-establishment-in-detail">
|
||||||
|
<h4>Link Establishment in Detail<a class="headerlink" href="#link-establishment-in-detail" title="Permalink to this headline">¶</a></h4>
|
||||||
|
<p>After exploring the basics of the announce mechanism, finding a path through the network, and an overview
|
||||||
|
of the link establishment procedure, this section will go into greater detail about the Reticulum link
|
||||||
|
establishment process.</p>
|
||||||
|
<p>The <em>link</em> in Reticulum terminology should not be viewed as a direct node-to-node link on the
|
||||||
|
physical layer, but as an abstract channel, that can be open for any amount of time, and can span
|
||||||
|
an arbitrary number of hops, where information will be exchanged between two nodes.</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><div class="line-block">
|
<li><div class="line-block">
|
||||||
<div class="line">When a node in the network wants to establish verified connectivity with another node, it
|
<div class="line">When a node in the network wants to establish verified connectivity with another node, it
|
||||||
@@ -461,8 +516,7 @@ considered as single public key for simplicity in this explanation.</em></div>
|
|||||||
</li>
|
</li>
|
||||||
<li><div class="line-block">
|
<li><div class="line-block">
|
||||||
<div class="line">The <em>link request</em> is addressed to the destination hash of the desired destination, and
|
<div class="line">The <em>link request</em> is addressed to the destination hash of the desired destination, and
|
||||||
contains the following data: The newly generated X25519 public key <em>LKi</em>. The contents
|
contains the following data: The newly generated X25519 public key <em>LKi</em>.</div>
|
||||||
are encrypted with the RSA public key of the destination and tramsitted over the network.</div>
|
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li><div class="line-block">
|
<li><div class="line-block">
|
||||||
@@ -473,21 +527,22 @@ previously.</div>
|
|||||||
<li><div class="line-block">
|
<li><div class="line-block">
|
||||||
<div class="line">Any node that forwards the link request will store a <em>link id</em> in it’s <em>link table</em> , along with the
|
<div class="line">Any node that forwards the link request will store a <em>link id</em> in it’s <em>link table</em> , along with the
|
||||||
amount of hops the packet had taken when received. The link id is a hash of the entire link
|
amount of hops the packet had taken when received. The link id is a hash of the entire link
|
||||||
request packet. If the path is not <em>proven</em> within some set amount of time, the entry will be
|
request packet. If the link request packet is not <em>proven</em> by the addressed destination within some
|
||||||
dropped from the <em>link table</em> again.</div>
|
set amount of time, the entry will be dropped from the <em>link table</em> again.</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li><div class="line-block">
|
<li><div class="line-block">
|
||||||
<div class="line">When the destination receives the link request packet, it will decrypt it and decide whether to
|
<div class="line">When the destination receives the link request packet, it will decide whether to accept the request.
|
||||||
accept the request. If it is accepted, the destination will also generate a new X25519 private/public
|
If it is accepted, the destination will also generate a new X25519 private/public key pair, and
|
||||||
key pair, and perform a Diffie Hellman Key Exchange, deriving a new symmetric key that will be used
|
perform a Diffie Hellman Key Exchange, deriving a new symmetric key that will be used to encrypt the
|
||||||
to encrypt the channel, once it has been established.</div>
|
channel, once it has been established.</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li><div class="line-block">
|
<li><div class="line-block">
|
||||||
<div class="line">A <em>link proof</em> packet is now constructed and transmitted over the network. This packet is
|
<div class="line">A <em>link proof</em> packet is now constructed and transmitted over the network. This packet is
|
||||||
addressed to the <em>link id</em> of the <em>link</em>. It contains the following data: The newly generated X25519
|
addressed to the <em>link id</em> of the <em>link</em>. It contains the following data: The newly generated X25519
|
||||||
public key <em>LKr</em> and an RSA-1024 signature of the <em>link id</em> and <em>LKr</em>.</div>
|
public key <em>LKr</em> and an Ed25519 signature of the <em>link id</em> and <em>LKr</em> made by the signing key of
|
||||||
|
the addressed destination.</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li><div class="line-block">
|
<li><div class="line-block">
|
||||||
@@ -615,7 +670,7 @@ the light of Reticulums goal of equal access, doing so would need to be the subj
|
|||||||
investigation of the consequences first.</p>
|
investigation of the consequences first.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="binary-packet-format">
|
<div class="section" id="binary-packet-format">
|
||||||
<h3>Binary Packet Format<a class="headerlink" href="#binary-packet-format" title="Permalink to this headline">¶</a></h3>
|
<span id="understanding-packetformat"></span><h3>Binary Packet Format<a class="headerlink" href="#binary-packet-format" title="Permalink to this headline">¶</a></h3>
|
||||||
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>== Reticulum Wire Format ======
|
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>== Reticulum Wire Format ======
|
||||||
|
|
||||||
A Reticulum packet is composed of the following fields:
|
A Reticulum packet is composed of the following fields:
|
||||||
@@ -706,9 +761,9 @@ proof 11
|
|||||||
wire size including all fields.
|
wire size including all fields.
|
||||||
|
|
||||||
- Path Request : 33 bytes
|
- Path Request : 33 bytes
|
||||||
- Announce : 323 bytes
|
- Announce : 151 bytes
|
||||||
- Link Request : 141 bytes
|
- Link Request : 77 bytes
|
||||||
- Link Proof : 205 bytes
|
- Link Proof : 77 bytes
|
||||||
- Link RTT packet : 86 bytes
|
- Link RTT packet : 86 bytes
|
||||||
- Link keepalive : 14 bytes
|
- Link keepalive : 14 bytes
|
||||||
</pre></div>
|
</pre></div>
|
||||||
@@ -740,9 +795,9 @@ proof 11
|
|||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a class="reference internal" href="#reticulum-transport">Reticulum Transport</a><ul>
|
<li><a class="reference internal" href="#reticulum-transport">Reticulum Transport</a><ul>
|
||||||
|
<li><a class="reference internal" href="#the-announce-mechanism-in-detail">The Announce Mechanism in Detail</a></li>
|
||||||
<li><a class="reference internal" href="#reaching-the-destination">Reaching the Destination</a><ul>
|
<li><a class="reference internal" href="#reaching-the-destination">Reaching the Destination</a><ul>
|
||||||
<li><a class="reference internal" href="#step-1-pathfinding">Step 1: Pathfinding</a></li>
|
<li><a class="reference internal" href="#link-establishment-in-detail">Link Establishment in Detail</a></li>
|
||||||
<li><a class="reference internal" href="#step-2-link-establishment">Step 2: Link Establishment</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a class="reference internal" href="#resources">Resources</a></li>
|
<li><a class="reference internal" href="#resources">Resources</a></li>
|
||||||
@@ -760,8 +815,11 @@ proof 11
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h4>Previous topic</h4>
|
<h4>Previous topic</h4>
|
||||||
|
<p class="topless"><a href="gettingstartedfast.html"
|
||||||
|
title="previous chapter">Getting Started Fast</a></p>
|
||||||
|
<h4>Next topic</h4>
|
||||||
<p class="topless"><a href="reference.html"
|
<p class="topless"><a href="reference.html"
|
||||||
title="previous chapter">API Reference</a></p>
|
title="next chapter">API Reference</a></p>
|
||||||
<div role="note" aria-label="source link">
|
<div role="note" aria-label="source link">
|
||||||
<h3>This Page</h3>
|
<h3>This Page</h3>
|
||||||
<ul class="this-page-menu">
|
<ul class="this-page-menu">
|
||||||
@@ -791,8 +849,11 @@ proof 11
|
|||||||
>index</a></li>
|
>index</a></li>
|
||||||
<li class="right" >
|
<li class="right" >
|
||||||
<a href="reference.html" title="API Reference"
|
<a href="reference.html" title="API Reference"
|
||||||
|
>next</a> |</li>
|
||||||
|
<li class="right" >
|
||||||
|
<a href="gettingstartedfast.html" title="Getting Started Fast"
|
||||||
>previous</a> |</li>
|
>previous</a> |</li>
|
||||||
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li>
|
||||||
<li class="nav-item nav-item-this"><a href="">Understanding Reticulum</a></li>
|
<li class="nav-item nav-item-this"><a href="">Understanding Reticulum</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+14
-7
@@ -5,7 +5,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>What is Reticulum? — Reticulum Network Stack 0.2.0 beta documentation</title>
|
<title>What is Reticulum? — Reticulum Network Stack 0.2.1 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/classic.css" />
|
<link rel="stylesheet" type="text/css" href="_static/classic.css" />
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
<li class="right" >
|
<li class="right" >
|
||||||
<a href="index.html" title="Reticulum Network Stack Manual"
|
<a href="index.html" title="Reticulum Network Stack Manual"
|
||||||
accesskey="P">previous</a> |</li>
|
accesskey="P">previous</a> |</li>
|
||||||
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li>
|
||||||
<li class="nav-item nav-item-this"><a href="">What is Reticulum?</a></li>
|
<li class="nav-item nav-item-this"><a href="">What is Reticulum?</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -59,13 +59,14 @@
|
|||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
<li><p>Coordination-less globally unique adressing and identification</p></li>
|
<li><p>Coordination-less globally unique adressing and identification</p></li>
|
||||||
<li><p>Fully self-configuring multi-hop routing</p></li>
|
<li><p>Fully self-configuring multi-hop routing</p></li>
|
||||||
<li><p>Asymmetric RSA encryption and signatures as basis for all communication</p></li>
|
<li><p>Asymmetric X25519 encryption and Ed25519 signatures as a basis for all communication</p></li>
|
||||||
<li><p>Perfect Forward Secrecy on links with ephemereal Elliptic Curve Diffie-Hellman keys (on Curve25519)</p></li>
|
<li><p>Forward Secrecy with ephemereal Elliptic Curve Diffie-Hellman keys on Curve25519</p></li>
|
||||||
<li><p>Reticulum uses the Fernet specification for encryption on links and to group destinations</p>
|
<li><p>Reticulum uses the <a class="reference external" href="https://github.com/fernet/spec/blob/master/Spec.md">Fernet</a> specification for encryption</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><p>AES-128 in CBC mode with PKCS7 padding</p></li>
|
<li><p>AES-128 in CBC mode with PKCS7 padding</p></li>
|
||||||
<li><p>HMAC using SHA256 for authentication</p></li>
|
<li><p>HMAC using SHA256 for authentication</p></li>
|
||||||
<li><p>IVs are generated through os.urandom()</p></li>
|
<li><p>IVs are generated through os.urandom()</p></li>
|
||||||
|
<li><p>Keys are ephemeral and derived from an ECDH key exchange on Curve25519</p></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><p>Unforgeable packet delivery confirmations</p></li>
|
<li><p>Unforgeable packet delivery confirmations</p></li>
|
||||||
@@ -78,11 +79,17 @@
|
|||||||
<li><p>The API is very easy to use, and provides transfer progress</p></li>
|
<li><p>The API is very easy to use, and provides transfer progress</p></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
<li><p>Efficient link establishment</p>
|
||||||
|
<ul>
|
||||||
|
<li><p>Total bandwidth cost of setting up a link is only 3 packets, totalling 240 bytes</p></li>
|
||||||
|
<li><p>Low cost of keeping links open at only 0.62 bits per second</p></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="where-can-reticulum-be-used">
|
<div class="section" id="where-can-reticulum-be-used">
|
||||||
<h2>Where can Reticulum be Used?<a class="headerlink" href="#where-can-reticulum-be-used" title="Permalink to this headline">¶</a></h2>
|
<h2>Where can Reticulum be Used?<a class="headerlink" href="#where-can-reticulum-be-used" title="Permalink to this headline">¶</a></h2>
|
||||||
<p>On practically any hardware that can support at least a half-duplex channel
|
<p>Over practically any medium that can support at least a half-duplex channel
|
||||||
with 1.000 bits per second throughput, and an MTU of 500 bytes. Data radios,
|
with 1.000 bits per second throughput, and an MTU of 500 bytes. Data radios,
|
||||||
modems, LoRa radios, serial lines, AX.25 TNCs, amateur radio digital modes,
|
modems, LoRa radios, serial lines, AX.25 TNCs, amateur radio digital modes,
|
||||||
ad-hoc WiFi, free-space optical links and similar systems are all examples
|
ad-hoc WiFi, free-space optical links and similar systems are all examples
|
||||||
@@ -174,7 +181,7 @@ network, and vice versa.</p>
|
|||||||
<li class="right" >
|
<li class="right" >
|
||||||
<a href="index.html" title="Reticulum Network Stack Manual"
|
<a href="index.html" title="Reticulum Network Stack Manual"
|
||||||
>previous</a> |</li>
|
>previous</a> |</li>
|
||||||
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li>
|
||||||
<li class="nav-item nav-item-this"><a href="">What is Reticulum?</a></li>
|
<li class="nav-item nav-item-this"><a href="">What is Reticulum?</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ copyright = '2021, Mark Qvist'
|
|||||||
author = 'Mark Qvist'
|
author = 'Mark Qvist'
|
||||||
|
|
||||||
# The full version, including alpha/beta/rc tags
|
# The full version, including alpha/beta/rc tags
|
||||||
release = '0.2.0 beta'
|
release = '0.2.1 beta'
|
||||||
|
|
||||||
|
|
||||||
# -- General configuration ---------------------------------------------------
|
# -- General configuration ---------------------------------------------------
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
********************
|
********************
|
||||||
Getting Started Fast
|
Getting Started Fast
|
||||||
********************
|
********************
|
||||||
What do we want to do? Something! When do we want to do it? Right now! Let's go.
|
|
||||||
|
|
||||||
The best way to get started with the Reticulum Network Stack depends on what
|
The best way to get started with the Reticulum Network Stack depends on what
|
||||||
you want to do. This guide will outline sensible starting paths for different
|
you want to do. This guide will outline sensible starting paths for different
|
||||||
@@ -23,7 +22,7 @@ in the development for the messaging and information-sharing protocol
|
|||||||
Develop a Program with Reticulum
|
Develop a Program with Reticulum
|
||||||
===========================================
|
===========================================
|
||||||
If you want to develop programs that use Reticulum, the easiest way to get
|
If you want to develop programs that use Reticulum, the easiest way to get
|
||||||
started is to install Reticulum via pip:
|
started is to install the latest release of Reticulum via pip:
|
||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ the development of Reticulum itself.
|
|||||||
|
|
||||||
whatis
|
whatis
|
||||||
gettingstartedfast
|
gettingstartedfast
|
||||||
examples
|
|
||||||
reference
|
|
||||||
understanding
|
understanding
|
||||||
|
reference
|
||||||
|
examples
|
||||||
|
|
||||||
|
|
||||||
Indices and Tables
|
Indices and Tables
|
||||||
|
|||||||
+139
-92
@@ -160,9 +160,13 @@ Destination Naming
|
|||||||
Destinations are created and named in an easy to understand dotted notation of *aspects*, and
|
Destinations are created and named in an easy to understand dotted notation of *aspects*, and
|
||||||
represented on the network as a hash of this value. The hash is a SHA-256 truncated to 80 bits. The
|
represented on the network as a hash of this value. The hash is a SHA-256 truncated to 80 bits. The
|
||||||
top level aspect should always be a unique identifier for the application using the destination.
|
top level aspect should always be a unique identifier for the application using the destination.
|
||||||
The next levels of aspects can be defined in any way by the creator of the application. For example,
|
The next levels of aspects can be defined in any way by the creator of the application.
|
||||||
a destination for a environmental monitoring application could be made up of the application name, a
|
|
||||||
device type and measurement type, like this:
|
Aspects can be as long and as plentiful as required, and a resulting long destination name will not
|
||||||
|
impact efficiency, as names are always represented as truncated SHA-256 hashes on the network.
|
||||||
|
|
||||||
|
As an example, a destination for a environmental monitoring application could be made up of the
|
||||||
|
application name, a device type and measurement type, like this:
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
@@ -201,9 +205,8 @@ To recap, the different destination types should be used in the following situat
|
|||||||
* **Single**
|
* **Single**
|
||||||
When private communication between two endpoints is needed. Supports multiple hops.
|
When private communication between two endpoints is needed. Supports multiple hops.
|
||||||
* **Group**
|
* **Group**
|
||||||
When private communication between two or more endpoints is needed. More efficient in
|
When private communication between two or more endpoints is needed. Supports multiple hops
|
||||||
data usage than *single* destinations. Supports multiple hops indirectly, but must first be
|
indirectly, but must first be established through a *single* destination.
|
||||||
established through a *single* destination.
|
|
||||||
* **Plain**
|
* **Plain**
|
||||||
When plain-text communication is desirable, for example when broadcasting information.
|
When plain-text communication is desirable, for example when broadcasting information.
|
||||||
|
|
||||||
@@ -214,9 +217,9 @@ an unknown public key from the network, as all participating nodes serve as a di
|
|||||||
of public keys.
|
of public keys.
|
||||||
|
|
||||||
Note that public key information can be shared and verified in many other ways than using the
|
Note that public key information can be shared and verified in many other ways than using the
|
||||||
built-in methodology, and that it is therefore not required to use the announce/request functionality.
|
built-in *announce* functionality, and that it is therefore not required to use the announce/request
|
||||||
It is by far the easiest though, and should definitely be used if there is not a good reason for
|
functionality to obtain public keys. It is by far the easiest though, and should definitely be used
|
||||||
doing it differently.
|
if there is not a good reason for doing it differently.
|
||||||
|
|
||||||
.. _understanding-keyannouncements:
|
.. _understanding-keyannouncements:
|
||||||
|
|
||||||
@@ -235,7 +238,7 @@ contain the following information:
|
|||||||
* The announcers public key
|
* The announcers public key
|
||||||
* Application specific data, in this case the users nickname and availability status
|
* Application specific data, in this case the users nickname and availability status
|
||||||
* A random blob, making each new announce unique
|
* A random blob, making each new announce unique
|
||||||
* A signature of the above information, verifying authenticity
|
* An Ed25519 signature of the above information, verifying authenticity
|
||||||
|
|
||||||
With this information, any Reticulum node that receives it will be able to reconstruct an outgoing
|
With this information, any Reticulum node that receives it will be able to reconstruct an outgoing
|
||||||
destination to securely communicate with that destination. You might have noticed that there is one
|
destination to securely communicate with that destination. You might have noticed that there is one
|
||||||
@@ -244,8 +247,9 @@ the aspect names of the destination. These are intentionally left out to save ba
|
|||||||
will be implicit in almost all cases. If a destination name is not entirely implicit, information can be
|
will be implicit in almost all cases. If a destination name is not entirely implicit, information can be
|
||||||
included in the application specific data part that will allow the receiver to infer the naming.
|
included in the application specific data part that will allow the receiver to infer the naming.
|
||||||
|
|
||||||
It is important to note that announcements will be forwarded throughout the network according to a
|
It is important to note that announces will be forwarded throughout the network according to a
|
||||||
certain pattern. This will be detailed later.
|
certain pattern. This will be detailed in the section
|
||||||
|
:ref:`The Announce Mechanism in Detail<understanding-announce>`.
|
||||||
|
|
||||||
Seeing how *single* destinations are always tied to a private/public key pair leads us to the next topic.
|
Seeing how *single* destinations are always tied to a private/public key pair leads us to the next topic.
|
||||||
|
|
||||||
@@ -268,8 +272,8 @@ the identity first, and then link it to created destinations.
|
|||||||
|
|
||||||
Building upon the simple messenger example, we could use an identity to represent the user of the
|
Building upon the simple messenger example, we could use an identity to represent the user of the
|
||||||
application. Destinations created will then be linked to this identity to allow communication to
|
application. Destinations created will then be linked to this identity to allow communication to
|
||||||
reach the user. In such a case it is of great importance to store the user’s identity securely and
|
reach the user. In all cases it is of great importance to store the private keys associated with any
|
||||||
privately.
|
Reticulum Identity securely and privately.
|
||||||
|
|
||||||
.. _understanding-gettingfurther:
|
.. _understanding-gettingfurther:
|
||||||
|
|
||||||
@@ -279,8 +283,9 @@ Getting Further
|
|||||||
The above functions and principles form the core of Reticulum, and would suffice to create
|
The above functions and principles form the core of Reticulum, and would suffice to create
|
||||||
functional networked applications in local clusters, for example over radio links where all interested
|
functional networked applications in local clusters, for example over radio links where all interested
|
||||||
nodes can directly hear each other. But to be truly useful, we need a way to direct traffic over multiple
|
nodes can directly hear each other. But to be truly useful, we need a way to direct traffic over multiple
|
||||||
hops in the network. In the next sections, two concepts that allow this will be introduced, *paths* and
|
hops in the network.
|
||||||
*links*.
|
|
||||||
|
In the following sections, two concepts that allow this will be introduced, *paths* and *links*.
|
||||||
|
|
||||||
.. _understanding-transport:
|
.. _understanding-transport:
|
||||||
|
|
||||||
@@ -298,70 +303,28 @@ useable over bandwidth-limited, high-latency links.
|
|||||||
|
|
||||||
To overcome such challenges, Reticulum’s *Transport* system uses public-key cryptography to
|
To overcome such challenges, Reticulum’s *Transport* system uses public-key cryptography to
|
||||||
implement the concept of *paths* that allow discovery of how to get information to a certain
|
implement the concept of *paths* that allow discovery of how to get information to a certain
|
||||||
destination, and *resources* that help make reliable data transfer more efficient.
|
destination. It is important to note that no single node in a Reticulum network knows the complete
|
||||||
|
path to a destination. Every Transport node participating in a Reticulum network will only
|
||||||
|
know what the most direct way to get a packet one hop closer to it's destination is.
|
||||||
|
|
||||||
.. _understanding-paths:
|
.. _understanding-announce:
|
||||||
|
|
||||||
Reaching the Destination
|
The Announce Mechanism in Detail
|
||||||
------------------------
|
--------------------------------
|
||||||
|
|
||||||
In networks with changing topology and trustless connectivity, nodes need a way to establish
|
When an *announce* is transmitted by a node, it will be forwarded by any node receiving it, but
|
||||||
*verified connectivity* with each other. Since the network is assumed to be trustless, Reticulum
|
according to some specific rules:
|
||||||
must provide a way to guarantee that the peer you are communicating with is actually who you
|
|
||||||
expect. To do this, the following process is employed:
|
|
||||||
|
|
||||||
|
|
||||||
* | First, the node that wishes to establish connectivity will send out a special packet, that
|
* | If this exact announce has already been received before, ignore it.
|
||||||
traverses the network and locates the desired destination. Along the way, the nodes that
|
|
||||||
forward the packet will take note of this *link request*.
|
|
||||||
|
|
||||||
* | Second, if the destination accepts the *link request* , it will send back a packet that proves the
|
* | If not, record into a table which node the announce was received from, and how many times in
|
||||||
authenticity of it’s identity (and the receipt of the link request) to the initiating node. All
|
|
||||||
nodes that initially forwarded the packet will also be able to verify this proof, and thus
|
|
||||||
accept the validity of the *link* throughout the network.
|
|
||||||
|
|
||||||
* | When the validity of the *link* has been accepted by forwarding nodes, these nodes will
|
|
||||||
remember the *link* , and it can subsequently be used by referring to a hash representing it.
|
|
||||||
|
|
||||||
* | As a part of the *link request* , a Diffie-Hellman key exchange takes place, that sets up an
|
|
||||||
efficient symmetrically encrypted tunnel between the two nodes, using elliptic curve
|
|
||||||
cryptography. As such, this mode of communication is preferred, even for situations when
|
|
||||||
nodes can directly communicate, when the amount of data to be exchanged numbers in the
|
|
||||||
tens of packets.
|
|
||||||
|
|
||||||
* | When a *link* has been set up, it automatically provides message receipt functionality, so the
|
|
||||||
sending node can obtain verified confirmation that the information reached the intended
|
|
||||||
recipient.
|
|
||||||
|
|
||||||
In a moment, we will discuss the specifics of how this methodology is implemented, but let’s first
|
|
||||||
recap what purposes this serves. We first ensure that the node answering our request is actually the
|
|
||||||
one we want to communicate with, and not a malicious actor pretending to be so. At the same time
|
|
||||||
we establish an efficient encrypted channel. The setup of this is relatively cheap in terms of
|
|
||||||
bandwidth, so it can be used just for a short exchange, and then recreated as needed, which will also
|
|
||||||
rotate encryption keys, but the link can also be kept alive for longer periods of time, if this is
|
|
||||||
more suitable to the application. The amount of bandwidth used on keeping a link open is practically
|
|
||||||
negligible. The procedure also inserts the *link id* , a hash calculated from the link request packet,
|
|
||||||
into the memory of forwarding nodes, which means that the communicating nodes can thereafter reach each
|
|
||||||
other simply by referring to this *link id*.
|
|
||||||
|
|
||||||
Step 1: Pathfinding
|
|
||||||
^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
The pathfinding method builds on the *announce* functionality discussed earlier. When an announce
|
|
||||||
is sent out by a node, it will be forwarded by any node receiving it, but according to some specific
|
|
||||||
rules:
|
|
||||||
|
|
||||||
|
|
||||||
* | If this announce has already been received before, ignore it.
|
|
||||||
|
|
||||||
* | Record into a table which node the announce was received from, and how many times in
|
|
||||||
total it has been retransmitted to get here.
|
total it has been retransmitted to get here.
|
||||||
|
|
||||||
* | If the announce has been retransmitted *m+1* times, it will not be forwarded. By default, *m* is
|
* | If the announce has been retransmitted *m+1* times, it will not be forwarded. By default, *m* is
|
||||||
set to 18.
|
set to 18.
|
||||||
|
|
||||||
* | The announce will be assigned a delay *d* = c\ :sup:`h` seconds, where *c* is a decay constant, by
|
* | The announce will be assigned a delay *d* = c\ :sup:`h` seconds, where *c* is a decay constant, and *h* is the amount of times this packet has already been forwarded.
|
||||||
default 2, and *h* is the amount of times this packet has already been forwarded.
|
|
||||||
|
|
||||||
* | The packet will be given a priority *p = 1/d*.
|
* | The packet will be given a priority *p = 1/d*.
|
||||||
|
|
||||||
@@ -370,10 +333,11 @@ rules:
|
|||||||
not utilized by other traffic, the announce will be forwarded.
|
not utilized by other traffic, the announce will be forwarded.
|
||||||
|
|
||||||
* | If no other nodes are heard retransmitting the announce with a greater hop count than when
|
* | If no other nodes are heard retransmitting the announce with a greater hop count than when
|
||||||
it left this node, transmitting it will be retried *r* times. By default, *r* is set to 2. Retries follow
|
it left this node, transmitting it will be retried *r* times. By default, *r* is set to 1. Retries
|
||||||
same rules as above, with the exception that it must wait for at least *d* = c\ :sup:`h+1` + t seconds, ie.,
|
follow same rules as above, with the exception that it must wait for at least *d* = c\ :sup:`h+1` +
|
||||||
the amount of time it would take the next node to retransmit the packet. By default, *t* is set to
|
t + rand(0, rw) seconds. This amount of time is equal to the amount of time it would take the next
|
||||||
10.
|
node to retransmit the packet, plus a random window. By default, *t* is set to 10 seconds, and the
|
||||||
|
random window *rw* is set to 10 seconds.
|
||||||
|
|
||||||
* | If a newer announce from the same destination arrives, while an identical one is already in
|
* | If a newer announce from the same destination arrives, while an identical one is already in
|
||||||
the queue, the newest announce is discarded. If the newest announce contains different
|
the queue, the newest announce is discarded. If the newest announce contains different
|
||||||
@@ -392,14 +356,95 @@ distance of *Lavg =* 15 kilometers, an announce will be able to propagate outwar
|
|||||||
kilometers in 34 minutes, and a *maximum announce radius* of 270 kilometers in approximately 3
|
kilometers in 34 minutes, and a *maximum announce radius* of 270 kilometers in approximately 3
|
||||||
days.
|
days.
|
||||||
|
|
||||||
Step 2: Link Establishment
|
.. _understanding-paths:
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
After seeing how the conditions for finding a path through the network are created, we will now
|
Reaching the Destination
|
||||||
explore how two nodes can establish reliable communications over multiple hops. The *link* in
|
------------------------
|
||||||
Reticulum terminology should not be viewed as a direct node-to-node link on the physical layer, but
|
|
||||||
as an abstract channel, that can be open for any amount of time, and can span an arbitrary number
|
In networks with changing topology and trustless connectivity, nodes need a way to establish
|
||||||
of hops, where information will be exchanged between two nodes.
|
*verified connectivity* with each other. Since the network is assumed to be trustless, Reticulum
|
||||||
|
must provide a way to guarantee that the peer you are communicating with is actually who you
|
||||||
|
expect. Reticulum offers two ways to do this.
|
||||||
|
|
||||||
|
For exchanges of small amounts of information, Reticulum offers the *Packet* API, which works exactly like you would expect - on a per packet level. The following process is employed when sending a packet:
|
||||||
|
|
||||||
|
* | A packet is always created with an associated destination and some payload data. When the packet is sent
|
||||||
|
to a *single* destination type, Reticulum will automatically create an ephemeral encryption key, perform
|
||||||
|
an ECDH key exchange with the destinations public key, and encrypt the information.
|
||||||
|
|
||||||
|
* | It is important to note that this key exchange does not require any network traffic. The sender already
|
||||||
|
knows the public key of the destination from an earlier received *announce*, and can thus perform the ECDH
|
||||||
|
key exchange locally, before sending the packet.
|
||||||
|
|
||||||
|
* | The public part of the newly generated ephemeral key-pair is included with the encrypted token, and sent
|
||||||
|
along with the encrypted payload data in the packet.
|
||||||
|
|
||||||
|
* | When the destination receives the packet, it can itself perform an ECDH key exchange and decrypt the
|
||||||
|
packet.
|
||||||
|
|
||||||
|
* | A new ephemeral key is used for every packet sent in this way, and forward secrecy is guaranteed on a
|
||||||
|
per packet level.
|
||||||
|
|
||||||
|
* | Once the packet has been received and decrypted by the addressed destination, that destination can opt
|
||||||
|
to *prove* its receipt of the packet. It does this by calculating the SHA-256 hash of the received packet,
|
||||||
|
and signing this hash with it's Ed25519 signing key. Transport nodes in the network can then direct this
|
||||||
|
*proof* back to the packets origin, where the signature can be verified against the destinations known
|
||||||
|
public signing key.
|
||||||
|
|
||||||
|
* | In case the packet is addressed to a *group* destination type, the packet will be encrypted with the
|
||||||
|
pre-shared AES-128 key associated with the destination. In case the packet is addressed to a *plain*
|
||||||
|
destination type, the payload data will not be encrypted. Neither of these two destination types offer
|
||||||
|
forward secrecy. In general, it is recommended to always use the *single* destination type, unless it is
|
||||||
|
strictly necessary to use one of the others.
|
||||||
|
|
||||||
|
|
||||||
|
For exchanges of larger amounts of data, or when longer sessions of bidirectional communication is desired, Reticulum offers the *Link* API. To establish a *link*, the following process is employed:
|
||||||
|
|
||||||
|
* | First, the node that wishes to establish a link will send out a special packet, that
|
||||||
|
traverses the network and locates the desired destination. Along the way, the nodes that
|
||||||
|
forward the packet will take note of this *link request*.
|
||||||
|
|
||||||
|
* | Second, if the destination accepts the *link request* , it will send back a packet that proves the
|
||||||
|
authenticity of it’s identity (and the receipt of the link request) to the initiating node. All
|
||||||
|
nodes that initially forwarded the packet will also be able to verify this proof, and thus
|
||||||
|
accept the validity of the *link* throughout the network.
|
||||||
|
|
||||||
|
* | When the validity of the *link* has been accepted by forwarding nodes, these nodes will
|
||||||
|
remember the *link* , and it can subsequently be used by referring to a hash representing it.
|
||||||
|
|
||||||
|
* | As a part of the *link request* , a Diffie-Hellman key exchange takes place, that sets up an
|
||||||
|
efficiently encrypted tunnel between the two nodes, using elliptic curve cryptography. As such,
|
||||||
|
this mode of communication is preferred, even for situations when nodes can directly communicate,
|
||||||
|
when the amount of data to be exchanged numbers in the tens of packets.
|
||||||
|
|
||||||
|
* | When a *link* has been set up, it automatically provides message receipt functionality, through
|
||||||
|
the same *proof* mechanism discussed before, so the sending node can obtain verified confirmation
|
||||||
|
that the information reached the intended recipient.
|
||||||
|
|
||||||
|
In a moment, we will discuss the details of how this methodology is implemented, but let’s first
|
||||||
|
recap what purposes this methodology serves. We first ensure that the node answering our request
|
||||||
|
is actually the one we want to communicate with, and not a malicious actor pretending to be so.
|
||||||
|
At the same time we establish an efficient encrypted channel. The setup of this is relatively cheap in
|
||||||
|
terms of bandwidth, so it can be used just for a short exchange, and then recreated as needed, which will
|
||||||
|
also rotate encryption keys. The link can also be kept alive for longer periods of time, if this is
|
||||||
|
more suitable to the application. The procedure also inserts the *link id* , a hash calculated from the link request packet, into the memory of forwarding nodes, which means that the communicating nodes can thereafter reach each other simply by referring to this *link id*.
|
||||||
|
|
||||||
|
The combined bandwidth cost of setting up a link is 3 packets totalling 240 bytes (more info in the
|
||||||
|
:ref:`Binary Packet Format<understanding-packetformat>` section). The amount of bandwidth used on keeping
|
||||||
|
a link open is practically negligible, at 0.62 bits per second. Even on a slow 1200 bits per second packet
|
||||||
|
radio channel, 100 concurrent links will still leave 95% channel capacity for actual data.
|
||||||
|
|
||||||
|
|
||||||
|
Link Establishment in Detail
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
After exploring the basics of the announce mechanism, finding a path through the network, and an overview
|
||||||
|
of the link establishment procedure, this section will go into greater detail about the Reticulum link
|
||||||
|
establishment process.
|
||||||
|
|
||||||
|
The *link* in Reticulum terminology should not be viewed as a direct node-to-node link on the
|
||||||
|
physical layer, but as an abstract channel, that can be open for any amount of time, and can span
|
||||||
|
an arbitrary number of hops, where information will be exchanged between two nodes.
|
||||||
|
|
||||||
|
|
||||||
* | When a node in the network wants to establish verified connectivity with another node, it
|
* | When a node in the network wants to establish verified connectivity with another node, it
|
||||||
@@ -412,25 +457,25 @@ of hops, where information will be exchanged between two nodes.
|
|||||||
considered as single public key for simplicity in this explanation.*
|
considered as single public key for simplicity in this explanation.*
|
||||||
|
|
||||||
* | The *link request* is addressed to the destination hash of the desired destination, and
|
* | The *link request* is addressed to the destination hash of the desired destination, and
|
||||||
contains the following data: The newly generated X25519 public key *LKi*. The contents
|
contains the following data: The newly generated X25519 public key *LKi*.
|
||||||
are encrypted with the RSA public key of the destination and tramsitted over the network.
|
|
||||||
|
|
||||||
* | The broadcasted packet will be directed through the network according to the rules laid out
|
* | The broadcasted packet will be directed through the network according to the rules laid out
|
||||||
previously.
|
previously.
|
||||||
|
|
||||||
* | Any node that forwards the link request will store a *link id* in it’s *link table* , along with the
|
* | Any node that forwards the link request will store a *link id* in it’s *link table* , along with the
|
||||||
amount of hops the packet had taken when received. The link id is a hash of the entire link
|
amount of hops the packet had taken when received. The link id is a hash of the entire link
|
||||||
request packet. If the path is not *proven* within some set amount of time, the entry will be
|
request packet. If the link request packet is not *proven* by the addressed destination within some
|
||||||
dropped from the *link table* again.
|
set amount of time, the entry will be dropped from the *link table* again.
|
||||||
|
|
||||||
* | When the destination receives the link request packet, it will decrypt it and decide whether to
|
* | When the destination receives the link request packet, it will decide whether to accept the request.
|
||||||
accept the request. If it is accepted, the destination will also generate a new X25519 private/public
|
If it is accepted, the destination will also generate a new X25519 private/public key pair, and
|
||||||
key pair, and perform a Diffie Hellman Key Exchange, deriving a new symmetric key that will be used
|
perform a Diffie Hellman Key Exchange, deriving a new symmetric key that will be used to encrypt the
|
||||||
to encrypt the channel, once it has been established.
|
channel, once it has been established.
|
||||||
|
|
||||||
* | A *link proof* packet is now constructed and transmitted over the network. This packet is
|
* | A *link proof* packet is now constructed and transmitted over the network. This packet is
|
||||||
addressed to the *link id* of the *link*. It contains the following data: The newly generated X25519
|
addressed to the *link id* of the *link*. It contains the following data: The newly generated X25519
|
||||||
public key *LKr* and an RSA-1024 signature of the *link id* and *LKr*.
|
public key *LKr* and an Ed25519 signature of the *link id* and *LKr* made by the signing key of
|
||||||
|
the addressed destination.
|
||||||
|
|
||||||
* | By verifying this *link proof* packet, all nodes that originally transported the *link request*
|
* | By verifying this *link proof* packet, all nodes that originally transported the *link request*
|
||||||
packet to the destination from the originator can now verify that the intended destination received
|
packet to the destination from the originator can now verify that the intended destination received
|
||||||
@@ -556,6 +601,8 @@ the light of Reticulums goal of equal access, doing so would need to be the subj
|
|||||||
investigation of the consequences first.
|
investigation of the consequences first.
|
||||||
|
|
||||||
|
|
||||||
|
.. _understanding-packetformat:
|
||||||
|
|
||||||
Binary Packet Format
|
Binary Packet Format
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
@@ -651,8 +698,8 @@ Binary Packet Format
|
|||||||
wire size including all fields.
|
wire size including all fields.
|
||||||
|
|
||||||
- Path Request : 33 bytes
|
- Path Request : 33 bytes
|
||||||
- Announce : 323 bytes
|
- Announce : 151 bytes
|
||||||
- Link Request : 141 bytes
|
- Link Request : 77 bytes
|
||||||
- Link Proof : 205 bytes
|
- Link Proof : 77 bytes
|
||||||
- Link RTT packet : 86 bytes
|
- Link RTT packet : 86 bytes
|
||||||
- Link keepalive : 14 bytes
|
- Link keepalive : 14 bytes
|
||||||
+12
-4
@@ -25,11 +25,11 @@ What does Reticulum Offer?
|
|||||||
|
|
||||||
* Fully self-configuring multi-hop routing
|
* Fully self-configuring multi-hop routing
|
||||||
|
|
||||||
* Asymmetric RSA encryption and signatures as basis for all communication
|
* Asymmetric X25519 encryption and Ed25519 signatures as a basis for all communication
|
||||||
|
|
||||||
* Perfect Forward Secrecy on links with ephemereal Elliptic Curve Diffie-Hellman keys (on Curve25519)
|
* Forward Secrecy with ephemereal Elliptic Curve Diffie-Hellman keys on Curve25519
|
||||||
|
|
||||||
* Reticulum uses the Fernet specification for encryption on links and to group destinations
|
* Reticulum uses the `Fernet <https://github.com/fernet/spec/blob/master/Spec.md>`_ specification for encryption
|
||||||
|
|
||||||
* AES-128 in CBC mode with PKCS7 padding
|
* AES-128 in CBC mode with PKCS7 padding
|
||||||
|
|
||||||
@@ -37,6 +37,8 @@ What does Reticulum Offer?
|
|||||||
|
|
||||||
* IVs are generated through os.urandom()
|
* IVs are generated through os.urandom()
|
||||||
|
|
||||||
|
* Keys are ephemeral and derived from an ECDH key exchange on Curve25519
|
||||||
|
|
||||||
* Unforgeable packet delivery confirmations
|
* Unforgeable packet delivery confirmations
|
||||||
|
|
||||||
* A variety of supported interface types
|
* A variety of supported interface types
|
||||||
@@ -51,10 +53,16 @@ What does Reticulum Offer?
|
|||||||
|
|
||||||
* The API is very easy to use, and provides transfer progress
|
* The API is very easy to use, and provides transfer progress
|
||||||
|
|
||||||
|
* Efficient link establishment
|
||||||
|
|
||||||
|
* Total bandwidth cost of setting up a link is only 3 packets, totalling 240 bytes
|
||||||
|
|
||||||
|
* Low cost of keeping links open at only 0.62 bits per second
|
||||||
|
|
||||||
|
|
||||||
Where can Reticulum be Used?
|
Where can Reticulum be Used?
|
||||||
============================
|
============================
|
||||||
On practically any hardware that can support at least a half-duplex channel
|
Over practically any medium that can support at least a half-duplex channel
|
||||||
with 1.000 bits per second throughput, and an MTU of 500 bytes. Data radios,
|
with 1.000 bits per second throughput, and an MTU of 500 bytes. Data radios,
|
||||||
modems, LoRa radios, serial lines, AX.25 TNCs, amateur radio digital modes,
|
modems, LoRa radios, serial lines, AX.25 TNCs, amateur radio digital modes,
|
||||||
ad-hoc WiFi, free-space optical links and similar systems are all examples
|
ad-hoc WiFi, free-space optical links and similar systems are all examples
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
|
|||||||
|
|
||||||
setuptools.setup(
|
setuptools.setup(
|
||||||
name="rns",
|
name="rns",
|
||||||
version="0.2.0",
|
version="0.2.1",
|
||||||
author="Mark Qvist",
|
author="Mark Qvist",
|
||||||
author_email="mark@unsigned.io",
|
author_email="mark@unsigned.io",
|
||||||
description="Self-configuring, encrypted and resilient mesh networking stack for LoRa, packet radio, WiFi and everything in between",
|
description="Self-configuring, encrypted and resilient mesh networking stack for LoRa, packet radio, WiFi and everything in between",
|
||||||
|
|||||||
Reference in New Issue
Block a user