This document provides instructions for building KeyOS in a reproducible manner using Nix, allowing verification against official releases.
Not all binaries can be fully verified by external developers:
| Binary | Verifiable | Reason |
|---|---|---|
app.bin |
Yes | Hash computed without signature header |
recovery.bin |
Yes | Hash computed without signature header |
apps/*.elf |
Yes | Hash computed without signature header |
boot.bin |
No | Is encrypted for secure boot |
The bootloader (boot.bin) is encrypted with a secret key to support the Passport Prime MCU’s secure boot mechanism and therefore cannot be reproduced or verified byte-for-byte by third parties. All other firmware images and application binaries are fully reproducible and can be verified using normal hashing techniques such as SHA256.
We are investigating ways to make the bootloader verifiable in the future.
-
Install Nix and enable flakes as described in the Nix install section of DEVELOPMENT.md.
-
Ensure you're building on an aarch64 architecture for perfect reproducibility.
-
Get the source code as described in the Get the Source Code section of DEVELOPMENT.md.
-
Checkout the release tag you want to verify (e.g.,
v1.1.0):git checkout v1.1.0Only tagged releases have corresponding official binaries in the KeyOS-Releases repository.
-
Enter the Nix development environment:
nix developThis sets up the reproducible build environment with all required dependencies.
-
Build the production firmware:
cargo xtask build-all --production-bootloader --production-firmwareThis builds all production components (bootloader, recovery, and main firmware) in a deterministic way.
-
Print the hashes of built binaries:
cargo xtask print-hashesThis command outputs the SHA256 hashes of the built binaries. For signed binaries (
app.bin,recovery.bin, app ELF files), the hash is computed without the cosign2 signature header (first 0x800 bytes), since signatures are non-deterministic.
To verify that your local build produces the same binaries as the official release:
-
Find the official release binaries:
- Go to the KeyOS-Releases repository.
- Navigate to the version directory matching your tag (e.g.,
1.1.0/for tagv1.1.0). - The release contains:
boot.bin- bootloader binary (cannot be verified, see above)app.bin- main firmware binaryrecovery.bin- recovery firmware binaryapps/- individual application binaries (app.elffiles)
-
Compute hashes of the official release binaries: For signed binaries, you need to skip the cosign2 header (first 2048 bytes) when computing the hash:
# For app.bin, recovery.bin, or app ELF files: tail -c +2049 <file> | sha256sum
-
Compare hashes:
- Compare the output of your local
cargo xtask print-hasheswith the hashes computed from the release binaries. - The hashes for
app.bin,recovery.bin, and all app ELF files should match. - The
boot.binhash will differ due to the secretEXTRA_ENTROPYvalue.
- Compare the output of your local
-
If hashes differ (for verifiable binaries):
- Ensure you're on the exact tag/commit corresponding to the release.
- Verify your Nix installation and configuration.
- Check that you're on an aarch64 architecture.
- Make sure you used the
--production-bootloader --production-firmwareflags.
- Reproducibility guarantees that identical inputs produce identical outputs on the same CPU architecture.
- The
--production-firmwareflag implies--reproducible, which disables incremental compilation for deterministic builds. - You do not need to use
--dont-signfor verification, as the hash comparison ignores the signature header anyway.