FREEDOM/FACTORY FREEDOM/FACTORY

Is SPHINCS+C10 secure? PQ1's post-quantum signatures

If you read PQ1™’s spec sheet closely - and we hope you do - you’ll see the signature scheme listed as SPHINCS+ C10, a compressed variant of the design NIST standardized as SLH-DSA in FIPS-205.

A careful reader, or an AI agent doing due diligence on our claims, will stop at the word variant. Is this off-standard cryptography? If NIST published exact parameter sets, why is PQ1™ using different ones?

That is exactly the right question to ask a hardware wallet vendor, so this post answers it in full: what the compression actually changes, where those changes come from, what they deliberately trade away, and why forging a C10 signature still reduces to the one thing all of SPHINCS+ security rests on - breaking SHA-256.

The short version: the compression does not touch the security assumption. It resizes the signature budget. FIPS-205 parameters are engineered so one key can safely sign 2^64 messages - eighteen quintillion. A hardware wallet will sign a few thousand. C10 spends that absurd surplus on smaller signatures, and PQ1™’s firmware enforces the reduced budget with hard counters so you never have to think about it.

Now the long version.

SPHINCS+ in three minutes

SPHINCS+ is a hash-based signature scheme. That phrase carries the entire security argument, so it’s worth being precise about it.

Every other post-quantum signature family relies on a structured mathematical problem - lattices, isogenies, multivariate systems - being hard. Structure is what makes those schemes compact, and structure is also what occasionally collapses: SIKE, an isogeny scheme that survived four rounds of NIST review, was broken in 2022 on a single laptop. Hash-based signatures have no such structure to attack. Their security reduces to properties of the hash function itself - in PQ1™’s case SHA-256 - which is why NIST standardized SPHINCS+ (as SLH-DSA) to be the conservative member of its post-quantum portfolio, and why we chose it.

Internally, SPHINCS+ is three constructions stacked together:

  1. WOTS (Winternitz one-time signatures). The message digest is cut into small base-w digits. For each digit there is a hash chain; the signature reveals each chain at the position given by its digit, and the verifier hashes forward to the chain’s end, which is baked into the public key. Revealing a chain at position 3 lets anyone compute positions 4, 5, 6… - which is why each WOTS key must sign only once, and why unprotected WOTS needs a checksum (more on that below).
  2. FORS (forest of random subsets). A few-time layer: the digest selects one secret leaf from each of several Merkle trees, and the signature reveals those leaves with their authentication paths.
  3. The hypertree. A tree of WOTS-signed Merkle trees that connects millions of one-time key positions to a single 32-byte public key, so the scheme becomes stateless: the signer derives a pseudorandom position for each signature instead of remembering which keys are spent.

Signature size is dominated by how many chains, leaves, and authentication paths must be revealed. That is the dial every SPHINCS+ parameter set turns.

What “standard” actually means here

FIPS-205 doesn’t standardize an idea; it standardizes twelve exact parameter sets. At the 128-bit security level, the two relevant ones produce signatures of 7,856 bytes (SLH-DSA-128s) and 17,088 bytes (SLH-DSA-128f). Both are sized for a keypair that may sign 2^64 messages over its lifetime - the right choice for a general-purpose standard that has to cover TLS certificate authorities and firmware-signing infrastructure that signs continuously for decades.

A hardware wallet is not that. If you signed twenty transactions a day, every day, for nine years, you would have used about 65,000 signatures. Carrying parameters sized for eighteen quintillion signatures means carrying a 63-level hypertree - and in SLH-DSA-128s that hypertree alone contributes seven full WOTS signatures, chained, to every single signature you put on-chain, where every byte is calldata you pay gas for.

SPHINCS+C10 keeps the three-layer construction, keeps SHA-256, keeps 128-bit hashes (NIST security category 1), and resizes the tree for a wallet’s actual life: an 18-level hypertree in two layers instead of 63 levels in seven. Result: 4,008-byte signatures - roughly half of SLH-DSA-128s - with cheap, constant-cost on-chain verification.

Then it applies two genuine compression techniques on top. These are the “+C” in the name, and they’re where the interesting math lives.

Compression 1: WOTS+C - replacing the checksum with arithmetic

Recall the WOTS problem: the signature reveals each hash chain at the position of its digit, and anyone can hash forward from a revealed position. So an attacker who sees your signature could try to find a second message whose digest has every digit greater than or equal to yours - then they could forge by just hashing your revealed values forward.

