Code location: the quip-crypto-primitives crate and BABE integration in the QuipNetwork polkadot-sdk fork (branch v0.2). Issues are disabled on that fork, so this is filed here on the consuming protocol repo.
Summary
quip-crypto-primitives derives component seeds with a fixed HKDF info (b"pq" and b"classical") that does not vary by hybrid suite. Two different suites derived from the same master seed get the same pq_seed and the same classical seed. For the lattice suites this is a key-reuse concern that domain separation at signing time covers in practice. For the proposed stateful hash-based suites (H5 = ed25519+SHRINCS, H6 = sr25519+SHRINCS) it is worse. An identical pq_seed yields a byte-identical SHRINCS signing key. Two independent signers then operate one stateful Merkle tree, reuse its one-time leaves, and compromise the key.
Detail
HKDF_PQ_INFO = b"pq" and HKDF_CLASSICAL_INFO = b"classical", fixed for every suite — quip/primitives/crypto/src/seed.rs:16-40 (path on branch v0.2).
derive_component_seeds(master_seed) returns the same pq_seed for H5 and H6 (and for H1/H3). SHRINCS keygen(pq_seed, maxSignatures) is deterministic, so H5 and H6 from one master seed share stateful_sk_seed, stateful_prf_seed, the leaf secrets, stateful_root, and the commitment.
- Each signer keeps its own leaf counter starting at 1 and advances it independently. When H5 signs message A at leaf 1 and H6 signs a different message B at leaf 1, two messages share one WOTS-C one-time leaf. Two signatures under one one-time leaf yield a forgery that breaks the SHRINCS component, and the composite drops to classical-only security with no signal.
- The ordinary one-master-seed backup pattern triggers this.
Fix
Bind the construction's suite label and profile into the HKDF info for both components:
classical_seed = HKDF-Expand(prk, info = "classical/" ‖ Label, L = 32)
pq_seed = HKDF-Expand(prk, info = "pq/" ‖ Label, L = 32)
with Label the construction's registry label such as hybrid-sr25519-shrincs-256s-v1. A SHRINCS key then becomes a function of (master_seed, suite, profile, maxSignatures), and two suites cannot map to one tree.
Found during the SHRINCS-hybrid spec review (companion to hybrid signature spec v2.0, section 9). H5/H6 are proposed and not yet implemented, so there is no current deployed exposure — but the derivation should be suite-separated before any stateful suite merges.
Summary
quip-crypto-primitivesderives component seeds with a fixed HKDFinfo(b"pq"andb"classical") that does not vary by hybrid suite. Two different suites derived from the same master seed get the samepq_seedand the same classical seed. For the lattice suites this is a key-reuse concern that domain separation at signing time covers in practice. For the proposed stateful hash-based suites (H5 = ed25519+SHRINCS, H6 = sr25519+SHRINCS) it is worse. An identicalpq_seedyields a byte-identical SHRINCS signing key. Two independent signers then operate one stateful Merkle tree, reuse its one-time leaves, and compromise the key.Detail
HKDF_PQ_INFO = b"pq"andHKDF_CLASSICAL_INFO = b"classical", fixed for every suite —quip/primitives/crypto/src/seed.rs:16-40(path on branch v0.2).derive_component_seeds(master_seed)returns the samepq_seedfor H5 and H6 (and for H1/H3). SHRINCSkeygen(pq_seed, maxSignatures)is deterministic, so H5 and H6 from one master seed sharestateful_sk_seed,stateful_prf_seed, the leaf secrets,stateful_root, and the commitment.Fix
Bind the construction's suite label and profile into the HKDF
infofor both components:with
Labelthe construction's registry label such ashybrid-sr25519-shrincs-256s-v1. A SHRINCS key then becomes a function of(master_seed, suite, profile, maxSignatures), and two suites cannot map to one tree.Found during the SHRINCS-hybrid spec review (companion to hybrid signature spec v2.0, section 9). H5/H6 are proposed and not yet implemented, so there is no current deployed exposure — but the derivation should be suite-separated before any stateful suite merges.