Encrypt it today.
Still secret tomorrow.

Post-quantum file encryption for iPhone and Android, built on the age protocol. Seal a file to a quantum-safe ML-KEM-768 hybrid key, sign it with a YubiKey over NFC, and hand it to anyone with the age CLI. Any size you like: a 1 GB file encrypts like a small one. The whole app is open source. No accounts. No tracking. Your keys never leave your device.

post-quantum age protocol any file size SSHSIG signing duress vault security keys open source no accounts no analytics free

It runs on your computer too.

AgePony for macOS, Windows and Linux writes the same age files the phone apps do — including the standardised post-quantum ML-KEM-768 recipient, checked against the same reference vectors on every build. Move your identity across by QR and keep going on the bigger screen.

  • Any file size — everything streams in 64 KiB
  • X25519, post-quantum, SSH keys and passphrases
  • Signed, notarized, checksums published
  • No accounts, no telemetry, no network access

The cryptography is public. Read it.

All three apps are open source under Apache-2.0, not just the crypto cores.

AgePonyCore in Swift, agepony-core in Kotlin and agepony-core in Rust are the hearts of the three apps: the age protocol, ML-KEM-768, SSH key parsing, SSHSIG, the FIDO/CTAP2 + PIN stack, and the streaming tar archiver. All three are pinned to the same reference test vectors, which is what keeps a file encrypted on one device readable on the others. Audit any of them, fork it, or just satisfy yourself that there is no second envelope.

The file you send today gets read twice.

Once by the person you sent it to. Possibly again, years later, by whoever kept a copy.

Encrypted traffic gets recorded and stored. It does not need to be readable at the time. The bet is that a cryptographically relevant quantum computer eventually arrives, and every X25519 file in the archive opens at once. The industry calls it harvest now, decrypt later, and it is the reason a file with a long secrecy lifetime needs more than good classical crypto today.

  • ML-KEM-768, standardised. The lattice KEM from FIPS 203, formerly known as Kyber. Not a preprint, not a draft.
  • Hybrid, never a swap. Every post-quantum file is also sealed with classical X25519. It stays secret if either one holds, so adopting it costs you nothing if the lattice assumption disappoints.
  • Still just an age file. The mlkem768x25519 recipient type is part of the age ecosystem. The age CLI 1.3 and newer opens what AgePony seals.
  • Bring your old files along. The re-encrypt tool moves files you already hold onto a quantum-safe key, leaving the originals untouched.
what a post-quantum recipient looks like

Long, because it carries an ML-KEM key alongside an X25519 one. Still safe to hand to anyone.

# about 1,950 characters, abbreviated here age1pq1qg7v2x9k3mn4rw8ptyl6z0shj5c2 d9fq3xbv7nm8k4lp2ws6ty0zq1ae5rc8xu ... # the CLI reads it too age -R pq.txt -o secret.age secret.pdf # => needs age v1.3.0+

What post-quantum actually means →

File size stopped being a thing.

Encrypt, decrypt, sign and verify all stream. Nothing is ever held whole.

  • A 1 GB file behaves like a small one. Bytes move through a fixed 64 KiB buffer, so memory stays flat no matter what you feed it.
  • Signing streams too. SSHSIG only ever covers the message digest, so a large file is hashed as it passes rather than loaded to be signed.
  • Several files, your choice. One archive, or one encrypted file each. The archive is assembled as the encryptor reads it and never exists on disk.
  • Tunable passphrase cost. scrypt is memory-hard on purpose. The work factor is adjustable, so a device with less headroom can still use passphrase mode.
  • Progress you can trust. A real byte counter, not a spinner that lies.
why this was hard

The obvious way to encrypt a file is to read it into memory, transform it, and write it back out. That works until the file is bigger than the headroom the OS will give a phone app, and then it does not fail gracefully, it gets the app killed.

Every path in AgePony 3.1 was rebuilt to pull and push in fixed-size chunks instead, including the ones that assemble archives and unwrap signatures.

Everything age should be on a phone.

01

Quantum-safe recipients new in 3.0

Hybrid ML-KEM-768 plus X25519, so a file recorded today stays sealed even if X25519 falls later. Reads and writes with the age CLI 1.3 and newer.

02

Files of any size new in 3.1

Everything streams in bounded memory. A 1 GB video encrypts, signs and decrypts using no more memory than a text file.

03

Encrypt to a GitHub username

