# Filie Protocol

This is the public specification for Filie's application-layer transfer protocol
and cryptographic design. Filie uses open, documented control messages and
standard cryptographic primitives to protect file transfers without depending on
the secrecy of the protocol itself.

The specification covers the wire-visible protocol, key agreement, key
derivation, authenticated encryption, and security boundaries. Local storage
policy, UI behavior, service deployment, transfer retention, and operational
tuning are implementation profiles layered on top of the core protocol.

## Goals

Filie follows a zero-trust computing model for transfer infrastructure: the
network, relay services, and object storage are treated as untrusted. File
contents are encrypted on the sending device and decrypted only on the receiving
device. The shared encryption secret is derived locally by the participating
devices and is never transmitted over the wire or stored by Filie
infrastructure. Filie infrastructure does not know, and cannot derive, the
contents of encrypted chunks.

The protocol is designed to provide:

- End-to-end confidentiality for file contents.
- Authentication of device announcements and transfer intents.
- Bounded exposure when short-term key material is retained for offline or
  delayed delivery.
- Independent encryption of file chunks.
- Operation over LAN paths and cloud-assisted relay/storage paths.

The protocol does not attempt to protect plaintext from a device that is already
compromised before encryption or after decryption.

## Terminology

- **Device identity key**: A long-term Ed25519 signing key generated on a
  device. It identifies and authenticates the device.
- **Ephemeral agreement key**: A short-term X25519 key used for key agreement.
- **Shared secret**: The output of X25519 key agreement between the sender and
  receiver ephemeral keys.
- **Transfer key**: A symmetric key derived from the shared secret for a
  specific transfer context.
- **Chunk**: A contiguous segment of a file encrypted independently under the
  transfer key.
- **Relay**: Any service used for coordination, presence, transfer state,
  metadata delivery, or encrypted chunk storage.

## Cryptographic Primitives

The current protocol profile uses:

- Ed25519 for device identity signatures.
- X25519 for ephemeral Diffie-Hellman key agreement.
- HKDF-HMAC-SHA-256 for key derivation.
- AES-256-GCM for authenticated encryption.
- Random AEAD nonces generated by the encryption library.
- Base64url without padding for public keys, nonces, and signatures in JSON.

All private keys and symmetric keys are generated and used on client devices.
Relay services receive public keys, signed envelopes, transfer state, and
encrypted chunks, but not private keys, shared secrets, transfer keys, or
plaintext.

## Device Identity

Each device generates an Ed25519 identity keypair:

```text
ID_priv, ID_pub = Ed25519.Generate()
```

`ID_priv` remains local to the device. `ID_pub` is included in signed device
announcements and transfer messages. Identity keys are used for signatures only;
they are not used directly as encryption keys or key-agreement keys.

## Ephemeral Agreement Keys

Each device maintains a short-term X25519 keypair:

```text
E_priv, E_pub = X25519.Generate()
```

The public key `E_pub` may be advertised through LAN discovery or cloud device
registration. The private key `E_priv` remains local.

Ephemeral key rotation and retention are protocol profile parameters. A Filie
implementation may retain a bounded history of recent ephemeral private keys so
that delayed transfers encrypted for a recently advertised public key can still
be received. The exact retention window is not part of the core wire protocol.
Deployments should document their chosen retention profile separately.

## Signed Device Envelope

Devices advertise identity and agreement material with signed envelopes. The
signature binds the device identity to the advertised ephemeral key and a fresh
nonce.

WAN/cloud device envelope:

```json
{
  "hdr": {
    "nonce": "BASE64URL(16 random bytes)",
    "sig": "BASE64URL(Ed25519 signature)"
  },
  "body": {
    "device": {
      "id": "device identifier",
      "name": "device display name",
      "platform": "platform identifier",
      "identity": "BASE64URL(Ed25519 public key)"
    },
    "wan": {
      "ephemeral": "BASE64URL(X25519 public key)"
    },
    "discovery": {
      "ttl": 300
    }
  }
}
```

The WAN signature payload is the following fixed-field JSON string:

```json
{"id":"...","name":"...","platform":"...","identity":"...","wan_ephemeral":"...","nonce":"..."}
```

LAN discovery uses the same structure with a `lan` object:

```json
{
  "msg": "device",
  "ver": 1,
  "hdr": {
    "ask": true,
    "nonce": "BASE64URL(16 random bytes)",
    "sig": "BASE64URL(Ed25519 signature)"
  },
  "body": {
    "device": {
      "id": "device identifier",
      "name": "device display name",
      "platform": "platform identifier",
      "identity": "BASE64URL(Ed25519 public key)"
    },
    "lan": {
      "port": 28073,
      "ephemeral": "BASE64URL(X25519 public key)"
    },
    "discovery": {
      "timestamp": 1714000000,
      "ttl": 300
    }
  }
}
```

