PQC-XXJTLU · cryptanalysis

HomePublic-key schemes › FlexTree

Signature · hash-based

FlexTree

Design

flextree-1

The specified verifier omits the one-time signature's encoding checks

Minor break · Argued · Cause: specification text

Property: existential unforgeability, for verifiers that follow the specification

Cost against claim: forgery ≈240.4 on FlexTree-160s, for a verifier that follows the specification

Scope: Verifiers written from the specification. The submitted code performs the checks and is not affected.

The specified signer accepts a one-time digest only when its leading bits are zero and its digits have the required constant sum; the specified verifier (Algorithm 10, and the abstract verifier of Construction 1) enforces neither. A verifier that follows the text accepts a checksum-free Winternitz signature, forgeable by advancing the chains of one genuine signature.

Parameter setClaimAttack costVerdict
FlexTree-160s160 classical≈240.4 (reporter's figure)Minor break
other setsnot computednot recomputed by PQC-Xnot computed

Evidence

The omission was checked in the specification, and the submitted code was checked to enforce both conditions. The cost figure is the reporter's; PQC-X has not recomputed it for FlexTree (it computed the same attack for CEDRUS+C).

Cause in the specification, traced to the specification text.

Limits

Only an implementation written from the specification is forgeable.

Credit

Found by Mikhail Kudinov (ngcc.dev sign-11-3, 2026-09-22). Reproduced by PQC-X.

flextree-3

Unread padding makes signatures malleable

Holds · Demonstrated · Cause: specification text

Property: strong unforgeability; existential unforgeability holds

Cost against claim: a second valid signature from any signature; EUF-CMA holds

A PORS+FP signature is zero-padded to a fixed number of authentication nodes, and the verifier does not read the padding. Flipping a padding bit yields a different signature that still verifies. The call accepts EUF-CMA, so no requirement is missed, but the scheme is not strongly unforgeable.

Parameter setClaimAttack costVerdict
all FlexTree setsEUF-CMAone valid signatureHolds

Evidence

On FlexTree-160f: flipping either trailing all-zero slot still verifies, while flipping any of the 153 real nodes is rejected.

Cause in the specification, traced to the specification text.

Credit

First public report: Mikhail Kudinov (ngcc.dev sign-11-5, 2026-09-22). Found independently by PQC-X.

flextree-2

The subset counter re-rolls subsets on a fixed few-time instance

Holds · Argued · Cause: construction

Property: the designers' independence premise; the security level holds

Cost against claim: fewer message-hash calls, same total hash work: no level falls

The message hash fixes the few-time instance first; a 32-bit counter then re-draws only the subset within that instance until forced pruning succeeds. The designers' bound treats every trial as a fresh instance, so its premise does not hold. What the grinding saves, however, is message-hash calls, not hash work: the total cost of a forgery stays 28n.

Parameter setClaimAttack costVerdict
all FlexTree sets8ntotal hash work 28n, unchangedHolds

Evidence

Two-budget recomputation: total hash complexity 1/p̄ = 2160 / 2256 / 2384 / 2512, unchanged; the message-hash call count drops by 32 bits (to 2128 / 2224 / 2352 / 2480), because 232 · p1(q) < 1 for every relevant instance load.

Cause in the specification, traced to the specification text.

What PQC-X adds

The impact, measured in the call's metric. The reduction applies to the number of message-hash calls only; the total hash complexity of a forgery, which the call scores, stays at the claimed level. So no security level falls.

Credit

Found by Mikhail Kudinov (ngcc.dev sign-11-1, 2026-09-22). Reproduced by PQC-X.

flextree-4

The specified PORS tree reuses leaf hash addresses

Holds · Argued · Cause: specification text

Property: distinct-tweak premise of the security discussion

Cost against claim: one bit of generic multi-target loss

Height-1 leaves of the specified PORS tree are hashed with the same address as height-0 leaves, so hundreds to tens of thousands of tweaks per instance are used for two secret values. The loss is one bit on that path; the submitted code is not affected.

Parameter setClaimAttack costVerdict
specification-conformant implementationsdistinct tweaksone bitHolds

Evidence

Cause in the specification, traced to the specification text.

Credit

Found by Mikhail Kudinov (ngcc.dev sign-11-6, 2026-09-22). Reproduced by PQC-X.

flextree-5

SM3's 256-bit state caps the 384- and 512-bit sets

Holds · Argued · Cause: parameter size · not counted

Property: not counted: SM3 is the call's placeholder

Cost against claim: not counted: a limit of the placeholder hash, not of FlexTree

The 384- and 512-bit sets stretch SM3 with a counter-mode XOF, so their internal state is SM3's 256 bits and generic preimages cost at most 2256. The call supplies SM3 only to check correctness and measure performance, explicitly without considering its security, and announces new hash functions for later rounds. PQC-X therefore judges every design at the lengths it specifies, with an ideal hash, and does not count this against FlexTree.

Parameter setClaimAttack costVerdict
FlexTree-384s/f, -512s/f384 / 512 classical≤ 2256 with SM3; not countedHolds

Evidence

Cause in the specification, traced to the specification text.

Credit

Reported by Mikhail Kudinov (ngcc.dev sign-11-4, 2026-09-22).

Implementation

Bugs in the submitted code; the specification is sound on these points.

flextree-i1

The code leaves 1 to 4 one-time digest bits unchecked

Holds · Argued · Cause: code

Property: second-preimage resistance of the one-time digest path

Cost against claim: 1 to 4 bits below 8n on one path

The code takes the one-time digits from the leading 8n − zb digest bits but tests the high zb bits of the final byte; for seven sets the two regions overlap, leaving 1 to 4 bits neither encoded nor checked. Not the cheapest attack on the scheme.

Parameter setClaimAttack costVerdict
seven sets (not 384s)8n28n − 1 to 28n − 4: fewer than 8 bits under the claimHolds

Evidence

Cause in the submitted code; the specification is not affected.

Credit

Found by Mikhail Kudinov (ngcc.dev sign-11-7, 2026-09-22). Reproduced by PQC-X.

flextree-i2

FlexTree-384f and -512s accept the ceiling of the specified digit sum

Holds · Argued · Cause: code

Property: conformance; no security loss from the rounding alone

Cost against claim: an off-by-one between specification and code

The code compares the complementary digit sum with the specified constant, which accepts the ceiling instead of the floor when Σ(w_i − 1) is odd, as for these two sets.

Parameter setClaimAttack costVerdict
FlexTree-384f, -512sspecified digit sumnoneHolds

Evidence

Cause in the submitted code; the specification is not affected.

Credit

Found by Mikhail Kudinov (ngcc.dev sign-11-8, 2026-09-22). Reproduced by PQC-X.