Compare commits

..

8 Commits

Author SHA1 Message Date
Mark Qvist d17fbf1f34 Merge branch 'master' of github.com:markqvist/Reticulum 2022-03-28 15:20:35 +02:00
Mark Qvist 7398e312fc Updated version 2022-03-28 15:20:14 +02:00
markqvist 82fc8720ad Update README.md 2022-03-26 22:45:46 +01:00
markqvist 4b9686c31a Update README.md 2022-03-26 22:44:32 +01:00
Mark Qvist 86a5b3302a Updated readme 2022-03-25 20:15:11 +01:00
Mark Qvist c990aae648 Updated license 2022-03-25 20:07:09 +01:00
Mark Qvist 3051b6897d Updated filtering rules. Fixes #18. 2022-03-15 14:55:47 +01:00
Mark Qvist 550dfd44cb Improved cryptography API compatibility 2022-03-08 00:38:51 +01:00
8 changed files with 66 additions and 13 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License, unless otherwise noted
Copyright (c) 2018 Mark Qvist / unsigned.io
Copyright (c) 2016-2022 Mark Qvist / unsigned.io
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+8 -5
View File
@@ -1,7 +1,9 @@
Reticulum Network Stack β
==========
Reticulum is a cryptography-based networking stack for wide-area networks built on readily available hardware, and can operate even with very high latency and extremely low bandwidth. Reticulum allows you to build very wide-area networks with off-the-shelf tools, and offers end-to-end encryption, autoconfiguring cryptographically backed multi-hop transport, efficient addressing, unforgeable packet acknowledgements and more.
<p align="center"><img width="200" src="https://unsigned.io/wp-content/uploads/2022/03/reticulum_logo_512.png"></p>
Reticulum is the cryptography-based networking stack for wide-area networks built on readily available hardware. It can operate even with very high latency and extremely low bandwidth. Reticulum allows you to build wide-area networks with off-the-shelf tools, and offers end-to-end encryption, initiator anonymity, autoconfiguring cryptographically backed multi-hop transport, efficient addressing, unforgeable packet acknowledgements and more.
Reticulum is a complete networking stack, and does not need IP or higher layers, although it is easy to use IP (with TCP or UDP) as the underlying carrier for Reticulum. It is therefore trivial to tunnel Reticulum over the Internet or private IP networks.
@@ -42,8 +44,9 @@ For more info, see [unsigned.io/projects/reticulum](https://unsigned.io/projects
## Examples of Reticulum Applications
If you want to quickly get an idea of what Reticulum can do, take a look at the following resources.
- [LXMF](https://github.com/markqvist/lxmf) is a distributed, delay and disruption tolerant message transfer protocol built on Reticulum
- For an off-grid, encrypted and resilient mesh communications platform, see [Nomad Network](https://github.com/markqvist/NomadNet)
- For a distributed, delay and disruption tolerant message transfer protocol built on Reticulum, see [LXMF](https://github.com/markqvist/lxmf)
- The Android, Linux and macOS app [Sideband](https://unsigned.io/sideband) has a graphical interface and focuses on ease of use.
## Where can Reticulum be used?
Over practically any medium that can support at least a half-duplex channel with 500 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.
@@ -84,8 +87,6 @@ Reticulum implements a range of generalised interface types that covers most of
- TCP over IP networks
- UDP over IP networks
## Planned Features
- More interface types for even broader compatibility
- ESP32 devices (ESP-Now, Bluetooth, etc.)
@@ -113,5 +114,7 @@ You can help support the continued development of open, free and private communi
- Bitcoin: 3CPmacGm34qYvR6XWLVEJmi2aNe3PZqUuq
- Ko-Fi: https://ko-fi.com/markqvist
Are certain features in the development roadmap are important to you or your organisation? Make them a reality quickly by sponsoring their implementation.
## Caveat Emptor
Reticulum is experimental software, and should be considered as such. While it has been built with cryptography best-practices very foremost in mind, it _has not_ been externally security audited, and there could very well be privacy-breaking bugs. If you want to help out, or help sponsor an audit, please do get in touch.
Reticulum is relatively young software, and should be considered as such. While it has been built with cryptography best-practices very foremost in mind, it _has not_ been externally security audited, and there could very well be privacy-breaking bugs. If you want to help out, or help sponsor an audit, please do get in touch.
+6
View File
@@ -118,6 +118,9 @@ class Destination:
identity = RNS.Identity()
aspects = aspects+(identity.hexhash,)
if identity != None and self.type == Destination.PLAIN:
raise TypeError("Selected destination type PLAIN cannot hold an identity")
self.identity = identity
self.name = Destination.full_name(app_name, *aspects)
@@ -146,6 +149,9 @@ class Destination:
:param app_data: *bytes* containing the app_data.
:param path_response: Internal flag used by :ref:`RNS.Transport<api-transport>`. Ignore.
"""
if self.type != Destination.SINGLE:
raise TypeError("Only SINGLE destination types can be announced")
destination_hash = self.hash
random_hash = RNS.Identity.get_random_hash()[0:5]+int(time.time()).to_bytes(5, "big")
+10 -2
View File
@@ -14,6 +14,8 @@ from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey, X
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
from cryptography.fernet import Fernet
cio_default_backend = default_backend()
class Identity:
"""
This class is used to manage identities in Reticulum. It provides methods
@@ -392,11 +394,14 @@ class Identity:
)
shared_key = ephemeral_key.exchange(self.pub)
derived_key = derived_key = HKDF(
# TODO: Improve this re-allocation of HKDF
derived_key = HKDF(
algorithm=hashes.SHA256(),
length=32,
salt=self.get_salt(),
info=self.get_context(),
backend=cio_default_backend,
).derive(shared_key)
fernet = Fernet(base64.urlsafe_b64encode(derived_key))
@@ -424,11 +429,14 @@ class Identity:
peer_pub = X25519PublicKey.from_public_bytes(peer_pub_bytes)
shared_key = self.prv.exchange(peer_pub)
derived_key = derived_key = HKDF(
# TODO: Improve this re-allocation of HKDF
derived_key = HKDF(
algorithm=hashes.SHA256(),
length=32,
salt=self.get_salt(),
info=self.get_context(),
backend=cio_default_backend,
).derive(shared_key)
fernet = Fernet(base64.urlsafe_b64encode(derived_key))
+6 -1
View File
@@ -15,6 +15,8 @@ import RNS
import traceback
cio_default_backend = default_backend()
class LinkCallbacks:
def __init__(self):
self.link_established = None
@@ -199,11 +201,14 @@ class Link:
def handshake(self):
self.status = Link.HANDSHAKE
self.shared_key = self.prv.exchange(self.peer_pub)
# TODO: Improve this re-allocation of HKDF
self.derived_key = HKDF(
algorithm=hashes.SHA256(),
length=32,
salt=self.get_salt(),
info=self.get_context(),
backend=cio_default_backend,
).derive(self.shared_key)
def prove(self):
@@ -1064,4 +1069,4 @@ class RequestReceiptCallbacks:
def __init__(self):
self.response = None
self.failed = None
self.progress = None
self.progress = None
+27 -3
View File
@@ -457,7 +457,7 @@ class Transport:
sent = False
# Check if we have a known path for the destination in the path table
if packet.packet_type != RNS.Packet.ANNOUNCE and packet.destination_hash in Transport.destination_table:
if packet.packet_type != RNS.Packet.ANNOUNCE and packet.destination.type != RNS.Destination.PLAIN and packet.destination.type != RNS.Destination.GROUP and packet.destination_hash in Transport.destination_table:
outbound_interface = Transport.destination_table[packet.destination_hash][5]
# If there's more than one hop to the destination, and we know
@@ -572,14 +572,38 @@ class Transport:
return True
if packet.context == RNS.Packet.CACHE_REQUEST:
return True
if packet.destination_type == RNS.Destination.PLAIN:
return True
if packet.packet_type != RNS.Packet.ANNOUNCE:
if packet.hops > 1:
RNS.log("Dropped PLAIN packet "+RNS.prettyhexrep(packet.hash)+" with "+str(packet.hops)+" hops", RNS.LOG_DEBUG)
return False
else:
return True
else:
RNS.log("Dropped invalid PLAIN announce packet", RNS.LOG_DEBUG)
return False
if packet.destination_type == RNS.Destination.GROUP:
if packet.packet_type != RNS.Packet.ANNOUNCE:
if packet.hops > 1:
RNS.log("Dropped GROUP packet "+RNS.prettyhexrep(packet.hash)+" with "+str(packet.hops)+" hops", RNS.LOG_DEBUG)
return False
else:
return True
else:
RNS.log("Dropped invalid GROUP announce packet", RNS.LOG_DEBUG)
return False
if not packet.packet_hash in Transport.packet_hashlist:
return True
else:
if packet.packet_type == RNS.Packet.ANNOUNCE:
return True
if packet.destination_type == RNS.Destination.SINGLE:
return True
else:
RNS.log("Dropped invalid announce packet", RNS.LOG_DEBUG)
return False
RNS.log("Filtered packet with hash "+RNS.prettyhexrep(packet.packet_hash), RNS.LOG_DEBUG)
return False
+1 -1
View File
@@ -1 +1 @@
__version__ = "0.3.3"
__version__ = "0.3.4"
+7
View File
@@ -36,3 +36,10 @@ def platform_checks():
RNS.log("On Windows, Reticulum requires Python 3.8 or higher.", RNS.LOG_ERROR)
RNS.log("Please update Python to run Reticulum.", RNS.LOG_ERROR)
RNS.panic()
def cryptography_old_api():
import cryptography
if cryptography.__version__ == "2.8":
return True
else:
return False