sqrt method

  1. @override
FieldSqrtResult<Bls12Fp2> sqrt()
override

Implementation

@override
FieldSqrtResult<Bls12Fp2> sqrt() {
  if (isZero()) {
    return FieldSqrtResult(Bls12Fp2.zero(), true);
  }

  // a1 = self^((p - 3) / 4)
  final a1 = powVarTime([
    BigInt.parse('0xee7fbfffffffeaaa'),
    BigInt.parse('0x07aaffffac54ffff'),
    BigInt.parse('0xd9cc34a83dac3d89'),
    BigInt.parse('0xd91dd2e13ce144af'),
    BigInt.parse('0x92c6e9ed90d2eb35'),
    BigInt.parse('0x0680447a8e5ff9a6'),
  ]);

  // alpha = a1^2 * self = self^((p - 1) / 2)
  final alpha = a1.square() * this;

  // x0 = self^((p + 1) / 4)
  final x0 = a1 * this;

  // Case 1: alpha == -1
  if (alpha == -Bls12Fp2.one()) {
    final sqrt = Bls12Fp2(c0: -x0.c1, c1: x0.c0);

    // Verify sqrt^2 == self
    return FieldSqrtResult(sqrt, sqrt.square() == this);
  }

  // Case 2: general case
  final sqrt =
      (alpha + Bls12Fp2.one()).powVarTime([
        BigInt.parse('0xdcff7fffffffd555'),
        BigInt.parse('0x0f55ffff58a9ffff'),
        BigInt.parse('0xb39869507b587b12'),
        BigInt.parse('0xb23ba5c279c2895f'),
        BigInt.parse('0x258dd3db21a5d66b'),
        BigInt.parse('0x0d0088f51cbff34d'),
      ]) *
      x0;

  // Final verification
  return FieldSqrtResult(sqrt, sqrt.square() == this);
}