Skip to content

Conversation

@suyash67
Copy link
Contributor

@suyash67 suyash67 commented Jan 26, 2026

Fixes two issues found by @guidovranken in our ecdsa circuit.

Issue 1: Point-at-Infinity in ecdsa verification

ecdsa verification can lead to a point at infinity for carefully crafted signature $(r, s)$ with message $z$:

$$u_1 \cdot G + u_2 \cdot P = \mathcal{O}$$

where $u_1 = z/s \bmod n$, $u_2 = r/s \bmod n$, and $\mathcal{O}$ is the point at infinity ($n$ is the scalar field modulus of secp256k1). We do not allow the output of ecdsa mul to be point at infinity in the ecdsa circuit, so by design such signatures will not be able to generate a satisfying proof. However, the boolean output of the ecdsa verification must also be false in those cases. The bug is that the output of the ecdsa verification is still true even if the ecdsa mul is a point at infinity. The fix is to update the boolean output of the ecdsa verification to ensure the mul result is not a point at infinity.

Issue 2: NAF Reconstruction $2^{136}$ Overflow

In compute_naf() function in biggroup, if the input scalar is even (skew = 1) and its least-significant $2L$ bits (where $L = 68$ limb size) are all 0 then there is an overflow in reconstructing the lower half of the scalar. For a 256-bit scalar $a$ ($N = 256$) with skew $\mathfrak{s}_a \in {0, 1}$ we reconstruct it as

$$ \begin{aligned} a &= \underbrace{\sum_{i=0}^{N-2} (1 - a'_{i+1}) \cdot \textcolor{grey}{2^{i}}}_{\textsf{positive part}} - \underbrace{\left(\mathfrak{s}_a + \sum_{i=0}^{N-2} a'_{i+1} \cdot \textcolor{grey}{2^{i}} \right)}_{\textsf{negative part}}. \\ \end{aligned} $$

where $a'_1, a'_2, \dots, a'_{N-1}$ are inverted bits of $a$ (that is, $a'_{i+1} = 1 - a'_{i+1}$). See biggroup README for more details.

We reconstruct the positive and the negative parts separately, and each of those parts is a bigfield element (non-native). So while reconstructing the negative part's lower $2L$ bits, we have:

$$ \textsf{negative}_{\textsf{lo}} := \mathfrak{s}_a + \sum_{i=0}^{2L-1} a'_{i+1} \cdot \textcolor{grey}{2^i} $$

This overflows when $a'_{i+1} = 1$ for all $i \in [0, 2L)$. So we need to detect such overflow and then carry it over the higher limb of the negative part.

More details on the issues: https://hackmd.io/JZ_uFRZPTvq4rOVcwNuX9A?view

…n result

The ECDSA verification was missing a constraint to enforce that the result
of the batch multiplication (u1*G + u2*P) is not the point at infinity.
This allowed crafted signatures to bypass verification in the circuit.

The fix adds an assertion that fails the circuit when the result is infinity,
matching the documented constraint in the docstring (constraint 6).

Also updates the test expectations for Secp256k1NativeStdlibDiscrepancy to
expect circuit failure since the attack scenario now correctly fails.
}
}

TEST(EcdsaTests, Secp256k1PointAtInfinityRegression)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm keeping regression tests separate from the main test suite

Copy link
Contributor

@federicobarbacovi federicobarbacovi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for doing this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants