- * First of all, a complicated exponentation. The addition chain here is
- * mine. We start with some preliminary values.
- */ /* step | value */
- SQRN(&u, y, 1); /* 1 | 0, 2 */
- f25519_mul(&t, &u, y); /* 2 | 0, 3 */
- f25519_mul(&xy3, &t, x); /* 3 | 1, 3 */
- SQRN(&u, &u, 1); /* 4 | 0, 4 */
- f25519_mul(&w, &u, &xy3); /* 5 | 1, 7 */
-
- /* And now we calculate w^((p - 5)/8) = w^(252 - 3). */
- SQRN(&u, &w, 1); /* 6 | 2 */
- f25519_mul(&t, &w, &u); /* 7 | 3 */
- SQRN(&u, &t, 1); /* 8 | 6 */
- f25519_mul(&t, &u, &w); /* 9 | 7 */
- SQRN(&u, &t, 3); /* 12 | 56 */
- f25519_mul(&t, &t, &u); /* 13 | 63 = 2^6 - 1 */
- SQRN(&u, &t, 6); /* 19 | 2^12 - 2^6 */
- f25519_mul(&t, &t, &u); /* 20 | 2^12 - 1 */
- SQRN(&u, &t, 12); /* 32 | 2^24 - 2^12 */
- f25519_mul(&t, &t, &u); /* 33 | 2^24 - 1 */
- SQRN(&u, &t, 1); /* 34 | 2^25 - 2 */
- f25519_mul(&t, &u, &w); /* 35 | 2^25 - 1 */
- SQRN(&u, &t, 25); /* 60 | 2^50 - 2^25 */
- f25519_mul(&t2p50m1, &t, &u); /* 61 | 2^50 - 1 */
- SQRN(&u, &t2p50m1, 50); /* 111 | 2^100 - 2^50 */
- f25519_mul(&t, &t2p50m1, &u); /* 112 | 2^100 - 1 */
- SQRN(&u, &t, 100); /* 212 | 2^200 - 2^100 */
- f25519_mul(&t, &t, &u); /* 213 | 2^200 - 1 */
- SQRN(&u, &t, 50); /* 263 | 2^250 - 2^50 */
- f25519_mul(&t, &t2p50m1, &u); /* 264 | 2^250 - 1 */
- SQRN(&u, &t, 2); /* 266 | 2^252 - 4 */
- f25519_mul(&t, &u, &w); /* 267 | 2^252 - 3 */
-
- /* And finally... */
- f25519_mul(&beta, &t, &xy3); /* 268 | ... */
-
- /* Now we have beta = (x y^3) (x y^7)^((p - 5)/8) = (x/y)^((p + 3)/8), and
- * we're ready to finish the computation. Suppose that alpha^2 = u/w.
- * Then beta^4 = (x/y)^((p + 3)/2) = alpha^(p + 3) = alpha^4 = (x/y)^2, so
- * we have beta^2 = ±x/y. If y beta^2 = x then beta is the one we wanted;
- * if -y beta^2 = x, then we want beta sqrt(-1), which we already know. Of
- * course, it might not match either, in which case we fail.