Skip to content

Latest commit

 

History

History
131 lines (104 loc) · 6.33 KB

encryption.md

File metadata and controls

131 lines (104 loc) · 6.33 KB

Encryption

Meld can authenticate and encrypt a point-to-point flow when both endpoints provide the same passphrase and security parameters. The session host owns cryptography; the coding core continues to process opaque source bytes.

The standalone specification defines the exact handshake, key labels, transcript, nonce, AAD, and control framing. wireformat.md summarizes the datagram layouts.

Construction

passphrase + salt --Argon2id--> PSK

two-message authenticated key exchange:
    ephemeral X25519
  + ephemeral ML-KEM-768
  + PSK
  + transcript-bound HKDF-SHA256

source record:
  ChaCha20-Poly1305(plaintext, nonce(epoch, source ID), AAD(flow, epoch, source ID))
  then systematic coding / repair

Default Argon2id parameters are 64 MiB, three iterations, and four lanes. The result is cached for the session rather than recomputed per handshake message. Deployments should use distinct salts and sufficiently strong passphrases; Argon2id raises the cost of an offline guess but does not turn a weak passphrase into a high-entropy key.

The handshake follows an NNpsk0-shaped transcript. The initiator and responder contribute fresh X25519 keys; ML-KEM-768 supplies the post-quantum component. Both shared secrets are mixed into the chaining key with successive HKDF steps. Public keys, the KEM ciphertext, the flow-specific prologue, and the sender's epoch size are included in the transcript. A PSK-derived mac1 rejects unauthenticated requests before expensive responder work. This is a custom composition, not the standard Noise NNpsk0 wire protocol; the framework and hybrid-handshake literature do not by themselves prove this exact construction secure.

Under configured load, the receiver may require a short-lived mac2 cookie bound to the peer address before processing a retry. CookieThreshold controls that gate; its default effectively disables cookies for normal point-to-point operation.

Encrypt then code

Each application chunk is sealed before it enters the erasure coder. The 16-byte Poly1305 tag is therefore part of the coded source symbol and can be reconstructed by a repair equation. Coding ciphertext does not require a traffic key, but arbitrary relay recombinations are not necessarily representable by Meld's finite repair-key family. The receiver decodes first and authenticates each recovered source symbol before delivering plaintext; pollution can affect decoder state before that check.

SymbolSize remains the maximum coded-source size, so an encrypted application chunk is limited to SymbolSize - 16 bytes. Oversized writes return ErrChunkTooLarge.

The nonce is deterministic and is not transmitted. Its significant components are the key epoch and source ID. A sealer requires strictly increasing source IDs and refuses reuse. The host derives the full key epoch from sourceID / EpochSize and ratchets the directional traffic secret at those intervals. The wire Epoch field remains reserved and zero. Protection of earlier traffic depends on which old secrets and master material are retained, not just on advancing the ratchet.

The authenticated data contains only values reconstructable after coding: flow ID, key epoch, and source ID. Priority, deadline, and frame metadata are not in the record AAD, because a recovered source symbol has no copy of its original wire header. They remain protocol inputs rather than cryptographically protected media metadata.

Control authentication

Encrypted sessions also authenticate feedback and clock messages. Each direction has a separate HMAC-SHA256 key. A control datagram carries a monotonic sequence number and a truncated tag; the receiver applies a 64-entry sliding replay window. Control messages are suppressed until the handshake establishes these keys. The reference counter has no exhaustion check: an application must replace the session before its uint64 control sequence wraps. Source-ID exhaustion is checked separately by the encrypted sender.

Handshake messages and cookie replies retain their own framing and authentication rules.

Re-handshake behavior

The receiver does not replace a live session merely because it receives a new handshake request. It keeps the candidate session pending until a systematic symbol authenticates under the candidate keys, then promotes it and rebuilds the receive core. For 500 ms a guard rejects old-session systematics that can be trial-authenticated; it does not authenticate equations or systematics outside its trial epoch range. This permits sender restart without letting a replayed first handshake message displace working keys.

Configuration

Public meld.Config exposes:

  • Passphrase and Salt;
  • Argon2Time, Argon2MemoryKiB, and Argon2Threads;
  • EpochSize;
  • CookieThreshold.

An empty passphrase selects cleartext operation. Both endpoints must agree on the passphrase, salt, and effective Argon2id parameters. The sender carries its epoch size in the authenticated handshake, so the receiver adopts the sender's value.

Security scope and limitations

  • The design is for provisioned point-to-point links. It does not provide group keying, anonymity, or metadata confidentiality.
  • Authentication is passphrase-based; there are no separate long-term host identities or certificates.
  • A human-strength passphrase remains subject to offline guessing. The protocol does not implement a PAKE or online lockout policy.
  • Coding headers are visible. Flow identity is record-authenticated, but priority, deadlines, frame descriptors, and repair headers are not individually authenticated.
  • Corrupted repair can poison a decode, but the recovered source then fails its AEAD tag and is not delivered. There is no per-hop homomorphic pollution check.
  • Traffic analysis can reveal packet sizes, timing, coding windows, and priority classes.
  • Generation-mode ShedTopLayerOverBudget can drop a chunk after the host has advanced its encryption source ID, while the coder does not advance its ID. Subsequent source authentication then fails. This optional combination is disabled by default; the spec includes a deterministic trace.

Primitive references

  • Argon2id: RFC 9106
  • HKDF-SHA256: RFC 5869
  • X25519: RFC 7748
  • ML-KEM-768: FIPS 203
  • ChaCha20-Poly1305: RFC 8439
  • Noise protocol framework, revision 34
  • PQNoise hybrid-handshake analysis, CCS 2022
  • Sliding anti-replay window: RFC 6479