/// <summary> /// Impplements Cipolla's algorithm /// </summary> /// <param name="N"></param> /// <param name="p"></param> /// <returns></returns> public static BigInteger ModSqrt(BigInteger N, BigInteger p) { BigInteger a = 0, w2 = 0; BigInteger ls = 0; // Pick up any value 'a' such that 'w^2 = a^2 - N' is a non-quadratic // residue in Fp do { ++a; w2 = (a * a + p - N) % p; ls = LS(w2, p); } while (ls != p - 1); // In Fp^2, compute '(a + w)^((p + 1)/2) (mod p)' var r = new Fp2Point(1, 0); var s = new Fp2Point(a, 1); for (var n = (p + 1) / 2 % p; n > 0; n >>= 1) { if (!n.IsEven) { r = Fp2Point.Mul(r, s, p, w2); } s = Fp2Point.Mul(s, s, p, w2); } // Check for errors if (r.x * r.x % p != N) { return(0); } if (r.y != 0) { return(0); } return(r.x); } // ModSqrt
internal static Fp2Point Mul(Fp2Point a, Fp2Point b, BigInteger p, BigInteger w2) { return(new Fp2Point((a.x * b.x + a.y * b.y * w2) % p, (a.x * b.y + b.x * a.y) % p)); }