mirror of
https://github.com/markqvist/Reticulum.git
synced 2024-12-23 12:20:18 +00:00
Refactored fernet to token
This commit is contained in:
parent
04d2626809
commit
aabb763cea
@ -325,12 +325,12 @@ In the default installation configuration, the `X25519`, `Ed25519` and
|
|||||||
(via the [PyCA/cryptography](https://github.com/pyca/cryptography) package).
|
(via the [PyCA/cryptography](https://github.com/pyca/cryptography) package).
|
||||||
The hashing functions `SHA-256` and `SHA-512` are provided by the standard
|
The hashing functions `SHA-256` and `SHA-512` are provided by the standard
|
||||||
Python [hashlib](https://docs.python.org/3/library/hashlib.html). The `HKDF`,
|
Python [hashlib](https://docs.python.org/3/library/hashlib.html). The `HKDF`,
|
||||||
`HMAC`, `Fernet` primitives, and the `PKCS7` padding function are always
|
`HMAC`, `Token` primitives, and the `PKCS7` padding function are always
|
||||||
provided by the following internal implementations:
|
provided by the following internal implementations:
|
||||||
|
|
||||||
- [HKDF.py](RNS/Cryptography/HKDF.py)
|
- [HKDF.py](RNS/Cryptography/HKDF.py)
|
||||||
- [HMAC.py](RNS/Cryptography/HMAC.py)
|
- [HMAC.py](RNS/Cryptography/HMAC.py)
|
||||||
- [Fernet.py](RNS/Cryptography/Fernet.py)
|
- [Token.py](RNS/Cryptography/Token.py)
|
||||||
- [PKCS7.py](RNS/Cryptography/PKCS7.py)
|
- [PKCS7.py](RNS/Cryptography/PKCS7.py)
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ from RNS.Cryptography import HMAC
|
|||||||
from RNS.Cryptography import PKCS7
|
from RNS.Cryptography import PKCS7
|
||||||
from RNS.Cryptography.AES import AES_128_CBC
|
from RNS.Cryptography.AES import AES_128_CBC
|
||||||
|
|
||||||
class Fernet():
|
class Token():
|
||||||
"""
|
"""
|
||||||
This class provides a slightly modified implementation of the Fernet spec
|
This class provides a slightly modified implementation of the Fernet spec
|
||||||
found at: https://github.com/fernet/spec/blob/master/Spec.md
|
found at: https://github.com/fernet/spec/blob/master/Spec.md
|
||||||
@ -37,7 +37,7 @@ class Fernet():
|
|||||||
not relevant to Reticulum. They are therefore stripped from this
|
not relevant to Reticulum. They are therefore stripped from this
|
||||||
implementation, since they incur overhead and leak initiator metadata.
|
implementation, since they incur overhead and leak initiator metadata.
|
||||||
"""
|
"""
|
||||||
FERNET_OVERHEAD = 48 # Bytes
|
TOKEN_OVERHEAD = 48 # Bytes
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def generate_key():
|
def generate_key():
|
@ -5,7 +5,7 @@ from .Hashes import sha256
|
|||||||
from .Hashes import sha512
|
from .Hashes import sha512
|
||||||
from .HKDF import hkdf
|
from .HKDF import hkdf
|
||||||
from .PKCS7 import PKCS7
|
from .PKCS7 import PKCS7
|
||||||
from .Fernet import Fernet
|
from .Token import Token
|
||||||
from .Provider import backend
|
from .Provider import backend
|
||||||
|
|
||||||
import RNS.Cryptography.Provider as cp
|
import RNS.Cryptography.Provider as cp
|
||||||
|
@ -26,7 +26,7 @@ import time
|
|||||||
import threading
|
import threading
|
||||||
import RNS
|
import RNS
|
||||||
|
|
||||||
from RNS.Cryptography import Fernet
|
from RNS.Cryptography import Token
|
||||||
from .vendor import umsgpack as umsgpack
|
from .vendor import umsgpack as umsgpack
|
||||||
|
|
||||||
class Callbacks:
|
class Callbacks:
|
||||||
@ -525,8 +525,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 = Token.generate_key()
|
||||||
self.prv = Fernet(self.prv_bytes)
|
self.prv = Token(self.prv_bytes)
|
||||||
|
|
||||||
def get_private_key(self):
|
def get_private_key(self):
|
||||||
"""
|
"""
|
||||||
@ -556,7 +556,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 = Token(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:
|
||||||
|
@ -31,7 +31,7 @@ import threading
|
|||||||
from .vendor import umsgpack as umsgpack
|
from .vendor import umsgpack as umsgpack
|
||||||
|
|
||||||
from RNS.Cryptography import X25519PrivateKey, X25519PublicKey, Ed25519PrivateKey, Ed25519PublicKey
|
from RNS.Cryptography import X25519PrivateKey, X25519PublicKey, Ed25519PrivateKey, Ed25519PublicKey
|
||||||
from RNS.Cryptography import Fernet
|
from RNS.Cryptography import Token
|
||||||
|
|
||||||
|
|
||||||
class Identity:
|
class Identity:
|
||||||
@ -66,7 +66,7 @@ class Identity:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# Non-configurable constants
|
# Non-configurable constants
|
||||||
FERNET_OVERHEAD = RNS.Cryptography.Fernet.FERNET_OVERHEAD
|
TOKEN_OVERHEAD = RNS.Cryptography.Token.TOKEN_OVERHEAD
|
||||||
AES128_BLOCKSIZE = 16 # In bytes
|
AES128_BLOCKSIZE = 16 # In bytes
|
||||||
HASHLENGTH = 256 # In bits
|
HASHLENGTH = 256 # In bits
|
||||||
SIGLENGTH = KEYSIZE # In bits
|
SIGLENGTH = KEYSIZE # In bits
|
||||||
@ -646,8 +646,8 @@ class Identity:
|
|||||||
context=self.get_context(),
|
context=self.get_context(),
|
||||||
)
|
)
|
||||||
|
|
||||||
fernet = Fernet(derived_key)
|
token = Token(derived_key)
|
||||||
ciphertext = fernet.encrypt(plaintext)
|
ciphertext = token.encrypt(plaintext)
|
||||||
token = ephemeral_pub_bytes+ciphertext
|
token = ephemeral_pub_bytes+ciphertext
|
||||||
|
|
||||||
return token
|
return token
|
||||||
@ -684,8 +684,8 @@ class Identity:
|
|||||||
context=self.get_context(),
|
context=self.get_context(),
|
||||||
)
|
)
|
||||||
|
|
||||||
fernet = Fernet(derived_key)
|
token = Token(derived_key)
|
||||||
plaintext = fernet.decrypt(ciphertext)
|
plaintext = token.decrypt(ciphertext)
|
||||||
if ratchet_id_receiver:
|
if ratchet_id_receiver:
|
||||||
ratchet_id_receiver.latest_ratchet_id = ratchet_id
|
ratchet_id_receiver.latest_ratchet_id = ratchet_id
|
||||||
|
|
||||||
@ -709,8 +709,8 @@ class Identity:
|
|||||||
context=self.get_context(),
|
context=self.get_context(),
|
||||||
)
|
)
|
||||||
|
|
||||||
fernet = Fernet(derived_key)
|
token = Token(derived_key)
|
||||||
plaintext = fernet.decrypt(ciphertext)
|
plaintext = token.decrypt(ciphertext)
|
||||||
if ratchet_id_receiver:
|
if ratchet_id_receiver:
|
||||||
ratchet_id_receiver.latest_ratchet_id = None
|
ratchet_id_receiver.latest_ratchet_id = None
|
||||||
|
|
||||||
|
20
RNS/Link.py
20
RNS/Link.py
@ -21,7 +21,7 @@
|
|||||||
# SOFTWARE.
|
# SOFTWARE.
|
||||||
|
|
||||||
from RNS.Cryptography import X25519PrivateKey, X25519PublicKey, Ed25519PrivateKey, Ed25519PublicKey
|
from RNS.Cryptography import X25519PrivateKey, X25519PublicKey, Ed25519PrivateKey, Ed25519PublicKey
|
||||||
from RNS.Cryptography import Fernet
|
from RNS.Cryptography import Token
|
||||||
from RNS.Channel import Channel, LinkChannelOutlet
|
from RNS.Channel import Channel, LinkChannelOutlet
|
||||||
|
|
||||||
from time import sleep
|
from time import sleep
|
||||||
@ -61,7 +61,7 @@ class Link:
|
|||||||
ECPUBSIZE = 32+32
|
ECPUBSIZE = 32+32
|
||||||
KEYSIZE = 32
|
KEYSIZE = 32
|
||||||
|
|
||||||
MDU = math.floor((RNS.Reticulum.MTU-RNS.Reticulum.IFAC_MIN_SIZE-RNS.Reticulum.HEADER_MINSIZE-RNS.Identity.FERNET_OVERHEAD)/RNS.Identity.AES128_BLOCKSIZE)*RNS.Identity.AES128_BLOCKSIZE - 1
|
MDU = math.floor((RNS.Reticulum.MTU-RNS.Reticulum.IFAC_MIN_SIZE-RNS.Reticulum.HEADER_MINSIZE-RNS.Identity.TOKEN_OVERHEAD)/RNS.Identity.AES128_BLOCKSIZE)*RNS.Identity.AES128_BLOCKSIZE - 1
|
||||||
|
|
||||||
ESTABLISHMENT_TIMEOUT_PER_HOP = RNS.Reticulum.DEFAULT_PER_HOP_TIMEOUT
|
ESTABLISHMENT_TIMEOUT_PER_HOP = RNS.Reticulum.DEFAULT_PER_HOP_TIMEOUT
|
||||||
"""
|
"""
|
||||||
@ -188,7 +188,7 @@ class Link:
|
|||||||
self.prv = X25519PrivateKey.generate()
|
self.prv = X25519PrivateKey.generate()
|
||||||
self.sig_prv = Ed25519PrivateKey.generate()
|
self.sig_prv = Ed25519PrivateKey.generate()
|
||||||
|
|
||||||
self.fernet = None
|
self.token = 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()
|
||||||
@ -979,14 +979,14 @@ class Link:
|
|||||||
|
|
||||||
def encrypt(self, plaintext):
|
def encrypt(self, plaintext):
|
||||||
try:
|
try:
|
||||||
if not self.fernet:
|
if not self.token:
|
||||||
try:
|
try:
|
||||||
self.fernet = Fernet(self.derived_key)
|
self.token = Token(self.derived_key)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not instantiate Fernet while performin encryption on link "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log("Could not instantiate token while performing encryption on link "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
return self.fernet.encrypt(plaintext)
|
return self.token.encrypt(plaintext)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Encryption on link "+str(self)+" failed. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log("Encryption on link "+str(self)+" failed. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
@ -995,10 +995,10 @@ class Link:
|
|||||||
|
|
||||||
def decrypt(self, ciphertext):
|
def decrypt(self, ciphertext):
|
||||||
try:
|
try:
|
||||||
if not self.fernet:
|
if not self.token:
|
||||||
self.fernet = Fernet(self.derived_key)
|
self.token = Token(self.derived_key)
|
||||||
|
|
||||||
return self.fernet.decrypt(ciphertext)
|
return self.token.decrypt(ciphertext)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Decryption failed on link "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log("Decryption failed on link "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
|
@ -95,7 +95,7 @@ class Packet:
|
|||||||
# With an MTU of 500, the maximum of data we can
|
# With an MTU of 500, the maximum of data we can
|
||||||
# send in a single encrypted packet is given by
|
# send in a single encrypted packet is given by
|
||||||
# the below calculation; 383 bytes.
|
# the below calculation; 383 bytes.
|
||||||
ENCRYPTED_MDU = math.floor((RNS.Reticulum.MDU-RNS.Identity.FERNET_OVERHEAD-RNS.Identity.KEYSIZE//16)/RNS.Identity.AES128_BLOCKSIZE)*RNS.Identity.AES128_BLOCKSIZE - 1
|
ENCRYPTED_MDU = math.floor((RNS.Reticulum.MDU-RNS.Identity.TOKEN_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
|
The maximum size of the payload data in a single encrypted packet
|
||||||
"""
|
"""
|
||||||
|
@ -868,13 +868,17 @@ both on general-purpose CPUs and on microcontrollers. The necessary primitives a
|
|||||||
|
|
||||||
* HKDF for key derivation
|
* HKDF for key derivation
|
||||||
|
|
||||||
* Modified Fernet for encrypted tokens
|
* Encrypted tokens are based on the Fernet spec
|
||||||
|
|
||||||
* AES-128 in CBC mode
|
* Ephemeral keys derived from an ECDH key exchange on Curve25519
|
||||||
|
|
||||||
* HMAC for message authentication
|
* AES-128 in CBC mode with PKCS7 padding
|
||||||
|
|
||||||
* No Version and Timestamp metadata included
|
* HMAC using SHA256 for message authentication
|
||||||
|
|
||||||
|
* IVs are generated through os.urandom()
|
||||||
|
|
||||||
|
* No Fernet version and timestamp metadata fields
|
||||||
|
|
||||||
* SHA-256
|
* SHA-256
|
||||||
|
|
||||||
@ -884,12 +888,12 @@ In the default installation configuration, the ``X25519``, ``Ed25519`` and ``AES
|
|||||||
primitives are provided by `OpenSSL <https://www.openssl.org/>`_ (via the `PyCA/cryptography <https://github.com/pyca/cryptography>`_
|
primitives are provided by `OpenSSL <https://www.openssl.org/>`_ (via the `PyCA/cryptography <https://github.com/pyca/cryptography>`_
|
||||||
package). The hashing functions ``SHA-256`` and ``SHA-512`` are provided by the standard
|
package). The hashing functions ``SHA-256`` and ``SHA-512`` are provided by the standard
|
||||||
Python `hashlib <https://docs.python.org/3/library/hashlib.html>`_. The ``HKDF``, ``HMAC``,
|
Python `hashlib <https://docs.python.org/3/library/hashlib.html>`_. The ``HKDF``, ``HMAC``,
|
||||||
``Fernet`` primitives, and the ``PKCS7`` padding function are always provided by the
|
``Token`` primitives, and the ``PKCS7`` padding function are always provided by the
|
||||||
following internal implementations:
|
following internal implementations:
|
||||||
|
|
||||||
- ``RNS/Cryptography/HKDF.py``
|
- ``RNS/Cryptography/HKDF.py``
|
||||||
- ``RNS/Cryptography/HMAC.py``
|
- ``RNS/Cryptography/HMAC.py``
|
||||||
- ``RNS/Cryptography/Fernet.py``
|
- ``RNS/Cryptography/Token.py``
|
||||||
- ``RNS/Cryptography/PKCS7.py``
|
- ``RNS/Cryptography/PKCS7.py``
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user