
A Detailed Elliptic Curve Cryptography Tutorial - 68c12c16
https://www.johannes-bauer.com/compsci/ecc/
======
runeks
Certicom also has a good tutorial on ECC:
[https://www.certicom.com/content/certicom/en/ecc-
tutorial.ht...](https://www.certicom.com/content/certicom/en/ecc-
tutorial.html)

Certicom authored the curve used by Bitcoin (secp256k1).

------
zmonx
Thank you for sharing! Beware though: The scalar point multiplication method
that is shown in the article is subject to side channel attacks such as timing
attacks, since it depends on features of the secret key. Use Montgomery
multiplication or similar methods to mitigate this.

------
loup-vaillant
This looks nice. Too bad I care more about Montgomery and Twisted Edwards
curves (everyone say curve255129 and edDSA are great, and I believe them).

I'm looking for _one_ thing, which I hope should speed up signature and
verification speed with very little bloat: converting a Twisted Edwards point
to Montgomery space, then back (with that sign recovery trick after the
Montgomery ladder).

Reading (and trying to apply) the relevant papers has been frustrating so far
(I get wrong results), and I can't find code (or pseudo-code) I can use. Have
someone implemented this?

~~~
pbsd
What exactly is the problem? Converting between Montgomery and twisted Edwards
is well documented by now, for example in [3, Theorem 3.2] or RFC 7748. The
descriptions in, e.g., [1, §3.2] or [2, §4.3] for the Montgomery y-recovery
trick are pretty straightforward.

[1]
[https://link.springer.com/chapter/10.1007/3-540-44709-1_12](https://link.springer.com/chapter/10.1007/3-540-44709-1_12)

[2] [https://eprint.iacr.org/2017/212](https://eprint.iacr.org/2017/212)

[3] [https://eprint.iacr.org/2008/013](https://eprint.iacr.org/2008/013)

~~~
loup-vaillant
The problem is, the following code doesn't work:

    
    
      sv ge_scalarmult(ge *p, const ge *q, const u8 scalar[32])
      {
          // convert q to montgomery format
          fe x1, y1, z1, x2, z2, x3, z3, t1, t2, t3, t4;
          fe_sub(z1, q->Z, q->Y);
          fe_mul(z1, z1, q->X);
          fe_invert(z1, z1);
          fe_add(t1, q->Z, q->Y);
          fe_mul(x1, q->X, t1  );
          fe_mul(x1, x1, z1);
          fe_mul(y1, q->Z, t1  );
          fe_mul(y1, y1, z1);
          fe_1(z1); // coherence
      
          // montgomery scalarmult
          x25519_ladder(x1, x2, z2, x3, z3, scalar);
      
          // recover the y1 coordinate
          fe_mul(t1, x1, z2);  // t1 = x1 * z2
          fe_add(t2, x2, t1);  // t2 = x2 + t1
          fe_sub(t3, x2, t1);  // t3 = x2 − t1
          fe_sq (t3, t3);      // t3 = t3^2
          fe_mul(t3, t3, x3);  // t3 = t3 * x3
          fe_mul973324(t1, z2);// t1 = 2a * z2
          fe_add(t2, t2, t1);  // t2 = t2 + t1
          fe_mul(t4, x1, x2);  // t4 = x1 * x2
          fe_add(t4, t4, z2);  // t4 = t4 + z2
          fe_mul(t2, t2, t4);  // t2 = t2 * t4
          fe_mul(t1, t1, z2);  // t1 = t1 * z2
          fe_sub(t2, t2, t1);  // t2 = t2 − t1
          fe_mul(t2, t2, z3);  // t2 = t2 * z3
          fe_add(t1, y1, y1);  // t1 = y1 + y1
          fe_mul(t1, t1, z2);  // t1 = t1 * z2
          fe_mul(t1, t1, z3);  // t1 = t1 * z3
          fe_mul(x1, t1, x2);  // x1 = t1 * x2
          fe_sub(y1, t2, t3);  // y1 = t2 − t3
          fe_mul(z1, t1, z2);  // z1 = t1 * z2
      
          // convert back to twisted edwards
          fe_sub(t1  , x1, z1);
          fe_add(t2  , x1, z1);
          fe_mul(p->X, x1, t2);
          fe_mul(p->Y, y1, t1);
          fe_mul(p->Z, y1, t2);
          fe_mul(p->T, x1, t1);
      }
    

This is supposed to be a straightforward application of the first link you
provided. I have no freaking idea what I did wrong. I can only say thef
x25519_ladder() function is correct, because it gives the correct results for
Diffie-Hellman.

I'm not sure your Last 2 links contain the information I want. RFC 7748 is of
no help whatsoever (I already have a correct curve25519 implementation).

~~~
pbsd
Your conversion between Edwards and Montgomery is not quite correct. I suspect
that is why you're getting different results (though I didn't really go over
the whole thing). RFC 7748 does include the correct conversion routines in
page 4: ((1+y)/(1-y), sqrt(-486664) * ((1+y)/(1-y))/x) to go from ed25519 to
x25519, and (sqrt(-486664) * u/v, (u-1)/(u+1)) to go back. So with some luck,
you're only missing 2 multiplications by a constant.

~~~
loup-vaillant
Okay, I went through my sources, and remembered I got my conversion from
Wikipedia¹. Strangely, Wikipedia gives a different map than the RFC. (One DJB
paper agrees with the RFC, so either the Wikipedia is wrong, or I'm missing
something.) That's why I didn't multiply by any constant.

I have a problem however: how do I find the modular square root of -486664?

[1]:
[https://en.wikipedia.org/wiki/Montgomery_curve#Equivalence_w...](https://en.wikipedia.org/wiki/Montgomery_curve#Equivalence_with_twisted_Edwards_curves)

~~~
pbsd

        sage: p=2^255-19
        sage: sqrt(GF(p)(-486664))
        6853475219497561581579357271197624642482790079785650197046958215289687604742
    

The formula in Wikipedia is not wrong, but note that it maps E_{a,d} to M_{A,
B} with B = 4/(a - d) = -486664. curve25519, and pretty much every Montgomery
curve, is defined with B = 1, so you need some extra twisting to get there.

~~~
loup-vaillant
Excellent, thank you. I'll get on it right away.

------
jerianasmith
The scalar point multiplication method is vulnerable as it can be attacked as
feature key in this case is very important

