sqrt method

  1. @override
ECFieldElement? sqrt()
override

return a sqrt root - the routine verifies that the calculation returns the right value - if none exists it returns null.

Implementation

@override
ECFieldElement? sqrt() {
  if (!_testBit(q!, 0)) {
    throw UnimplementedError('Not implemented yet');
  }

  // p % 4 == 3
  if (_testBit(q!, 1)) {
    // z = g^(u+1) + p, p = 4u + 3
    var z = ECFieldElement(q, x!.modPow((q! >> 2) + BigInt.one, q!));
    return z.square() == this ? z : null;
  }

  // p % 4 == 1
  var qMinusOne = q! - BigInt.one;

  var legendreExponent = qMinusOne >> 1;
  if (x!.modPow(legendreExponent, q!) != BigInt.one) {
    return null;
  }

  var u = qMinusOne >> 2;
  var k = (u << 1) + BigInt.one;

  var Q = x!;
  var fourQ = (Q >> 2) % q!;

  BigInt U, V;
  var rand = SecureRandom();
  do {
    BigInt? P;
    do {
      P = rand.nextBigInteger(q!.bitLength);
    } while ((P >= q!) ||
        (((P * P) - fourQ).modPow(legendreExponent, q!) != qMinusOne));

    var result = _lucasSequence(q!, P, Q, k);
    U = result[0];
    V = result[1];

    if (((V * V) % q!) == fourQ) {
      // Integer division by 2, mod q
      if (_testBit(V, 0)) {
        V = V + q!;
      }

      V = V >> 1;

      //assert V.multiply(V).mod(q).equals(x);

      return ECFieldElement(q, V);
    }
  } while ((U == BigInt.one) || (U == qMinusOne));

  return null;
}