/// <summary> /// D.1.4 91 /// return a sqrt root - the routine verifies that the calculation /// returns the right value - if none exists it returns null. /// </summary> /// <returns></returns> public override ECFieldElement Sqrt() { if (!_q.TestBit(0)) { throw Platform.CreateNotImplementedException("even value of q"); } // p mod 4 == 3 if (_q.TestBit(1)) { // TODO Can this be optimised (inline the Square?) // z = g^(u+1) + p, p = 4u + 3 var z = new FPFieldElement(_q, _x.ModPow(_q.ShiftRight(2).Add(BigInteger.One), _q)); return(z.Square().Equals(this) ? z : null); } // p mod 4 == 1 var qMinusOne = _q.Subtract(BigInteger.One); var legendreExponent = qMinusOne.ShiftRight(1); if (!(_x.ModPow(legendreExponent, _q).Equals(BigInteger.One))) { return(null); } var u = qMinusOne.ShiftRight(2); var k = u.ShiftLeft(1).Add(BigInteger.One); var Q = _x; var fourQ = Q.ShiftLeft(2).Mod(_q); IBigInteger U; IBigInteger V; do { IRandom rand = new Random(); IBigInteger P; do { P = new BigInteger(_q.BitLength, rand); }while (P.CompareTo(_q) >= 0 || !(P.Multiply(P).Subtract(fourQ).ModPow(legendreExponent, _q).Equals(qMinusOne))); var result = FastLucasSequence(_q, P, Q, k); U = result[0]; V = result[1]; if (!V.Multiply(V).Mod(_q).Equals(fourQ)) { continue; } // Integer division by 2, mod q if (V.TestBit(0)) { V = V.Add(_q); } V = V.ShiftRight(1); Debug.Assert(V.Multiply(V).Mod(_q).Equals(_x)); return(new FPFieldElement(_q, V)); }while (U.Equals(BigInteger.One) || U.Equals(qMinusOne)); return(null); }
/// <summary> /// D.1.4 91 /// return a sqrt root - the routine verifies that the calculation /// returns the right value - if none exists it returns null. /// </summary> /// <returns></returns> public override ECFieldElement Sqrt() { if (!_q.TestBit(0)) throw Platform.CreateNotImplementedException("even value of q"); // p mod 4 == 3 if (_q.TestBit(1)) { // TODO Can this be optimised (inline the Square?) // z = g^(u+1) + p, p = 4u + 3 var z = new FPFieldElement(_q, _x.ModPow(_q.ShiftRight(2).Add(BigInteger.One), _q)); return z.Square().Equals(this) ? z : null; } // p mod 4 == 1 var qMinusOne = _q.Subtract(BigInteger.One); var legendreExponent = qMinusOne.ShiftRight(1); if (!(_x.ModPow(legendreExponent, _q).Equals(BigInteger.One))) return null; var u = qMinusOne.ShiftRight(2); var k = u.ShiftLeft(1).Add(BigInteger.One); var Q = _x; var fourQ = Q.ShiftLeft(2).Mod(_q); IBigInteger U; IBigInteger V; do { IRandom rand = new Random(); IBigInteger P; do { P = new BigInteger(_q.BitLength, rand); } while (P.CompareTo(_q) >= 0 || !(P.Multiply(P).Subtract(fourQ).ModPow(legendreExponent, _q).Equals(qMinusOne))); var result = FastLucasSequence(_q, P, Q, k); U = result[0]; V = result[1]; if (!V.Multiply(V).Mod(_q).Equals(fourQ)) continue; // Integer division by 2, mod q if (V.TestBit(0)) { V = V.Add(_q); } V = V.ShiftRight(1); Debug.Assert(V.Multiply(V).Mod(_q).Equals(_x)); return new FPFieldElement(_q, V); } while (U.Equals(BigInteger.One) || U.Equals(qMinusOne)); return null; }