Score:2

Invalid point attack on quadratic twist of Elliptic Curve when -1 is a quadratic residue

ma flag

I'm replicating an invalid point attack on ECC using Short Weierstrass curves. For this I have written a "dumb" implementation that does not validate points are on the curve before going into the scalar multiplication. For the outline of the attack, I'm heavily borrowing from Samuel Neves' excellent descrption which he gave here: Understanding Twist Security with respect to short Weierstrass curves

I can replicate this without any issue when $d = -1$ is a quadratic non-residue in $\mathbb{F}_p$, then everything works out-of-the-box. However, when $p$ is so that $-1$ is a quadratic residue and therefore I need to choose a different value for $d$, everything falls apart.

For simplicity, in the first run I am not using curves in $\mathbb{F}_{p^2}$ because for small $p$ exhaustive enumeration to find low-order points is not an issue.

As an example, say my curve is defined over $\mathbb{F}_{101}$; here, $-1$ is a quadratic residue mod $p$, since $10 \cdot 10 = -1 \mod 101$. My curve is given by

$E: y^2 = x^3 + 13x + 29$

And with $d = 2$, a quadratic non-residue mod 101,

$E^d: y^2 = x^3 + 52x + 30$

The order of $E^d$ is $111 = 3 \cdot 37$. I have chosen two points on $E^d$ which have orders 3 and 37, respectively:

$P_1 = (28, 62)$

$P_2 = (8, 7)$

When I run these values through my scalar multiplication without point validation (for private key $d = 58$, I get the following output:

$S_1 = (94, 53)$

$S_2 = (32, 14)$

Neither $S_1$ nor $S_2$ is a point on the quadratic twist $E^d$. I can lift either X coordinate in $E^d$, but then the orders of the points are wrong.

Here's my example code:

Fp = GF(101)
D = Fp(2)
    
print(D, "is square?", D.is_square())
(a, b) = (13, 29)

E = EllipticCurve(Fp, [a, b])
Et = EllipticCurve(Fp, [ a*D^2, b*D^3 ])

print("Et.order()", factor(Et.order()))

attack_points = [
    Et(28, 62),
    Et(8, 7),
]
print(E)
print(Et)
for P in attack_points:
    print(P, P.order())

# private key d = 58
mul_results = [ 
    Et(94, 53), 
    Et(32, 14), 
]
#print(Et.lift_x(94).order())
#print(Et.lift_x(32).order())

Which outputs:

2 is square? False
Et.order() 3 * 37
Elliptic Curve defined by y^2 = x^3 + 13*x + 29 over Finite Field of size 101
Elliptic Curve defined by y^2 = x^3 + 52*x + 30 over Finite Field of size 101
(28 : 62 : 1) 3
(8 : 7 : 1) 37
TypeError: Coordinates [94, 53, 1] do not define a point on Elliptic Curve defined by y^2 = x^3 + 52*x + 30 over Finite Field of size 101

How can I perform this attack for a quadratic twist where $d \neq -1$?

kelalaka avatar
in flag
It might not be your problem. The original code is also not working on SageMath anymore. High probably there is a change in the library that prevents such calculations...
ma flag
I don't have enough reputation to comment in the other post, but the solution by Neves works, just not out of the box: The print statements need parenthesis and the .lift_x(randint(...)) calls needs to be replaced by .lift_x(K(randint(...))), then everything works like a charm. I could reproduce it perfectly with d = -1, but as I wrote -1 is a quadratic residue in some fields (like GF(101), as shown here).
kelalaka avatar
in flag
I've modified the answer, could you also check that?
ma flag
Thanks, the code over there works now, but still doesn't address my question (i.e., it explicitly uses d = -1) -- any idea how to get it running with a different d?
kelalaka avatar
in flag
Yes, I know. Algebraic geometry ( elliptic curves are part of it ) should be done on the algebraic closure. Samuel Neves's answer, as you can see, works on the closure, you are not.
kelalaka avatar
in flag
See Curve25519'paper on small-subgroup attack.
Ruggero avatar
kr flag
I suppose that with d!=-1 you need to convert your point from $E$ and $E^{d}$ and you can't just use the plain x coordinate. It would help if you can post a sage script for your scalar multiplication as the use of $y$ confuses me, why not making an invalid curve attack (without bothering with the twist) ?
ma flag
@kelalaka The example I'm giving here is for simplicity only -- he works on the quadratic extension field, but that also does not work for d != -1 if you modify his script to use other domain parameters. I.e., that is not the root cause of the issue, I fear. I just omitted it here for brevity to have a minimal example that demostrates the issue.
ma flag
@Ruggero I overlooked your respose. Yes I do believe some conversion is needed, but I cannot figure out how: Before putting it as input to the ladder or after the output of the ladder (or possibly both). Some conversion is most definitely needed and also note that -1^2 = 1, i.e. if an even power was multiplied/divided by, we'd never know in the d=-1 case. Your remark about the X-only ladder is correct. In my desparation I tried it all: Simple mul-and-add (works also for d=-1!), Brier/Joye X-ladder and additive X-only ladders. They all compute properly, so I'm missing the conversion for sure.
Score:0
ma flag

This is not a problem of d being a QNR that is not -1.

Instead, it is a problem of small moduli. I can demonstrate this reliably using a modified script of Samuel Neves: Invalid point attack yields wrong results for low order points

This does not answer at all why it does not work, but at least this demonstrates that $d \neq -1$ is not the root cause of my issue.

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.