Type a username. AgePony fetches their public SSH keys from github.com/user.keys and encrypts to all of them in one tap. The CLI trick everyone loves, made native.

04

Sign inside the ciphertext new in 3.0

Sign and encrypt in one step and the signature travels sealed within the file. One file instead of two, and the ciphertext no longer tells an interceptor who sent it.

05

Hardware security keys

Sign with a FIDO security key over NFC: YubiKey, Token2, others. sk-ssh-ed25519 and sk-ecdsa-sha2-nistp256, touch-only or FIDO2-PIN. Tap to sign.

06

Move old files forward new in 3.0

The re-encrypt tool lifts a file you already hold onto a post-quantum key. Your original is left exactly as it was.

07

Inspect before you open new in 3.1

See what any .age file is encrypted to, whether it is post-quantum, and whether you hold a key for it, all without decrypting a byte.

08

SSH keys as recipients

Use any ssh-ed25519 or ssh-rsa public key as a recipient. Encrypt to a server admin without minting new age keys.

09

Detached signing, standard SSHSIG

Prefer a separate .sig? Produce one in the same format as ssh-keygen -Y sign. Anyone with OpenSSH verifies it, no AgePony required.

10

Several files, your call

One archive, or one encrypted file each. Archives are standard uncompressed USTAR, unpacked anywhere with tar -xf.

11

Open .age files directly

Long-press any .age file in Files and tap Open in AgePony. It lands straight in the decrypt flow, ready to unwrap with your identity or passphrase.

12

Local-first, zero backend

No account. No cloud sync. No telemetry. Unlock with biometrics, a password or a PIN. Your keys live in your device's secure hardware and stay there.

13

A dedicated Sign tab new in 4.0

Sign a file on its own or sign-then-encrypt in one pass, pick from in-app, hardware or NFC keys, and keep the allowed_signers list you check incoming files against. RSA joins ed25519 for signing.

14

Duress password new in 4.0

Set a second password that opens an empty decoy vault and quietly clears the real one. An unlock forced under pressure looks identical to a normal one. Android for now, iOS next.

Four taps, no manual.

01

Pick files

One file or many, of any size. Several can become one archive or one encrypted file each.

02

Choose a recipient

A GitHub username, an SSH key, a classical age recipient, a post-quantum one, or just a passphrase.

03

Sign it (optional)

Flip one switch and the signature is sealed inside the file, made with a key, the Secure Enclave, or a tap of your YubiKey.

04

Seal it

AgePony writes a real age file. Share it however you like, it is just bytes.

A signature that keeps your name out of it.

Sign then encrypt, so the ciphertext gives nothing away.

A detached signature sitting next to a file is readable. Anyone who intercepts the pair can lift the signer's public key straight off it and learn who sent the file without decrypting anything. From 3.0 AgePony signs the plaintext, packs the payload and its signature together, and encrypts the whole thing. One file goes out. The recipient learns who signed it only once they can already read it. From 4.0 there is a dedicated Sign tab: pick a key, sign a file on its own or sign-then-encrypt in one pass, and manage the trusted signers you check incoming files against.

  • Standard SSHSIG inside. Namespace agepony, identical to ssh-keygen -Y sign. Sealing it in changes where it lives, not what it is.
  • Checked on the way out. Decrypt in AgePony and the signature is verified as the file streams past, with the signer matched against your own identities and trusted signers.
  • Trusted signers you control. Keep an allowed_signers list of the people you accept, add or remove them in the Sign tab, and AgePony names the signer when a file checks out.
  • Detached still available. Want a separate .sig anyone can verify with plain OpenSSH? That flow is untouched.
  • Sign with anything. An in-app SSH key (ed25519 or RSA), a Secure Enclave key born in hardware and non-exportable, or an external FIDO security key over NFC.
  • PIN-aware. Touch-only keys stay one tap. PIN-protected keys prompt for the FIDO2 PIN only when the key demands it.
  • Old pairs still open. A .age and .age.sig made by AgePony 2.0 verifies exactly as it always did.

How signing works, end to end →

verify anywhere

No AgePony needed on the other end. Anyone can confirm a signature with the tool they already have:

# they sign on their phone, you verify on a laptop ssh-keygen -Y verify \ -f allowed_signers \ -I friend@example.com \ -n agepony \ -s report.pdf.sig \ < report.pdf # => Good "agepony" signature for friend@example.com

