Notebook/2026-05-11

Signing Is Not Sealing

Post-quantum signatures are entering supply-chain infrastructure. Any ML artifact signing profile that adopts ML-DSA should get one deployment detail right before it ships: randomized mode opens a 256-bit hidden command channel that no deployed verifier can inspect.

When you sign an ML model artifact, you are asserting two things: the artifact came from a trusted key, and it has not been modified. Both assertions are correct. A valid signature really does mean those things.

What it does not assert is anything about the signature itself.

This distinction matters for where ML signing is heading. Post-quantum signatures are entering supply-chain infrastructure. ML-DSA (CRYSTALS-Dilithium, standardized as FIPS 204) is the leading post-quantum signature scheme, already deployed in non-ML signing contexts and on the roadmap for broader supply-chain adoption. ML-DSA is a sound cryptographic choice. ECDSA’s security depends on the hardness of the elliptic curve discrete log problem, which a sufficiently large quantum computer could break. ML-DSA’s does not.

But any ML artifact signing profile that adopts ML-DSA should get one deployment detail right before it ships: randomized ML-DSA exposes a 256-bit signer-controlled hidden input in every signature that no deployed verifier can inspect, and that receiver code provisioned with the relevant signing-key-derived secret can use to test prearranged commands with perfect accuracy.


The free parameter

FIPS 204 describes the ML-DSA signing procedure in detail. The relevant step is this: compute rho_prime = H(K || rnd || mu, 64), where rnd is a 256-bit value provided by the signer. In the default randomized mode, rnd is sampled uniformly at random. In deterministic mode, it is set to 32 zero bytes.

Here is the key fact: rnd does not appear in the signature output.

An ML-DSA signature is a tuple (c_tilde, z, h). Verification checks a challenge equation involving z and h against c_tilde. None of that computation involves rnd directly. The nonce feeds into an internal hash that determines a mask polynomial; by the time verification runs, rnd is gone. Any 256-bit value produces a valid, indistinguishable signature.

This is a textbook subliminal channel. Simmons identified the construction in 1984. Young and Yung extended it to public-key schemes in 1996. The channel appears in any probabilistic signature scheme where the signer controls a free parameter that the verifier cannot observe. ML-DSA has exactly that structure. The nonce field rnd is free, 256 bits wide, and absent from the observable bytes.

To be precise about what the channel provides: the signer can embed any 256-bit value as rnd. A receiver that holds the signing key component K can test a pre-agreed 256-bit candidate against a signature in a single O(1) check. This is not arbitrary message recovery from the signature bytes. The receiver cannot decode an unknown rnd from the signature, even holding K. Holding K lets it test expected candidates efficiently. It is a prearranged command channel: the receiver verifies whether this signature corresponds to one of its expected commands, epoch seeds, or activation tokens. That distinction matters for the threat model, and it does not make the channel less dangerous. Prearranged commands are all a C2 system needs.

The deployment gap

Today’s deployed ML signing infrastructure does not expose this channel.

Sigstore cosign, which powers OpenSSF Model Signing v1.1.1, uses RFC 6979 deterministic ECDSA. RFC 6979 derives the signing nonce as k = HMAC(private_key, message_hash). That value is fully determined by the key and the message, and the Python cryptography library does not expose k to callers. Via the standard signing API there is no free parameter. The practical prearranged-command capacity of RFC 6979 ECDSA via the standard library API is zero: no signer-controlled entropy reaches the signature at the API boundary.

ML-DSA changes this. Any signing profile that adopts ML-DSA and uses the default randomized mode gains a 256-bit per-signature hidden choice field at the API level. This is not a flaw in FIPS 204. The randomized mode provides real value, specifically hedging against hardware fault attacks that could bias the signing computation. But in artifact signing contexts, where the threat model is a compromised or malicious signing workflow operating through the standard API, the tradeoff points the wrong way. The safe profile is simple to specify before adoption: use deterministic ML-DSA in the enforced signing path.

What a compromised signer can do

Assume an attacker has the signing key. They can already sign arbitrary artifacts and pass all provenance checks. The subliminal channel does not change what they can sign. It changes something more subtle: it turns the public signing infrastructure into a persistent, authenticated, one-to-many command and control channel.

Here is the concrete picture. The attacker compromises the signing key once. They also plant receiver code somewhere in the target’s model-loading pipeline: a malicious dependency, an SDK hook, a custom loader. That code is compiled with one piece of the signing key (K, the PRF component) and a protocol label. Then the attacker walks away.

From that point on, every model release is an instruction broadcast. When the signer publishes a new version, the receiver code running inside the target’s infrastructure, potentially across thousands of deployed instances, intercepts the signature bundle, reads the Rekor transparency log entry, and verifies a pre-agreed 256-bit value against the signature in a single check. If it matches, the receiver acts: rotates an epoch key, unlocks a dormant payload encrypted in the model weights, updates a trigger domain.

