My first Rust-based project, PaperAge, is a solution for making secure paper backups of important secrets. The backups are secured with state-of-the-art cryptography using the age format.
Personally, I use it to make paper backups of the bare minimum credentials I’d need to regain access to all my online accounts and backups. For example, the 1Password recovery kit plus my email account and Apple ID credentials.
One of the requirements for PaperAge was being able to print the backups at any printer without having to trust the printer or whoever operates it. This is why the generated PDF has a blank space for the passphrase. Additionally, this allows you to store the passphrase separately for extra security (either physically or you can trust yourself to remember it).
My personal threat model doesn’t include state actors or extremely tech-savvy burglars, so just relying on physical security and/or obscurity provides a sufficient level of security for my needs. I’m mostly guarding against the unlikely event where I lose access to all my devices at the same time and have to regain access to my accounts and backups from scratch.
Equally, I didn’t want the backup solution to be dependent on any one tool or person. Not even if it was my own project. To this end, you don’t need PaperAge to recover from backups made with it. Instead, you can use either the original age CLI tool or any compatible implementation. Behind the scenes, PaperAge uses rage, the Rust port of age.
Automated releases
The release workflow for PaperAge is highly automated and uses cargo release to tag and publish new releases.
Pushing a release tag to GitHub kicks off a GitHub Actions workflow that will create a new draft release on GitHub, cross compile for macOS, Linux, and Windows, and publish the release once compiled. Finally, it sends a workflow_dispatch
event to the matiaskorhonen/homebrew-paper-age repository to kick off a GitHub Action that updates the Homebrew formula for PaperAge.
The Homebrew formula update action will install Homebrew, update the formula based on a template, test that the formula still works, and finally commit and push the updated formula.
Eventually, I’m planning on trying to get a PaperAge formula up-streamed to Homebrew itself, but the current Cask workflow works so well that I haven’t been very motivated to get it done so far.
Further reading
- Awesome Age: A collection of projects and resources in the age file encryption ecosystem
- cargo release: Cargo subcommand for releasing a crate
- upload-rust-binary-action: GitHub Action for building and uploading Rust binary to GitHub Releases