What stays on your device.
Spoiler: everything.

  • No account. Nothing to sign up for, nothing to log into.
  • No server. AgePony has no backend of its own to phone home to.
  • No telemetry. No analytics SDKs, no crash trackers, no ad IDs.
  • One network call, ever. Fetching a GitHub user's public keys, and only when you ask.
  • Hardware-backed keys. Identities live in the device's secure storage; Secure Enclave keys never leave it.
  • Your choice of lock. Face ID or fingerprint on launch, or unlock with a password or PIN. On Android the vault opens with the password alone, no biometric hardware required.
  • Duress password (Android). A second password opens a separate empty vault and quietly clears the real one, so an unlock under pressure gives nothing away.
plausible deniability

The duress password is designed so that Real, decoy, and wrong all behave the same from the outside. How the duress vault works →

the whole privacy policy, in one line

AgePony collects nothing, stores nothing on a server, and the only thing that ever leaves your phone is the ciphertext you choose to share.

Read the full privacy policy. It's short on purpose.

For the people who read the spec.

  • Encryptionage v1: X25519 + ChaCha20-Poly1305 (STREAM)
  • Post-quantumML-KEM-768 (FIPS 203) + X25519 hybrid, mlkem768x25519
  • PQ recipientsage1pq1…, bech32, ~1,950 chars
  • Passphrase modescrypt, adjustable work factor 2^16 to 2^20
  • Recipientsage1…, age1pq1…, ssh-ed25519, ssh-rsa, GitHub username
  • Memorybounded: 64 KiB buffers, independent of file size
  • SigningSSHSIG, namespace agepony
  • Signed filessign-then-encrypt bundle, or detached .sig
  • Sign keysed25519, RSA, Secure Enclave (P-256), FIDO sk-*
  • Security keysFIDO2 / CTAP2 over NFC, clientPin (PIN/UV v1)
  • Interopage CLI bit-perfect (1.3+ for PQ); SSHSIG via OpenSSH
  • PlatformsiOS 18.6+, Android
  • LicenseApache-2.0, source

How AgePony stacks up.

AgePonyage CLIPGP apps
Runs on a phone
Post-quantum recipients✓ (1.3+)
Files larger than memoryvaries
Encrypt to GitHub username✓ (manual)
SSHSIG signing
Signature hidden in ciphertext
Hardware security keys (NFC)some
No key servers / web of trust
No account / no telemetryvaries
Open sourcevaries

See the full comparisons →

Frequently asked.

Is AgePony free?
Yes. Free on the App Store and Google Play. No accounts, no subscriptions, no ads, no in-app purchases.
Is it compatible with the age CLI?
Yes. AgePony implements age directly and is bit-perfect with the reference CLI. Encrypt in AgePony, decrypt with age, and vice versa. Post-quantum recipients need age v1.3.0 or newer on the other end.
Is AgePony post-quantum?
Yes, since 3.0. A post-quantum recipient is a hybrid of ML-KEM-768 (the FIPS 203 lattice KEM) and classical X25519, so the file holds as long as either does. It protects against an adversary recording ciphertext now to open once a quantum computer exists. More on that here.
What is the largest file I can encrypt?
Whatever your device can store. Since 3.1 every path streams in bounded memory, so a 1 GB file uses no more memory than a small one. Signing and verifying stream too.
Can I move files I already encrypted onto a post-quantum key?
Yes. The re-encrypt tool decrypts a file you can already open and seals it to a new recipient, leaving your original untouched. It cannot do anything about copies you already sent to other people, which stay on the old key.
Can people verify the signatures it makes?
Yes. Signatures are standard SSHSIG. A detached signature verifies anywhere with ssh-keygen -Y verify and no AgePony. When you sign and encrypt in one step the signature rides inside the file, and AgePony checks it for the recipient as the file decrypts.
Which security keys work?
FIDO keys over NFC such as YubiKey and Token2. Both sk-ssh-ed25519 and sk-ecdsa-sha2-nistp256, touch-only or FIDO2-PIN protected.
Does AgePony send my data anywhere?
No server, no telemetry. The only network call is fetching a GitHub user's public keys, and only when you ask it to encrypt to a GitHub username.
How is this different from PGPony?
AgePony is the modern age world: small, no key servers. PGPony is the full OpenPGP world with smartcards and GnuPG interop. Same developer, same privacy rules.

Take encryption with you.

Free on iPhone, Android, Mac, Windows and Linux. Open source. No accounts, ever.