confium-composite — composite signatures
Composite multi-algorithm signatures for post-quantum migration. A single composite signature contains the artifacts of multiple component algorithms (e.g. Ed25519 + ECDSA-P256 + ML-DSA-65); verifiers check all components and accept the signature only if every component verifies.
When to use this crate
Use confium-composite when:
- You are migrating from a classical algorithm (Ed25519, ECDSA) to a post-quantum one (ML-DSA, SLH-DSA) and need both to verify simultaneously during the transition.
- You want defense-in-depth: a break in any single algorithm does not compromise the composite signature.
- You are building a transparency log leaf hash or a certificate signature that must remain verifiable across the PQ transition.
Public API
The crate exposes a CompositeSignature value type. Verification
takes a closure that dispatches per component — you supply the
verifier for each algorithm the composite contains.
use confium_composite::{CompositeSignature, ed25519_verifier, ED25519};
let composite: CompositeSignature = /* ... */;
let result = composite.verify(&message, |alg, pk, msg, sig| {
if alg == ED25519 {
ed25519_verifier(alg, pk, msg, sig)
} else {
// Route other algorithms to their verifiers.
Err(format!("no verifier for \{alg\}"))
}
})?;
// result.all_verified — true iff every component verified
// result.per_component — Vec<ComponentResult> with per-algorithm detail
Built-in verifiers ship for Ed25519 (ed25519_verifier) and
ECDSA-P256 (p256_verifier). Route other algorithms through your
own backend (Botan plugin, OpenSSL provider) inside the closure.
Verification semantics
A composite signature is valid if and only if:
- Every component signature verifies against the message.
- Every required component algorithm is registered with the verifier.
- The component set matches the deployment’s policy (e.g. the jurisdictional policy may require ≥1 classical + ≥1 PQ algorithm).
A missing verifier for any component is a hard failure, not a soft-accept. Include every algorithm the deployment expects to encounter in your verify closure.
Security notes
- No silent downgrade: if a verifier is missing for a component, verification fails. The crate never silently accepts on the subset of components it can verify.
- Callback isolation: per-algorithm verification runs as isolated closure invocations. An error in one does not short-circuit the others; each result is collected and AND-reduced at the end.
- Constant-time where it matters: the per-algorithm verifiers supplied by the caller are responsible for their own constant-time guarantees. The composite layer does not introduce branches that depend on secret data.
- Order independence: the composite signature lists components in a deterministic order; verification does not depend on the order the per-algorithm verifiers are registered.
Related
confium-transparency— uses composite signatures for tree head signatures.- PQ migration example — end-to-end walkthrough.
- PQ migration concept page on the public website.