The LAN signature payload is the following fixed-field JSON string:

```json
{"id":"...","name":"...","platform":"...","identity":"...","lan_ephemeral":"...","nonce":"..."}
```

Receivers verify the Ed25519 signature before trusting the advertised identity
and ephemeral key. Unknown fields are ignored unless they are required by a
negotiated future capability.

## Shared Secret Derivation

For a transfer between device A and device B:

```text
secret_A = X25519(A_E_priv, B_E_pub)
secret_B = X25519(B_E_priv, A_E_pub)
```

Both devices derive the same shared secret without transmitting it.

The shared secret is then bound to the transfer context with HKDF. Current
profiles use:

```text
lan_file_key   = HKDF-SHA256(shared_secret, info = "filie-file", length = 32)
cloud_file_key = HKDF-SHA256(shared_secret,
                             info = "filie-cloud-transfer:" || transfer_id,
                             length = 32)
```

Future profiles may derive separate metadata, file, and chunk keys from an
intermediate session key:

```text
session_key = HKDF-SHA256(shared_secret, info = "filie-session", length = 32)
file_key    = HKDF-SHA256(session_key, info = "filie-file", length = 32)
meta_key    = HKDF-SHA256(session_key, info = "filie-meta", length = 32)
```

Key-derivation labels are part of the protocol profile and must not be reused
for unrelated purposes.

## Chunk Encryption

Files are split into chunks. Each chunk is encrypted independently with
AES-256-GCM:

```text
box_i = AES-256-GCM-Encrypt(file_key, plaintext_chunk_i)
```

The serialized encrypted box is:

```text
nonce || ciphertext || tag
```

The nonce is included with each encrypted chunk. Receivers reconstruct the AEAD
box, authenticate it, and reject the transfer if authentication fails.

Chunk size and upload/download parallelism are implementation tunables. Changing
chunk size does not change the cryptographic model as long as each chunk is
authenticated and encrypted independently.

## LAN Transfer Profile

LAN discovery uses multicast to advertise signed device envelopes. The current
LAN profile uses:

```text
IPv4 multicast: 239.0.19.69:25077
IPv6 multicast: ff02::1969:25077
Default local HTTP transfer port: 28073
```

The receiver exposes a local HTTP endpoint:

- `GET /device`: returns the receiver device and LAN public agreement key.
- `POST /accept`: receives a signed transfer intent and prompts for local user
  approval.
- `POST /upload`: receives encrypted chunk frames for one file.
- `POST /done`: ends the accepted sender session.

The `/accept` body includes the sender signed envelope plus transfer summary:

```json
{
  "hdr": {
    "nonce": "...",
    "sig": "..."
  },
  "body": {
    "device": {
      "id": "...",
      "name": "...",
      "platform": "...",
      "identity": "..."
    },
    "lan": {
      "ephemeral": "..."
    },
    "transfer": {
      "description": "10 photos",
      "file_count": 10,
      "total_bytes": 1048576
    }
  }
}
```

For `/upload`, each encrypted chunk frame is serialized as:

```text
clear_len_u32_be || box_len_u32_be || aes_gcm_box
```

The request includes:

```text
X-Filie-Sender-Id: sender device id
X-Filie-Filename: base64url(utf8(original filename))
```

The receiver accepts uploads only from a sender session that passed signature
verification and local approval.

## Cloud Transfer Profile

Cloud-assisted transfers use relay services for coordination and encrypted
chunk storage. The relay may know transfer identifiers, device identifiers,
file counts, chunk counts, chunk sizes, timing, and encrypted bytes. It does
not receive plaintext, private keys, shared secrets, or derived transfer keys.

The current encrypted cloud mode identifier is:

```text
x25519-aesgcm
```

A cloud transfer includes:

- Sender signed device envelope.
- Receiver signed device envelope or receiver device identifier.
- Sender and receiver X25519 ephemeral public keys.
- Transfer identifier.
- File descriptors such as file id, name, size, chunk size, and chunk count.
- Encrypted chunks stored or relayed as opaque bytes.

For upload, the sender derives:

```text
shared_secret = X25519(sender_E_priv, receiver_E_pub)
file_key = HKDF-SHA256(shared_secret,
                       info = "filie-cloud-transfer:" || transfer_id,
                       length = 32)
```