No network contact with the attacker. No encrypted traffic. No C2 server. No coordination observable after the initial implant. The Rekor transparency log, which exists specifically to make the signing ecosystem more auditable, is the delivery medium.

The Rekor property makes this worse than it sounds. Every entry is permanent and public. A receiver deployed months after the initial compromise can retroactively test every historical Rekor entry against its prearranged command set, identifying all matching signals since its secret was installed. If the legitimate owner rotates the signing key, the old entries in Rekor still exist and deployed receivers compiled with the old K can still verify them. The audit log that exists to detect compromise cannot be purged of the attacker’s traffic without destroying the audit record itself.

The weights pass a weight scanner. The signature passes a provenance verifier. The Rekor entry is public and looks like every other Rekor entry. The channel is in the structure of the signing scheme, and it hides in the infrastructure designed to expose it.

The auditor that cannot audit

The natural response is to build an entropy auditor. Run statistical tests on signature bytes. Look for bias. Compare batches from the same key.

We built that auditor. We ran a chi-squared uniformity test per signature, a two-sample Kolmogorov-Smirnov test across batches of 300 signatures from the same key, and a power analysis at batch sizes up to 50. We tested against honest signatures and against signatures encoding prearranged 256-bit commands via our construction.

The KS p-value comparing honest batches to subliminal batches was 0.81. The detection power was 0.08 at N=10 and 0.02 at N=50. Both should be 0.05 if the test has any signal. They are not. The power curve is flat at the false-positive rate.

The reason is not computational difficulty. rnd is absent from the observable signature bytes. An auditor inspecting (c_tilde, z, h) has no statistical path to the hidden rnd values at the signature-byte layer. This is structural, not a matter of test sophistication or sample count.

We release the auditor as manta-defend-sig-entropy, part of the manta-defend defender suite. It correctly returns “undetectable” on every subliminal batch we tested. That verdict is the point. The tool demonstrates the gap.

The threshold case

The single-signer ML-DSA case requires compromise of the full signing key. The multi-party case is worse.

FROST threshold Schnorr signing, which is what sigstore’s experimental multi-party path uses, gives each signer control over its nonce contribution. A single compromised signer in a k-party scheme can embed a 256-bit prearranged command in its nonce contribution via an HKDF-based construction. The other k-1 honest signers produce a valid aggregate signature and cannot detect the bias. The threshold architecture distributes the key to prevent forgery; it does not prevent a single insider from operating a command channel.

We tested this with a 2-of-3 FROST implementation over secp256k1. 100 of 100 signing sessions produced valid aggregate signatures. KS p-value on the compromised signer’s nonce commitment distribution was 0.81. Command verification accuracy for pre-agreed candidates: TP=1.00, FP=0.00.

The fix is one line

FIPS 204 specifies a deterministic signing mode where rnd = 0^256. Under this constraint, the internal nonce derivation is fully determined by the secret key and the message hash. The signer has no freedom. The channel closes.

Any ML artifact signing profile that adopts ML-DSA should specify deterministic mode explicitly: rnd = b"\x00" * 32 in the signing wrapper. This is far easier to get right in the initial signing profile than to mandate retroactively after signed artifacts are already in production.

One important note: mandating deterministic mode is not publicly verifiable from the signature alone. A verifier receiving (c_tilde, z, h) cannot confirm that rnd was set to zero. The fix works by making the standard signing path subliminal-free when the signing wrapper or signing service is the enforced interface. Implementation hardening, not a cryptographic guarantee the verifier can check. That is still the right thing to mandate before deployment.

Scope and responsible disclosure

To be precise about what is and is not at risk today: OpenSSF Model Signing v1.1.1 uses ECDSA via the Python cryptography library, which does not expose the nonce k to callers. There is nothing exploitable in the current deployed system. This is not a claim about a scheduled OpenSSF Model Signing ML-DSA migration. Sigstore confirmed no such migration is currently planned. It is forward-looking deployment guidance for any ML artifact signing profile that adopts ML-DSA.

We notified the OpenSSF Model Signing maintainers and sigstore prior to publishing. This is not a CVE. The subliminal channel is a documented design freedom in FIPS 204. The responsible action is a signing profile specification that mandates deterministic mode from day one.

What we are releasing

The paper: “Signing Is Not Sealing: Subliminal Channels in ML Artifact Provenance Schemes” covers the full ML-DSA single-signer construction, the FROST threshold variant, the power analysis, the composed threat model, and the responsible disclosure details. Preprint at 10.5281/zenodo.20127558.

The code: manta-defend-sig-entropy implement the entropy auditor described above. The subliminal signing PoC is available under a research-access agreement rather than an open license, for the usual dual-use reasons.

If you maintain signing infrastructure that is planning or considering an ML-DSA migration, the ask is simple: add rnd = b"\x00" * 32 to your signing call before you ship.


This post is part of the Manta research program on ML supply chain security.