Refactored fernet to token

This commit is contained in:
Mark Qvist 2024-11-22 15:19:12 +01:00
parent 04d2626809
commit aabb763cea
8 changed files with 38 additions and 34 deletions

View File

@ -325,12 +325,12 @@ In the default installation configuration, the `X25519`, `Ed25519` and
(via the [PyCA/cryptography](https://github.com/pyca/cryptography) 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`, `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:
- [HKDF.py](RNS/Cryptography/HKDF.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)

View File

@ -27,7 +27,7 @@ from RNS.Cryptography import HMAC
from RNS.Cryptography import PKCS7
from RNS.Cryptography.AES import AES_128_CBC
class Fernet():
class Token():
"""
This class provides a slightly modified implementation of the Fernet spec
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
implementation, since they incur overhead and leak initiator metadata.
"""
FERNET_OVERHEAD = 48 # Bytes
TOKEN_OVERHEAD = 48 # Bytes
@staticmethod
def generate_key():

View File

@ -5,7 +5,7 @@ from .Hashes import sha256
from .Hashes import sha512
from .HKDF import hkdf
from .PKCS7 import PKCS7
from .Fernet import Fernet
from .Token import Token
from .Provider import backend
import RNS.Cryptography.Provider as cp

View File

@ -26,7 +26,7 @@ import time
import threading
import RNS
from RNS.Cryptography import Fernet
from RNS.Cryptography import Token
from .vendor import umsgpack as umsgpack
class Callbacks:
@ -525,8 +525,8 @@ class Destination:
raise TypeError("A single destination holds keys through an Identity instance")
if self.type == Destination.GROUP:
self.prv_bytes = Fernet.generate_key()
self.prv = Fernet(self.prv_bytes)
self.prv_bytes = Token.generate_key()
self.prv = Token(self.prv_bytes)
def get_private_key(self):
"""
@ -556,7 +556,7 @@ class Destination:
if self.type == Destination.GROUP:
self.prv_bytes = key
self.prv = Fernet(self.prv_bytes)
self.prv = Token(self.prv_bytes)
def load_public_key(self, key):
if self.type != Destination.SINGLE:

View File

@ -31,7 +31,7 @@ import threading
from .vendor import umsgpack as umsgpack
from RNS.Cryptography import X25519PrivateKey, X25519PublicKey, Ed25519PrivateKey, Ed25519PublicKey
from RNS.Cryptography import Fernet
from RNS.Cryptography import Token
class Identity:
@ -66,7 +66,7 @@ class Identity:
"""
# Non-configurable constants
FERNET_OVERHEAD = RNS.Cryptography.Fernet.FERNET_OVERHEAD
TOKEN_OVERHEAD = RNS.Cryptography.Token.TOKEN_OVERHEAD
AES128_BLOCKSIZE = 16 # In bytes
HASHLENGTH = 256 # In bits
SIGLENGTH = KEYSIZE # In bits
@ -646,8 +646,8 @@ class Identity:
context=self.get_context(),
)
fernet = Fernet(derived_key)
ciphertext = fernet.encrypt(plaintext)
token = Token(derived_key)
ciphertext = token.encrypt(plaintext)
token = ephemeral_pub_bytes+ciphertext
return token
@ -684,8 +684,8 @@ class Identity:
context=self.get_context(),
)
fernet = Fernet(derived_key)
plaintext = fernet.decrypt(ciphertext)
token = Token(derived_key)
plaintext = token.decrypt(ciphertext)
if ratchet_id_receiver:
ratchet_id_receiver.latest_ratchet_id = ratchet_id
@ -709,8 +709,8 @@ class Identity:
context=self.get_context(),
)
fernet = Fernet(derived_key)
plaintext = fernet.decrypt(ciphertext)
token = Token(derived_key)
plaintext = token.decrypt(ciphertext)
if ratchet_id_receiver:
ratchet_id_receiver.latest_ratchet_id = None

View File

@ -21,7 +21,7 @@
# SOFTWARE.
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 time import sleep
@ -61,7 +61,7 @@ class Link:
ECPUBSIZE = 32+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
"""
@ -188,7 +188,7 @@ class Link:
self.prv = X25519PrivateKey.generate()
self.sig_prv = Ed25519PrivateKey.generate()
self.fernet = None
self.token = None
self.pub = self.prv.public_key()
self.pub_bytes = self.pub.public_bytes()
@ -979,14 +979,14 @@ class Link:
def encrypt(self, plaintext):
try:
if not self.fernet:
if not self.token:
try:
self.fernet = Fernet(self.derived_key)
self.token = Token(self.derived_key)
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
return self.fernet.encrypt(plaintext)
return self.token.encrypt(plaintext)
except Exception as e:
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):
try:
if not self.fernet:
self.fernet = Fernet(self.derived_key)
if not self.token:
self.token = Token(self.derived_key)
return self.fernet.decrypt(ciphertext)
return self.token.decrypt(ciphertext)
except Exception as e:
RNS.log("Decryption failed on link "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)

View File

@ -95,7 +95,7 @@ class Packet:
# With an MTU of 500, the maximum of data we can
# send in a single encrypted packet is given by
# 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
"""

View File

@ -868,13 +868,17 @@ both on general-purpose CPUs and on microcontrollers. The necessary primitives a
* 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
@ -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>`_
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``,
``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:
- ``RNS/Cryptography/HKDF.py``
- ``RNS/Cryptography/HMAC.py``
- ``RNS/Cryptography/Fernet.py``
- ``RNS/Cryptography/Token.py``
- ``RNS/Cryptography/PKCS7.py``