Technical Beauty ■ Episode 10
You want to encrypt a file for a colleague. A five-second task. You reach for GPG. GPG asks you to understand keyrings. Then trust models. Then configuration files. Then keyservers. Then fifty command-line flags, each with its own man page subsection and its own capacity to silently produce the wrong result. Forty minutes later, you are reading a Stack Overflow thread titled “gpg: No public key” and questioning whether the file was worth encrypting in the first place.
In 2019, Filippo Valsorda decided this was no longer acceptable. He wrote age, which stands for Actually Good Encryption. The name is either perfectly descriptive or magnificently cheeky, depending on how many hours you have personally lost to GPG. Either way, it is accurate.
The Command
Here is age encrypting a file:
age -r age1ql3z7hjy... secret.txt > secret.txt.age
That is the entire ceremony. No keyring. No configuration file. No trust model. No keyserver query. No interactive prompt asking which subkey to use. No ambiguity about what happened. The recipient’s public key is a string. You paste it. The file is encrypted. You are done, and you still have forty minutes of your life left.
Here is age decrypting it:
age -d -i key.txt secret.txt.age > secret.txt
Two commands. No state between them. No database of keys that can corrupt. No configuration directory that can drift between machines. Keys are strings, not entries in a local database that you must remember to export before reformatting your laptop at midnight.
The Numbers
age is 3,000 lines of Go. An experienced developer can audit the entire codebase in an afternoon. Not skim it. Not grep for obvious mistakes. Actually read it, understand every function, trace every code path, and leave with a justified opinion about whether it does what it claims.
GPG is 500,000 lines. Auditing GPG is not an afternoon. Auditing GPG is a funded research project with a timeline measured in months, an outcome measured in papers, and a conclusion that invariably includes the phrase “further work is needed.”
The ratio is 167:1. For every line of age, GPG has 167 lines doing something. Some of those lines implement features. Many of them implement the interactions between features. The majority implement the consequences of decisions made in the 1990s that cannot be reversed without breaking the web of trust, which itself is a feature that almost nobody uses and almost everybody misunderstands.
The Man
Valsorda was not an outsider complaining about GPG from the sidelines. He was the Go Security Lead at Google. He knew, in precise and quantifiable terms, what cryptographic complexity costs. He had reviewed the CVEs. He had traced the bugs. He understood that the attack surface of an encryption tool is not proportional to its line count but to the square of its feature count, because every feature interacts with every other feature in ways that the original designers did not anticipate and the current maintainers cannot fully enumerate.
His response was not to fix GPG. His response was to observe that GPG’s problems are architectural, not incidental. You cannot fix a tool that tries to do everything by doing everything better. You fix it by building a new tool that does one thing.
The Cryptography
age uses X25519 for key agreement and ChaCha20-Poly1305 for authenticated encryption. These are not the newest primitives. They are the correct primitives. X25519 was designed by Daniel J. Bernstein, who has a rather strong track record of designing things that do not break. ChaCha20-Poly1305 is the IETF standard for authenticated encryption when you want performance without hardware AES support, which is to say, on every device that is not a server.
GPG, by contrast, supports a museum of ciphers. IDEA. CAST5. Blowfish. Triple DES. Each one a historical artefact, each one a potential downgrade path, each one a configuration option that an uninformed user might select because it appeared first in a dropdown. age offers no dropdown. age offers one set of primitives, chosen correctly, and the user is not invited to second-guess the selection. This is not paternalism. This is the recognition that cryptographic agility, the ability to choose your cipher, is itself a vulnerability. The user who can choose wrong will choose wrong, given sufficient time and insufficient documentation.
The Ecosystem
age was not designed to replace GPG entirely. It was designed to replace the one thing people actually use GPG for: encrypting files for known recipients. By refusing to do more, it attracted an ecosystem of tools that do the rest.
SOPS, Mozilla’s secrets management tool, uses age as an encryption backend. chezmoi, the dotfiles manager, uses age to encrypt sensitive configuration. Over 350 Go projects import age as a library. Each of these tools chose age for the same reason Valsorda built it: they needed encryption that works without ceremony, without state, and without a forty-minute detour through keyserver configuration.
This is the Unix philosophy operating exactly as intended. age does one thing. Other tools compose with it. The result is an ecosystem where encryption is a pipe fitting, not a cathedral. You bolt it in where you need it. It does not demand that you restructure your architecture around its requirements.
The Refusal
The most interesting thing about age is what it does not do. It does not sign files. It does not manage a web of trust. It does not integrate with email clients. It does not support keyservers. It does not offer cipher negotiation. It does not maintain state between invocations.
Every one of these absent features is a conscious design decision. Signing is a different problem. The web of trust never worked at scale. Email encryption requires UI integration that belongs in the email client, not the encryption tool. Keyservers are a centralised dependency for a tool that claims to be decentralised. Cipher negotiation is the mechanism by which downgrade attacks become possible. State is the mechanism by which corruption becomes possible.
GPG has all of these features. GPG has had all of these features for decades. The result is that GPG is powerful, comprehensive, and almost impossible to use correctly. age is none of those first two things, and that is precisely why it achieves the third.
3,000 lines of Go. Zero configuration files. One purpose. Keys are strings, not databases. The tool that refuses to do everything is the tool that does one thing flawlessly. That is not limitation. That is beauty.