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.
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
mlkem768x25519recipient type is part of the age ecosystem. TheageCLI 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.
Long, because it carries an ML-KEM key alongside an X25519 one. Still safe to hand to anyone.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Several files, your call
One archive, or one encrypted file each. Archives are standard uncompressed USTAR, unpacked anywhere with tar -xf.
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.
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.
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.
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.
Pick files
One file or many, of any size. Several can become one archive or one encrypted file each.
Choose a recipient
A GitHub username, an SSH key, a classical age recipient, a post-quantum one, or just a passphrase.
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.
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 tossh-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_signerslist 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
.siganyone 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
.ageand.age.sigmade by AgePony 2.0 verifies exactly as it always did.
No AgePony needed on the other end. Anyone can confirm a signature with the tool they already have:
Made for people who already live in a terminal.
Developers
Encrypt a secret to a teammate's GitHub keys before you've finished your coffee. Sign a release artifact with the YubiKey already on your keychain.
Sysadmins & SRE
Ship a credential to a server admin using the SSH key that's already in authorized_keys. No new key material to manage.
Journalists & sources
A source with a phone and your public key can send you an encrypted, signed file. No PGP onboarding, no key servers, no metadata trail.
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.
The duress password is designed so that Real, decoy, and wrong all behave the same from the outside. How the duress vault works →
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 recipients
age1pq1…, 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.
| AgePony | age CLI | PGP apps | |
|---|---|---|---|
| Runs on a phone | ✓ | — | ✓ |
| Post-quantum recipients | ✓ | ✓ (1.3+) | — |
| Files larger than memory | ✓ | ✓ | varies |
| 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 telemetry | ✓ | ✓ | varies |
| Open source | ✓ | ✓ | varies |
Frequently asked.
Is AgePony free?
Is it compatible with the age CLI?
age, and vice versa. Post-quantum recipients need age v1.3.0 or newer on the other end.Is AgePony post-quantum?
What is the largest file I can encrypt?
Can I move files I already encrypted onto a post-quantum key?
Can people verify the signatures it makes?
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?
sk-ssh-ed25519 and sk-ecdsa-sha2-nistp256, touch-only or FIDO2-PIN protected.Does AgePony send my data anywhere?
How is this different from PGPony?
Take encryption with you.
Free on iPhone, Android, Mac, Windows and Linux. Open source. No accounts, ever.