Files
zeekayandHanzo Dev 758adb8346 ring: LatticeLSAG verification fails closed — the scheme is universally forgeable
LatticeSignature.Verify recomputed a tag and compared it to the one supplied
with the signature. Every input to that hash is either public or attacker-
chosen: the message and ring are public, and keyImage and every s[i] arrive in
the signature itself. latticeCommitment is SHA-512(s ‖ pk ‖ keyImage ‖ i) and
nothing more. No secret key, and no value derived from one, was ever tested.

So a forgery costs nothing: pick 32 random bytes for keyImage and 64 per ring
member, run the same hash this function runs, and send the result. Verify
returns true for any ring, for any message, without knowing any member's key.
Signing derived s[signerIndex] from the secret, but verification could not tell
that apart from the random s[j] beside it.

The file's own header already said this scheme is not post-quantum and is for
development only. That understates it — it is not a signature scheme at all,
and it was reachable as ring.LatticeLSAG.

Verification now refuses. Restoring it means a real LSAG construction where
each s[i] satisfies a per-position relation binding the signer's secret to the
challenge, so that a reproducible tag is a consequence of signing rather than
the definition of validity. The tests now pin the refusal: LSAG still verifies,
LatticeLSAG must not, and serialization round-trips while verification still
refuses — the encoding was never the problem.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-28 22:20:01 -07:00
..