2 releases

0.2.1 Aug 8, 2024
0.2.0 Jan 27, 2024
0.1.0 Jan 14, 2024

#821 in Cryptography

Download history 4/week @ 2024-07-24 3/week @ 2024-07-31 266/week @ 2024-08-07 127/week @ 2024-08-14 21/week @ 2024-08-21 104/week @ 2024-08-28 190/week @ 2024-09-04 195/week @ 2024-09-11 101/week @ 2024-09-18 118/week @ 2024-09-25 160/week @ 2024-10-02 254/week @ 2024-10-09 80/week @ 2024-10-16 82/week @ 2024-10-23 116/week @ 2024-10-30 61/week @ 2024-11-06

362 downloads per month
Used in morf-mqtt-bridge

Apache-2.0

19KB
331 lines

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}))$.

Dependencies

~4.5MB
~100K SLoC