Hybrid post-quantum (Ed25519+ML-DSA-65) narinfo signatures - #202
Hybrid post-quantum (Ed25519+ML-DSA-65) narinfo signatures#202Tristan-Stoltz-ERC wants to merge 1 commit into
Conversation
Proposes an optional, additive Sig-PQC: narinfo field carrying a hybrid Ed25519+ML-DSA-65 signature, so binary caches can begin dual-signing years ahead of any cryptographically-relevant quantum computer, without breaking existing nix clients. Supporting prototype: https://github.com/Luminous-Dynamics/nix-pqc-cache-proxy
|
Note that some prior art exists here in case it is useful. In NixOS/nix#15926 we upstreamed the start of our work for post-quantum cryptography which we implemented in Determinate Nix in DeterminateSystems/nix-src#449. That work embeds additional signatures under the existing narinfo format. It looks like this: ...producing: |
|
Why is “PQC” special from the Nix config’s perspective? Why not just extend existing signatures field to allow for extensible algo types and then add whatever algorithms are needed? |
|
Thanks @grahamc and @shlevy. I reviewed both NixOS/nix#15926 and the fuller implementation in DeterminateSystems/nix-src#449. I agree with the central point: PQC does not appear to require a special narinfo field. Extending the existing signature and trusted-key machinery by algorithm type is cleaner, more general, and already has working prior art. My original motivation for The review did expose a related distinction that may still be worth specifying: supporting multiple signature algorithms is not necessarily the same as requiring a hybrid signature policy. In the current verification path, a narinfo containing both Ed25519 and ML-DSA signatures is accepted when any trusted signature verifies. That provides algorithm agility, but it does not express “one valid classical signature AND one valid post-quantum signature are required.” Without explicit policy semantics, the post-quantum signature could be removed and the classical signature could still satisfy verification, so the combination would not provide downgrade-resistant hybrid authentication. The current RFC leaves enforcement policy as an implementation detail. After reviewing this prior art, I think that is backwards: the existing signature representation should probably be reused, while the potentially useful RFC contribution is the policy and migration model. I’m planning to revise the proposal along these lines:
Does that sound like a useful scope for this RFC, or would the signature-policy portion be better pursued through the configurable-verification work proposed in NixOS/nix#14451, or as a separate proposal? |
|
Thank you to everyone who reviewed this proposal, particularly @grahamc and @shlevy for pointing me toward the existing polymorphic-signature work and questioning whether post-quantum signatures required special treatment in the narinfo format. After reviewing the prior art and developing the prototype further, I agree that post-quantum algorithms should use Nix’s extensible signature representation rather than a parallel The work exposed a more general issue: supporting multiple signature algorithms does not by itself provide a way to require composed authorization—for example classical AND post-quantum signatures, thresholds, distinct authorities, identity binding, or cryptographic-family diversity. I am therefore closing #202 as superseded rather than rejected. I am preparing a new proposal, “Composable signature authorization for Nix store paths,” which is algorithm-neutral and focuses on authorization semantics, downgrade resistance, migration, recovery, and compatibility with existing Nix signature machinery. I appreciate the feedback that helped redirect this work toward a more general and useful design. |
docs/PRIOR_ART_AND_DESIGN_DELTA.md records the actual upstream research behind the previous commit: NixOS/rfcs#202 (this project's own prior submission, closed 2026-07-14 as superseded after real feedback from two NixOS/nix maintainers -- @grahamc pointed at nix#15926/DeterminateSystems' nix-src#449 as already doing algorithm-agility without a parallel narinfo field, @shlevy asked directly why PQC needed special treatment), the still-open nix#14451 proposal this project builds on (including its own author flagging the exit-code-vs-structured-output ambiguity we resolve, and real precedent citations: pam_exec, mod_authnz_external, OpenVPN --tls-verify, OpenSSH AuthorizedKeysCommand), and a maintainer's real, unresolved architectural concern (point-wise vs. closure-wide trust) that gets acknowledged as a genuine limitation rather than ignored. It states plainly what's reused, what's missing, and what's explicitly not being proposed. Open-source states (nix#15926, nix-src#449) are anchored to a verification date rather than described as "current," since they can change independently of this document. docs/CALLER_SAFETY.md documents src/caller.rs's behavior as the spec a future C++ implementation should mirror, maps the original 18-item hostile- helper brainstorm to what's actually tested vs. covered by fuzzing vs. explicitly out of scope, and replaces the community's order-of-magnitude performance estimate with a real measurement: 1755 cold-start invocations of the release binary on 2026-07-15, reported as a full latency distribution (min/p50/p90/p95/p99/max/mean, not just a mean) with the measurement environment and a reproduction command, since the tail matters more than the mean for an admission path. Also appends one clearly-speculative, non-binding paragraph to docs/PROJECT_HISTORY.md noting that this shape composes with a broader NIST SP 800-207-style model if that ever proves useful beyond Nix -- recorded so the idea isn't lost, not proposed as a roadmap, a rename, or scope for this project.
This proposes an optional, additive
Sig-PQC:narinfo field carrying ahybrid Ed25519+ML-DSA-65 signature, so binary caches can begin dual-signing
years ahead of any cryptographically-relevant quantum computer (CRQC)
existing, without breaking any existing
nixclient.Why now
Nix's binary-cache trust is 100% classical Ed25519. Store-path/NAR hashing
(SHA-256) retains a large security margin under Grover's algorithm, but
Ed25519 is broken outright by Shor's algorithm given a CRQC -- and every
narinfo a compromised key ever signed becomes forgeable, retroactively.
Signing keys and
trusted-public-keysconfiguration are long-lived, sothere's real value in caches dual-signing well before enforcement is ever
needed, rather than racing a migration under pressure later.
What this RFC does and doesn't propose
Sig-PQC:field, pairedwith the existing
Sig:line by key name. Existingnixversions needzero changes -- narinfo parsing already silently ignores unrecognized
fields.
require-pqc-sigssetting) as animplementation detail, separate from the format itself.
format versions, or
nix-store --generate-binary-cache-key's defaultoutput.
cache.nixos.orgitself PQC-signed, or touch Nix'sC++/Rust source at all yet -- see "Unresolved questions" for the
cppnixvstvixquestion.Supporting prototype
A working, tested, AGPL-3.0-or-later licensed prototype backs this
proposal: https://github.com/Luminous-Dynamics/nix-pqc-cache-proxy
It independently reimplements Nix's real narinfo fingerprint algorithm and
verifies it byte-for-byte against a real
cache.nixos.orgnarinfo and itsreal published key; dual-signs a local cache and runs a small reverse
proxy demonstrating the mechanics; and proves, via
nix store verifyagainst a real unmodified
nixbinary, that a client trusting only thenew hybrid key correctly trusts a dual-signed path and correctly refuses
an untrusted one. It ships a JSON test-vector suite so an independent
implementation (e.g. in
tvix) can check itself without reading theprototype's source, and builds/tests cleanly from a fresh clone with zero
private dependencies.
The prototype's crypto is explicitly unaudited -- it exists to prove
the wire format and trust-model mechanics work, not as a production
crypto library.
All claims in the RFC about current Nix source (file paths, function
names, trust logic) were verified directly against
NixOS/nixat apinned commit, cited in the RFC text.
Where I'd like the most help
cppnixortvixis the more sensible first realimplementation target (see "Unresolved questions" in the RFC).
Sig-PQC:field name/encoding should change beforethis is considered close to final.
haven't found.
Happy to nominate myself or find shepherds as this moves forward.