For the complete documentation index, see llms.txt. This page is also available as Markdown.

Trust & Threat Model

The DeRec protocol provides security guarantees under explicitly defined trust and threat assumptions. This page clarifies what the system protects against, what assumptions must hold, and what falls outside the protocol’s guarantees.

Security Objective

The primary security objective of DeRec is to ensure that the Secret can only be reconstructed from the Helper set when a defined threshold t of independent Helpers participate in the recovery process. The protocol prevents unilateral recovery by any single Helper and prevents recovery when fewer than the threshold number of Helpers cooperate.

The protocol does not attempt to eliminate trust entirely. Instead, it minimizes and isolates trust boundaries.

Trust Assumptions

DeRec relies on the following assumptions.

Trusted Owner Identity

The Owner environment is assumed to be trusted during:

  • Secret creation

  • Share generation

  • Recovery and reconstruction

When the Owner identity spans multiple devices via the replica feature, every Replica device is part of the same trust boundary as the Owner. The protocol does not separate them cryptographically — a Replica device holds the full Secret and can act on behalf of the Owner identity in full. Compromise of any device under the Owner identity is treated as compromise of the Owner.

Helper Independence

Security depends on Helper independence. Helpers are assumed to operate independently and not collude beyond the configured threshold.

If fewer than the threshold number of Helpers collude, the Secret remains protected. If at least the threshold number collude and combine their shares, reconstruction becomes possible.

Correct Cryptographic Implementation

The security guarantees assume that:

  • Secret-sharing algorithms are correctly implemented

  • Secure communication channels are correctly established

  • Protocol validation rules are enforced. Implementation flaws can invalidate protocol guarantees.

Adversarial Model

The protocol protects against the following adversarial scenarios.

  • Single Helper Compromise — If one Helper is compromised, the attacker gains access to only a single share. A single share is insufficient to reconstruct the Secret.

  • Partial Helper Compromise — If fewer than the threshold number of Helpers are compromised, reconstruction remains impossible.

  • Network Interception — Every protocol message is encrypted under per-channel Shared Keys. Interception of protocol communication does not reveal the Secret or any share material; only message metadata is exposed on insecure transport. See the network trust boundary note at the bottom of this page.

  • Helper Unavailability — If some Helpers are offline but at least the threshold number remain available, recovery remains possible.

  • Malicious Helper Behavior — A Helper may attempt to return invalid or manipulated shares. The protocol mitigates this through share commitments and verification mechanisms that allow the requester (the Owner, or any Replica acting on its behalf) to detect incorrect shares during recovery.

Out-of-Scope Threats

The following scenarios fall outside the protocol’s security guarantees.

  • Threshold-Level Collusion — If the threshold number (or more) of Helpers collude and combine shares, the Secret can be reconstructed.

  • Compromised Owner or Replica at Recovery — If any device under the Owner identity is compromised during recovery, the Secret may be exposed after reconstruction.

  • Compromised Owner Before Protection — If the Secret is compromised before share distribution begins, the protocol cannot provide protection.

  • Replica Compromise — A compromised Replica device holds the full Secret and the per-Helper Shared Keys. It can impersonate the Owner toward every Helper and read every user secret. See Recovery transitivity for the full discussion.

  • Improper Threshold Configuration — If the threshold is set too low relative to Helper trust assumptions, security is weakened by configuration, not protocol failure.

  • Cryptographic Breakthroughs — The protocol assumes the continued security of underlying cryptographic primitives.

  • Resource Exhaustion Against Helpers — The protocol imposes no share size, storage quota, or update-rate limit. A paired Owner can push shares of any size as often as it likes; bounding that is the Helper application's job. See Helper admission control.

Helper admission control

A Helper's only admission-control point for inbound shares is the decision to accept a StoreShareRequestMessage. The protocol enforces no limit of its own:

  • ParameterRange.maxShareSize is checked for range overlap between the two peers at pairing time only. It is never compared against an actual share.

  • With AutoAcceptPolicy.store_share off (the default), every inbound share surfaces as ActionRequired carrying PendingAction::StoreShare with the decoded request; the FFI and WASM bindings also expose its size as share_size. The application calls accept, or reject(action, status, memo) with SizeLimitExceeded, TooFrequent, or Rejected. The Owner sees the refusal as ShareRejected.

  • With AutoAcceptPolicy.store_share on, process stores every share from every paired Owner unconditionally, at whatever size it arrives. Keep it off in any deployment with per-user storage limits.

This is storage policy, not denial-of-service protection: by the time ActionRequired fires, the message has already been received, decrypted, and parsed. Bound inbound message size at the transport layer. See AutoAcceptPolicy.

Trust Boundary Summary

Component
Trusted For
Not Protected Against

Owner

Secret lifecycle and reconstruction

Owner compromise during recovery

Replica

Same as Owner — full Secret, full authority on its behalf

Compromise of any device under the Owner identity

Helper

Storage and return of one share

Collusion at or above threshold

Network

Delivery of protocol messages

Out-of-band ContactMessage exposure; metadata leakage (*)

(*) Network Trust Boundary

Outside of the initial ContactMessage transmission in the Pairing flow, the protocol is designed to not need a secure communication channel. Every message is encrypted under a pre-established Shared Key and wrapped in a DeRecEnvelope. When transmitted over an insecure channel, only message metadata is exposed.

How much the ContactMessage itself must be protected depends on the contact mode it was created with:

  • InlineKeys / HashedKeys — the out-of-band channel needs only integrity. In HashedKeys mode the contact carries a hash that binds the encryption keys, so a man-in-the-middle on the (plaintext) PrePair exchange cannot substitute its own keys without detection.

  • NoKeys — the contact carries no key material and no binding hash; the creator generates keys on the fly for whoever presents a matching nonce. The contact commits to nothing, so substitution is detected after the handshake rather than during it. The protocol holds a NoKeys channel in ChannelStatus::Pending until both sides compare the human-readable fingerprint derived from the established shared key. A man-in-the-middle ends up holding a different shared key with each side, so the two sides derive different fingerprints and the comparison fails — this is what HashedKeys gets from its binding hash, and what NoKeys can get no other way. The out-of-band channel still needs to be authentic enough that the contact reached the intended party, and an application offering NoKeys must rate-limit inbound PrePairRequests and expire outstanding contacts on a short timer; otherwise a NoKeys contact is a key-minting oracle for any caller that guesses or replays the nonce. See Fingerprint cross-confirmation.

The fingerprint gate applies to every replica pairing as well, whatever the contact mode — a replica receives the full Secret on its first sync, so no threshold bounds the damage of admitting the wrong peer.

Regardless of mode, the channel identifier in the ContactMessage only bootstraps pairing. The instant the handshake completes, both parties rotate to a long-term channel id derived from the pairing shared key (SHA-384(originalChannelId || sharedKey)); it travels once, encrypted inside the pairing envelope, so a passive observer of the contact or the pre-rekey traffic cannot link the exposed contact-time id to the long-running session. This is an unlinkability property that bounds what a leaked ContactMessage reveals — it does not replace the per-mode key trust above, since an active man-in-the-middle that completes the handshake derives the same shared key.

Security advisories

Fixed defects in the reference library that affect the guarantees above. Each fix is wire-compatible: patched and unpatched peers interoperate.

0.0.6 — channel messages reused one AES-GCM nonce

Before 0.0.6, every message on a channel was encrypted under the channel's long-lived shared key with the same all-zero 96-bit nonce. Under AES-GCM, nonce reuse is catastrophic: an eavesdropper learns the XOR of any two plaintexts, and can recover the authentication key and forge messages that pass the tag check.

Since 0.0.6, every channel message draws a fresh random 96-bit nonce. Receivers have always read the nonce from the first 12 bytes of the ciphertext, so old and new peers interoperate in both directions.

0.0.6 — replica destinations acted on unconfirmed channels

Before 0.0.6, the fingerprint gate on Pending channels checked helper records only. A replica destination that had not yet confirmed the fingerprint still accepted the source's first copy: it wrote the roster, the Helper keys, and the share map, and acknowledged Ok. The man-in-the-middle check therefore ran after the fact.

Since 0.0.6, a message on a channel with a Pending replica member is dropped like one on a Pending helper channel and reported as MessageIgnored with reason PendingVerification. The dropped copy is not replayed after confirmation; the destination pulls it with ReplicaDiscovery.

0.0.8 — randomness was not fork-safe

Before 0.0.8, nonces, seeds, and random ids were drawn from a thread-local generator that is not reseeded after fork(). A child process continued its parent's sequence, so two processes on one channel could encrypt with the same AES-GCM nonce and key.

Since 0.0.8, every random value is drawn directly from the operating system's generator, with nothing buffered in the process: channel message nonces, the pairing envelope nonce and one-time key, contact nonces, verification challenge nonces, generated channel and replica ids, trace_id, and the 32-byte seeds behind key generation and secret splitting. A forked process never repeats its parent's values.

Last updated