← Writing

November 22, 2023

ECDSA: Detecting the Reuse of k

Many people are familiar with the PS3 exploit discovered in 2010 by the fail0Overflow group. This exploit was the result of Sony reusing the value kk in their implementation of the Elliptic Curve Digital Signature Algorithm. By reusing the value for kk, the private key can be directly calculated (the details of which can be seen here)

But the answer to “how do you detect kk being reused” isn’t as prevalent. In order to detect that kk is being reused, we can take advantage of the nature of elliptic curves in Zp\mathbb{Z}_p for some prime pp.

We know that the signature (r,s)(r, s) can be expressed as:

  1. r=xkPmod  qr = x_{kP} \mod q
  2. s=k−1(h+αr)mod  qs = k^{-1}(h + \alpha r) \mod q

where:

Here’s our first clue: rr does not change if kk stays the same. This isn’t enough to conclude that the same kk is being used, but it is the first indicator.

There are at most two points which have the same x-value on the usual short-Weierstrass curves over Zp\mathbb{Z}_p for an odd prime pp. However, taking mod  q\mod q can make different x-values produce the same rr. So seeing the same rr three times does not guarantee that kk was reused.

For two signatures from the same key with the same rr, we can test the assumption that kk was reused. Subtracting their signature equations gives (s1−s2)k=h1−h2mod  q(s_1-s_2)k = h_1-h_2 \mod q, so:

k=(h1−h2)(s1−s2)−1mod  q,α=(s1k−h1)r−1mod  q.k = (h_1-h_2)(s_1-s_2)^{-1} \mod q, \qquad \alpha = (s_1k-h_1)r^{-1} \mod q.

This requires s1≠s2mod  qs_1 \ne s_2 \mod q and different h1h_1 and h2h_2 modulo qq; collecting the same signature repeatedly does not help. The inverses are modular inverses modulo qq. Since kk and q−kq-k also produce the same rr, we should also try replacing s2s_2 with −s2-s_2 when the resulting denominator is nonzero.

Then, you can check each candidate against the known public key: compute αP\alpha P and see whether it matches. A candidate nonce must also be nonzero and produce the observed rr.

With three signatures sharing rr, we have three pairs to try. Testing kk and q−kq-k gives us at most six candidate private keys before filtering. At most one will match the public key.