# Celld Fleet Communication Security Model: A Technical Deep Dive

> Discover the Celld fleet communication security model. Learn about its Zero-Trust, mutual-authentication approach using Ed25519 keys, Noise XK, and AEAD encryption for robust protection.

- Repository: [Deno/celld](https://github.com/denoland/celld)
- Tags: deep-dive
- Published: 2026-08-15

---

**Celld operates on a Zero-Trust, mutual-authentication security model built on Ed25519 identity keys, Noise XK handshake, and AEAD encryption with token-based revocation.**

This article explains how the `denoland/celld` distributed system protects inter-node communication. The security architecture ensures that every fleet member cryptographically proves its identity before exchanging data, with no implicit trust granted based on network location.

## Zero-Trust Foundations

Celld rejects perimeter-based security. Every cell—the fundamental unit in a celld fleet—mustauthenticate itself to every peer it contacts. The model rests on three pillars: **persistent identity**, **short-lived authorization**, and **session-based encryption**.

The threat model assumes compromised nodes, passive eavesdroppers, and active man-in-the-middle attackers. Countermeasures are enforced at the protocol layer, making them independent of transport mechanism.

## Identity: Ed25519 Long-Term Keys

Each cell generates a persistent **Ed25519 key pair** during initialization. These keys serve as the cell's identity throughout its lifecycle.

In [`crates/celld/peer_auth.rs`](https://github.com/denoland/celld/blob/main/crates/celld/peer_auth.rs), the `PeerAuth` struct loads and manages these keys:

```rust
// crates/celld/peer_auth.rs
pub struct PeerAuth {
    key_pair: Ed25519KeyPair,
    public_key: PublicKey,
}

```

The private key never leaves the node. The public key is registered with the fleet leader to establish initial trust.

### Key Generation Example

```ts
// Deno/TypeScript using the Web Crypto API
const keyPair = await crypto.subtle.generateKey(
  { name: "ED25519", namedCurve: "ED25519" },
  true,
  ["sign", "verify"],
);
await Deno.writeTextFile("node_private.key", 
  await crypto.subtle.exportKey("pkcs8", keyPair.privateKey));
await Deno.writeTextFile("node_public.key", 
  await crypto.subtle.exportKey("spki", keyPair.publicKey));

```

## Authorization: Leader-Signed Peer Tokens

Authorization in celld's security model uses **time-bound, cryptographically signed tokens**. When a node joins the fleet, the leader inspects its public key and issues a `PeerToken` if the node is permitted access.

The token structure is defined in [`crates/celld/peer.rs`](https://github.com/denoland/celld/blob/main/crates/celld/peer.rs):

```rust
// crates/celld/peer.rs
pub struct PeerToken {
    pub payload: PeerTokenPayload,
    pub signature: Signature,
}

pub struct PeerTokenPayload {
    pub pub_key: PublicKey,
    pub expires: SystemTime,
}

```

Token creation in [`peer_auth.rs`](https://github.com/denoland/celld/blob/main/peer_auth.rs) binds the peer's public key to an expiration timestamp:

```rust
// crates/celld/peer_auth.rs (simplified)
pub fn sign_peer_token(
    priv_key: &Ed25519KeyPair,
    peer_pub: &PublicKey,
    expires: SystemTime,
) -> PeerToken {
    let payload = PeerTokenPayload {
        pub_key: peer_pub.clone(),
        expires,
    };
    let sig = priv_key.sign(&bincode::serialize(&payload).unwrap());
    PeerToken { payload, signature: sig }
}

```

The leader's signature proves token authenticity. The expiration limits the window of compromise if a token is exfiltrated.

## Key Exchange: Noise XK Handshake

Celld implements the **Noise XK pattern** for authenticated key exchange. This pattern provides:

- **Mutual authentication**: Both peers verify each other's identity
- **Forward secrecy**: Session keys cannot be recovered from long-term keys
- **Noise properties**: No unauthenticated cleartext, identity hiding for the initiator

The handshake executes in [`crates/logic/peer.rs`](https://github.com/denoland/celld/blob/main/crates/logic/peer.rs):

```rust
// crates/logic/peer.rs (excerpt)
let mut handshake = NoiseHandshake::new_xk(
    &local_static_key,
    &remote_static_key, // from PeerToken
    &mut rng,
);
let msg1 = handshake.write_message(&[])?; // first handshake message
socket.send(msg1).await?;
let msg2 = socket.recv().await?;
handshake.read_message(&msg2)?;
let (cipher, _handshake_state) = handshake.into_transport_mode()?;

```

XK pattern specifics:
- **X**: Static key transmitted to initiator (leader knows peer's key from token)
- **K**: Responder knows initiator's static key in advance

After `into_transport_mode()`, all communication uses the derived session keys.

## Encryption: ChaCha20-Poly1305 AEAD

Transport-layer security in celld uses **ChaCha20-Poly1305 AEAD** for every frame. This provides:

- **Confidentiality**: 256-bit symmetric encryption
- **Integrity**: 128-bit authentication tag
- **Replay protection**: Sequential nonces derived from session state

The implementation lives in [`crates/celld/protocol.rs`](https://github.com/denoland/celld/blob/main/crates/celld/protocol.rs). Each encrypted frame includes a nonce, ciphertext, and authentication tag. The nonce space is partitioned to prevent collisions between sender and receiver.

## Revocation and Lifecycle Management

Fleet-wide security policies are enforced through the **ownership store**. The leader maintains the [`ownership_store.rs`](https://github.com/denoland/celld/blob/main/ownership_store.rs) registry of authorized peers:

```rust
// crates/celld/ownership_store.rs (simplified)
pub fn is_authorised(&self, peer_id: &PeerId) -> bool {
    self.active_peers.contains_key(peer_id)
}

pub fn revoke(&mut self, peer_id: &PeerId) {
    self.active_peers.remove(peer_id);
}

```

When `revoke()` removes a peer, all active connections to that peer are terminated. The cryptographic binding of session keys to the revoked identity prevents reconnection without a fresh, valid token.

## Transport Agnosticism

The celld security model operates over any reliable byte stream. The same handshake and encryption layer functions identically across:

- WebSockets
- HTTP/2 streams
- Raw TCP connections

This is enabled by the abstraction in [`crates/celld/runtime.rs`](https://github.com/denoland/celld/blob/main/crates/celld/runtime.rs), which wires the security layer into the chosen transport without protocol modification.

## Security Guarantees Summary

| Property | Mechanism | Source File |
|----------|-----------|-------------|
| Identity authenticity | Ed25519 signatures | [`peer_auth.rs`](https://github.com/denoland/celld/blob/main/peer_auth.rs) |
| Authorization validity | Leader-signed `PeerToken` with expiration | [`peer.rs`](https://github.com/denoland/celld/blob/main/peer.rs) |
| Session key establishment | Noise XK handshake (Curve25519 ECDH) | [`logic/peer.rs`](https://github.com/denoland/celld/blob/main/logic/peer.rs) |
| Data confidentiality | ChaCha20-Poly1305 AEAD | [`protocol.rs`](https://github.com/denoland/celld/blob/main/protocol.rs) |
| Peer eviction | `ownership_store` removal + connection drop | [`ownership_store.rs`](https://github.com/denoland/celld/blob/main/ownership_store.rs) |

## Summary

- **Zero-Trust architecture**: No implicit trust based on network position; every peer cryptographically authenticates
- **Ed25519 identity keys**: Long-term, persistent node identifiers stored in [`peer_auth.rs`](https://github.com/denoland/celld/blob/main/peer_auth.rs)
- **Token-based authorization**: Leader-issued, time-bound `PeerToken` grants fleet membership
- **Noise XK handshake**: Mutual authentication with forward secrecy via Curve25519 ECDH
- **AEAD encryption**: ChaCha20-Poly1305 protects all transported data with integrity and replay resistance
- **Immediate revocation**: Leader-controlled `ownership_store` enables instant peer removal

## Frequently Asked Questions

### How does celld prevent a compromised node from impersonating others?

**Each node's identity is tied to its private Ed25519 key, which never leaves the node.** The Noise XK handshake requires proof of possession of this key. A compromised node can only impersonate itself—it cannot forge signatures for other nodes' public keys. The protocol binding in [`logic/peer.rs`](https://github.com/denoland/celld/blob/main/logic/peer.rs) cryptographically locks sessions to the proven identity.

### What happens when a node fails to present a valid peer token?

**The Noise handshake aborts before any application data flows.** The initiator sends its static key and token signature in the first message; the responder verifies the leader's signature on the token and checks expiration. If verification fails, the handshake state machine in [`logic/peer.rs`](https://github.com/denoland/celld/blob/main/logic/peer.rs) returns an error and the underlying connection closes.

### Can the leader read all fleet communication?

**No.** The leader signs authorization tokens but does not possess session keys. The Noise XK handshake derives shared secrets directly between communicating peers using ephemeral Curve25519 key exchanges. The leader's role is limited to identity verification and access control, not traffic decryption.

### How does celld handle token expiration during long-lived connections?

**Session keys outlive tokens but new connections require fresh tokens.** The AEAD session established by the Noise handshake remains valid indefinitely for that specific connection pair. However, if the connection drops and reconnection is attempted, the peer must present a current, unexpired token. This balances operational continuity with revocation granularity.