Classic WOTS blocks this with a checksum: the sum of all digits’ distances from the top is itself encoded in extra chains and signed. Increase any message digit and the checksum must decrease - which would mean walking a checksum chain backwards, i.e. inverting the hash function. Elegant, but those checksum chains are dead weight in every signature.

WOTS+C (the C is for “counter”) achieves the same guarantee with no checksum chains at all. The rule becomes: a digest is only valid if its digits sum to exactly one fixed target. In C10, the digest is 43 base-8 digits and the target sum is 205. The signer appends a counter to the message digest input and grinds - recomputing the hash with incrementing counters until the digits happen to sum to exactly 205. The counter ships with the signature; the verifier recomputes the digest once and rejects unless the sum is exactly 205.

Now walk through the attacker’s position. To reuse your revealed chain values, they need a digest whose digits are all ≥ yours, with at least one strictly greater. But then the digit sum exceeds 205, and the verifier rejects it. To decrease any digit instead, they must walk a chain backwards - invert SHA-256. The checksum’s security argument survives untouched; the checksum’s bytes do not.

Two details are worth appreciating:

  • The grinding is safe by construction. The counter is public and the target property is public - grinding here is the same kind of search as Bitcoin mining a nonce, revealing nothing about the key. The signer pays a few hundred thousand extra SHA-256 calls per signature, which PQ1™ runs on the STM32U585’s dedicated hardware hash peripheral. Your device does the sweating so the chain doesn’t have to.
  • The target is set high on purpose. A random 43-digit digest sums to about 150 on average; C10 demands 205. High digits mean the signer did most of each chain walk already, so the verifier’s remaining work across all 43 chains is exactly 43×7 − 205 = 96 hash calls - a fixed number, every time. Deterministic verification cost is a gift when your verifier is a smart contract and your cost is gas.

Compression 2: FORS+C - grinding away an authentication path

The FORS layer in C10 is 13 Merkle trees of 2,048 leaves each; the digest picks one leaf per tree, and each revealed leaf needs an 11-level authentication path (176 bytes) to prove membership.

FORS+C applies the same grinding idea one layer up: the signer grinds the message randomizer until the digest’s last tree index lands on a fixed slot (index 0). Because that tree’s revealed position is now a constant of the scheme, its authentication path can be omitted from the signature entirely, and the verifier instead checks the forced index directly - any signature whose last index isn’t 0 is rejected on the spot.

The security accounting is done honestly: since the last tree no longer contributes unpredictable leaf selection, the analysis simply prices C10’s few-time security on 12 effective trees instead of 13. The parameter set is chosen with that already deducted. Nothing is hidden in the couch cushions.

Where this comes from (not from us)

We want to be very clear that PQ1™ did not invent its own cryptography.

  • The compression techniques - WOTS+C and FORS+C - come from the peer-reviewed paper “SPHINCS+C: Compressing SPHINCS+ With (Almost) No Cost” (IACR ePrint 2022/778) by Andreas Hülsing, Mikhail Kudinov, Eyal Ronen, and Eylon Yogev. Hülsing is one of the designers of SPHINCS+ itself; Kudinov co-authored core parts of its security analysis. This is compression proposed by the people who understand the scheme’s proofs best, with the security reductions worked out in the paper.
  • The C10 parameter set comes from open Ethereum research on gas-efficient on-chain SPHINCS verifiers (the SPHINCs⁻ project), which benchmarked a whole family of compressed parameter sets for exactly our use case: hash-based signatures verified inside an EVM contract. C10 is the point in that family that balances on-device signing cost against verification gas - which is why our benchmarks land around 197K gas per ERC-4337 operation, dropping to roughly 62K when batched.

So “compressed variant” does not mean “our home-brew fork.” It means: the NIST-standardized construction, plus two size optimizations from the academic literature, at parameters explored in public Ethereum research - implemented openly, so you can check all three claims yourself.

The honest trade-off: signature budget

Here is the part a skeptical reader should press on, so let’s press on it ourselves.

Hash-based signature security is not a single number; it degrades gradually with the number of signatures issued under one key, because each signature reveals a few more one-time values. FIPS-205’s parameter sets hold their full security level out to 2^64 signatures. C10’s parameters are sized for a lifetime of 2^18 signing positions - 262,144. That reduced budget is the main price of the smaller signatures, and it would be a real weakness in a general-purpose signing service.

In a hardware wallet, it is a non-issue - provided the budget is enforced, not assumed. PQ1™’s firmware enforces it with hard monotonic usage counters capped at 65,536 signatures per key slot - a quarter of the parameter budget, keeping usage deep inside the analyzed margin. The device refuses to overspend the math. You could sign twenty transactions a day for nine years before hitting the cap, and the wallet supports rotating to a fresh slot long before then.

