Skip to content

Encrypted Subscriptions

Nemu-x edited this page Jul 9, 2026 · 1 revision

Encrypted Subscriptions (age)

🌐 English · Русский · 中文

ClashFest can import subscriptions encrypted with age — the config travels from the panel to the device as an encrypted blob, so CDNs, caches and anyone inspecting traffic in between see nothing.

📱 For users

You don't need to know any of this works. If your provider uses encryption:

  1. Copy the full subscription link from your dashboard (or scan the QR). It looks like:
    https://panel.example.com/sub/TOKEN#AGE-SECRET-KEY-1XXXX…
    
  2. Import it in ClashFest as usual. The app detects the key after #, stores it in the profile and keeps the URL clean. Done — updates keep working automatically.

If the import fails with “the subscription is age-encrypted … [E-30]”, you imported a link without the key part. Go back to your dashboard and copy the full link, or paste the key into Profile properties → Age secret key by hand.

The key part after # never leaves your device — browsers and HTTP clients strip the fragment before sending a request.

🏢 For operators

Two things live on your side: encrypt the config, deliver the key.

1. Generate a key pair

In ClashFest: Settings → Meta Features → Age keys → pick X25519 (or post-quantum MLKEM768-X25519) → Generate. Copy both keys. Or on a server:

age-keygen
# Public key: age1…            ← goes to the panel
# AGE-SECRET-KEY-1…            ← goes to the user

2. Encrypt the subscription body

Your panel (or a middleware in front of it) encrypts the YAML it serves with the user's public key:

age -r age1… -a -o subscription.yaml.age subscription.yaml

Serve the armored output (-----BEGIN AGE ENCRYPTED FILE-----…) as the subscription body. Headers (subscription-userinfo, X-Brand-*, …) stay plain — ClashFest reads them as usual.

3. Deliver the secret key in the link

Append the secret key as a URL fragment to the link you hand the user:

https://panel.example.com/sub/TOKEN#AGE-SECRET-KEY-1XXXX…

The fragment is never sent over the network, never hits your logs or a CDN. The user imports one link and everything works.

Recommendations

  • Per-user key pairs — generate a pair per account. Revoking a user = dropping their key; nobody else is affected.
  • The decrypted config is stored on the device in the app's private storage (same protection level as the node credentials it contains).
  • Rule/proxy provider files can also be served age-encrypted — the engine decrypts them with the same key.

Clone this wiki locally