For receive, the receiver derives:

```text
shared_secret = X25519(receiver_E_priv, sender_E_pub)
file_key = HKDF-SHA256(shared_secret,
                       info = "filie-cloud-transfer:" || transfer_id,
                       length = 32)
```

If the receiver no longer has the private key corresponding to the advertised
receiver ephemeral public key, the transfer cannot be decrypted.

## Stranger Transfer Profile

A stranger transfer is a cloud-assisted transfer discovered through a short
code. The short code is a rendezvous locator, not an encryption secret.

The relay uses the code to connect sender and receiver long enough to exchange
signed device envelopes and public agreement keys. File encryption still uses
the same X25519, HKDF, and AES-GCM pipeline. Compromise of the short code alone
does not reveal file contents.

## Retention Profile

The core protocol requires only that private agreement keys stay local. It does
not mandate a specific private-key retention duration.

A deployment may choose a bounded retention profile for recent ephemeral private
keys to support delayed delivery, offline devices, retries, and cold starts.
This affects the security/usability tradeoff:

- Shorter retention reduces the amount of recent ciphertext decryptable after a
  device compromise.
- Longer retention improves reliability for delayed or offline delivery.
- Expired private keys should be deleted from persistent storage.
- Retention policy should be documented as an implementation or product
  security profile, not as a change to the wire protocol.

For public descriptions, it is accurate to say that Filie uses bounded local key
retention when that profile is enabled. Avoid describing bounded retention as
full perfect forward secrecy. It limits historical exposure, but retained keys
can decrypt the ciphertext they cover if the endpoint is compromised while those
keys are still available.

## Security Properties

Filie is designed so that:

- Captured traffic does not contain plaintext file data.
- Captured traffic does not contain shared secrets or private keys.
- Relay/storage compromise does not reveal file contents without endpoint key
  material.
- Chunk authentication detects ciphertext modification.
- Device announcements bind identity keys to ephemeral agreement keys.
- Decryption of delayed transfers is possible only while the relevant receiver
  ephemeral private key is still locally available.

## Non-Goals and Metadata

Filie does not hide all metadata by itself. Depending on the transfer path, a
network or relay observer may learn:

- Source and destination IP addresses.
- Timing and duration of activity.
- Transfer identifiers.
- Device identifiers or pseudonyms.
- File counts, chunk counts, and byte sizes.
- Whether a transfer completed, expired, or was retried.

Network metadata reduction can be layered below Filie, for example with a VPN
or multi-hop transport. That is separate from Filie's payload encryption
protocol.

Filie also does not protect against:

- Malware or live compromise on the sender or receiver device.
- Malicious operating system components.
- Compromised application update channels.
- Users approving transfers from the wrong device.
- Weaknesses introduced by replacing the specified primitives with
  non-equivalent algorithms.

## Post-Quantum Migration

The current X25519 key agreement and Ed25519 signatures are classical elliptic
curve primitives. They are not considered resistant to a future
cryptographically relevant quantum computer.

A post-quantum migration profile should use hybrid key establishment:

```text
classical_secret = X25519(...)
pq_secret        = ML-KEM.Decapsulate(...) or ML-KEM shared secret
hybrid_secret    = HKDF-SHA256(classical_secret || pq_secret,
                               info = "filie-hybrid-session",
                               length = 32)
```

Transfer keys would then be derived from `hybrid_secret` rather than directly
from the X25519 shared secret. Hybrid mode preserves compatibility with current
classical security assumptions while adding protection against harvest-now,
decrypt-later attacks if the post-quantum KEM remains secure.

A future identity migration may similarly use hybrid signatures, such as
Ed25519 plus a standardized post-quantum signature scheme. Payload secrecy
should prioritize hybrid key establishment first.

## Versioning

Protocol profiles should be identified explicitly when serialized on the wire.
Examples:

```text
x25519-aesgcm
x25519-mlkem-aesgcm
```

Receivers must fail closed when a transfer requests encryption but the relay or
peer does not return the expected encryption profile. Unsupported cryptographic
profiles must be rejected rather than silently downgraded.

## Open Protocol Statement

This document describes Filie's application-layer end-to-end encryption
protocol. Filie uses documented message formats and standard cryptographic
primitives rather than secret proprietary cryptography.

The control plane is human-readable JSON. Discovery, identity, transfer setup,
and public key material can be inspected directly on the wire. File contents are
not carried in plaintext; they are carried as opaque authenticated-encrypted
chunks. This keeps the protocol open and auditable while protecting transfer
contents and detecting payload tampering.
