Skip to content

Commit

Permalink
Improve comments/checks for fe_sqrt
Browse files Browse the repository at this point in the history
  • Loading branch information
sipa committed May 11, 2023
1 parent 6ab3508 commit be82bd8
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 8 deletions.
14 changes: 8 additions & 6 deletions src/field.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,12 +246,14 @@ static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp2
*/
static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a);

/** If a has a square root, it is computed in r and 1 is returned. If a does not
* have a square root, the root of its negation is computed and 0 is returned.
* The input's magnitude can be at most 8. The output magnitude is 1 (but not
* guaranteed to be normalized). The result in r will always be a square
* itself. */
static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a);
/** Compute a square root of a field element.
*
* On input, a must be a valid field element with magnitude<=8; r need not be initialized.
* Performs {r = sqrt(a)} or {r = sqrt(-a)}, whichever exists. The resulting value
* represented by r will be a square itself. Variables r and a must not point to the same object.
* On output, r will have magnitude 1 but will not be normalized.
*/
static int secp256k1_fe_sqrt(secp256k1_fe * SECP256K1_RESTRICT r, const secp256k1_fe * SECP256K1_RESTRICT a);

/** Sets a field element to be the (modular) inverse of another. Requires the input's magnitude to be
* at most 8. The output magnitude is 1 (but not guaranteed to be normalized). */
Expand Down
17 changes: 15 additions & 2 deletions src/field_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,13 @@ static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a) {
* itself always a square (a ** ((p+1)/4) is the square of a ** ((p+1)/8)).
*/
secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1;
int j;
int j, ret;

#ifdef VERIFY
VERIFY_CHECK(r != a);
secp256k1_fe_verify(a);
VERIFY_CHECK(a->magnitude <= 8);
#endif

/** The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in
* { 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block:
Expand Down Expand Up @@ -141,7 +145,16 @@ static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a) {
/* Check that a square root was actually calculated */

secp256k1_fe_sqr(&t1, r);
return secp256k1_fe_equal(&t1, a);
ret = secp256k1_fe_equal(&t1, a);

#ifdef VERIFY
if (!ret) {
secp256k1_fe_negate(&t1, &t1, 1);
secp256k1_fe_normalize_var(&t1);
VERIFY_CHECK(secp256k1_fe_equal_var(&t1, a));
}
#endif
return ret;
}

#ifndef VERIFY
Expand Down

0 comments on commit be82bd8

Please sign in to comment.