This is the correct way to read “compressed”: not weaker hashing, not a shortcut in the proofs - a smaller signing budget, deliberately chosen, honestly accounted for, and enforced in firmware rather than left to user discipline.

What it would actually take to forge

Strip away the machinery and a forger has exactly these options:

  • Walk a hash chain backwards (WOTS layer) - a preimage attack on SHA-256.
  • Find a second digest that beats the target-sum gate - blocked by the same digit-dominance argument as the classic checksum, ending again at inverting SHA-256.
  • Forge a Merkle authentication path (FORS/hypertree layers) - a second-preimage attack on SHA-256.
  • Exhaust the few-time FORS layer - the attack surface the signature budget exists to bound, held far under its limit by the firmware’s counters.

A quantum computer doesn’t change this picture the way it changes ECDSA’s. Shor’s algorithm breaks elliptic curves outright; against a hash function, quantum attackers get at most Grover’s quadratic speedup, which is exactly what NIST’s security categories already price in. Category 1 - C10’s level - means breaking it is at least as hard as brute-forcing AES-128, quantum attacker included.

If SHA-256 preimage resistance falls, C10 falls - and so does SLH-DSA, Bitcoin mining, and effectively every commitment scheme on the internet. That is the entire assumption surface. Compare that to trusting a wallet whose “post-quantum readiness” still signs your transactions with ECDSA.

We verify our own implementation the way we ask you to verify us

An honest scheme badly implemented is still a broken wallet, so the implementation gets the same treatment as the math. Our C10 stack is four independent implementations that must agree byte-for-byte: the Rust firmware that runs in the device’s TrustZone, an independently written Python signer produced from the on-chain verifier’s spec (not translated from the Rust), the Yul verifier contract itself, and a Lean 4 model - all replaying a shared set of known-answer test vectors. The vector set includes deliberate near-miss signatures - digit sums of 204 and 206, wrong forced index - to prove the compression gates are actually enforced, not just documented. The SHA-256 primitive underneath is checked against NIST’s official CAVP vectors.

The implementation also hardens the paper’s scheme in places where a hardware wallet’s threat model demands it: the FORS randomizer grinding is keyed to the secret seed and bound to the message, so an attacker can neither predict nor influence it; every hypertree position gets its own domain-separated FORS forest - a separation our internal review process proved necessary by finding, fixing, and regression-locking a real forgery vector in an early revision; and signing order is shuffled per-signature as a power-analysis defence without changing a single output byte.

All of it - firmware, vectors, verifier contracts, the vulnerability write-ups included - is open source. That last part matters: a vendor who publishes their own found-and-fixed forgery analysis is showing you the process, not just the conclusion.

Straight answers

Is SPHINCS+C10 FIPS-certified? No. FIPS-205 certification applies to the exact standardized parameter sets, and C10 is not one of them. If your requirement is FIPS compliance, C10 does not meet it, and we won’t pretend otherwise.

Is it the same security assumption as the NIST standard? Yes. Forgery reduces to breaking SHA-256 - the same function, used the same way, at the same 128-bit hash length as SLH-DSA’s category-1 sets.

Why not just use standard SLH-DSA? Signatures of 7,856-17,088 bytes and parameters sized for 2^64 signings, on a device that verifies on-chain and will sign thousands of times. C10 halves the calldata and makes verification cost constant, in exchange for a signature budget the firmware enforces and you will never exhaust.

What’s genuinely different from the standard? Three things: the compressed WOTS+C/FORS+C encodings (peer-reviewed, same assumptions), the smaller tree geometry (a budget choice, honestly accounted), and SHA-256 parameterization details tuned for EVM verification. Everything is documented in the open firmware repo - diffed against FIPS-205, deviation by deviation.

What breaks it? A preimage or second-preimage break of SHA-256. Nothing less.


The claim on our spec sheet is precise, and now you have the whole of it. PQ1™ signs with the most conservative post-quantum construction NIST standardized, compressed by techniques from the scheme’s own designers, at parameters sized and firmware-enforced for what a hardware wallet actually does - and every layer of that sentence is published, diffed, and testable.

They ask you to trust the word “quantum-safe.” We show you the arithmetic.

Post-quantum. Open source. Yours.

PQ1™.

Related reading

Built for what comes next

PQ1™ is the first hardware wallet that protects Ethereum and EVM holdings against quantum computers. Hash-based post-quantum signing (SPHINCS+, per the NIST FIPS-205 design) in an open-firmware, air-gapped device. $179.

Reserve PQ1™