morf

Crates.iomorf
lib.rsmorf
version0.2.1
sourcesrc
created_at2024-01-14 12:03:33.985623
updated_at2024-08-08 11:54:52.868048
descriptionSimple authenticated encryption layer over RF
homepage
repository
max_upload_size
id1099385
size30,103
Heyang Zhou (losfair)

documentation

README

MoRF

MoRF is a mutually-authenticated, encrypted communication protocol over lossy packet links with small MTUs, e.g. LoRa. Inspired by Noise.

  • no_std compatible, no dynamic memory allocation
  • Minimum supported MTU: 49 bytes, overhead per data packet: 19 bytes
  • Primitives: X25519 + BLAKE3 + ChaCha20-Poly1305
  • Identity hiding, forward secrecy, replay protection

Handshake

To establish an encrypted session, a client initiates a handshake to a server to exchange keys. Both peers are required to have ahead-of-time knowledge of each other's public key.

Notations

  • $CE_{pub}$, $CE_{sec}$: Client ephemeral X25519 public/secret key
  • $SE_{pub}$, $SE_{sec}$: Server ephemeral X25519 public/secret key
  • $CS_{pub}$, $CS_{sec}$: Client static X25519 public/secret key
  • $SS_{pub}$, $SS_{sec}$: Server static X25519 public/secret key
  • $X25519(secret, public)$: X25519 Diffie-Hellman key agreement
  • $ChaCha20(key, payload)$: Apply (unauthenticated) ChaCha20 keystream derived from $key$ to $payload$
  • $Mac(key, payload)$: Apply BLAKE3 keyed hash with $key$ to $payload$, and truncate the output to the first 16 bytes.
  • $DeriveKey(key, info)$: Derive a 32-byte subkey from $key$ using BLAKE3 as a KDF with $info$ as the info string
  • $Hash(payload)$: Calculate the BLAKE3 hash of $payload$ and truncate the output to the first 16 bytes.
  • $InitialEncryptionKeyInfo$: The string initial_encryption_key
  • $ServerEphemeralPublicKeyMacKeyInfo$: The string server_ephemeral_public_key_mac_key

Packet 1: client to server (49 bytes)

Let $InitialKey = DeriveKey(X25519(CE_{sec}, SS_{pub}), InitialEncryptionKeyInfo)$.

Field Length
$Const(3)$ 1
$CE_{pub}$ 32
$ChaCha20(InitialKey, Hash(CS_{pub}))$ 16

Packet 2: server to client (49 bytes)

Lookup client static public key $CS_{pub}$ from the provided hash.

Let $ServerSepkMacKey = DeriveKey(X25519(SS_{sec}, CE_{pub}), ServerEphemeralPublicKeyMacKeyInfo)$.

Let $ServerSessionKey = Concat(X25519(SE_{sec}, CS_{pub}), X25519(SE_{sec}, CE_{pub}))$.

Field Length
$Const(1)$ 1
$SE_{pub}$ 32
$Mac(ServerSepkMacKey, SE_{pub})$ 16

Finalize (client)

Let $ClientSepkMacKey = DeriveKey(X25519(CE_{sec}, SS_{pub}), ServerEphemeralPublicKeyMacKeyInfo)$.

Check that:

$Mac(ClientSepkMacKey, Packet2[1:33]) == Packet2[33:49]$

Let $ClientSessionKey = Concat(X25519(CS_{sec}, SE_{pub}), X25519(CE_{sec}, SE_{pub}))$.

Commit count: 0

cargo fmt