/** * Decode a point on this curve from its ASN.1 encoding. The different * encodings are taken account of, including point compression for * <code>F<sub>p</sub><code> (X9.62 s 4.2.1 pg 17). * @return The decoded point. */ public override ECPoint DecodePoint( byte[] encoded) { ECPoint p = null; switch (encoded[0]) { // compressed case 0x02: case 0x03: int ytilde = encoded[0] & 1; byte[] i = new byte[encoded.Length - 1]; Array.Copy(encoded, 1, i, 0, i.Length); ECFieldElement x = new FpFieldElement(this.q, new BigInteger(1, i)); ECFieldElement alpha = x.Multiply(x.Square()).Add(x.Multiply(a).Add(b)); ECFieldElement beta = alpha.Sqrt(); // // if we can't find a sqrt we haven't got a point on the // curve - run! // if (beta == null) { throw new ArithmeticException("Invalid point compression"); } BigInteger betaValue = beta.ToBigInteger(); int bit0 = betaValue.TestBit(0) ? 1 : 0; if (bit0 != ytilde) { // Use the other root beta = new FpFieldElement(q, q.Subtract(betaValue)); } p = new FpPoint(this, x, beta, true); break; case 0x04: byte[] xEnc = new byte[(encoded.Length - 1) / 2]; byte[] yEnc = new byte[(encoded.Length - 1) / 2]; Array.Copy(encoded, 1, xEnc, 0, xEnc.Length); Array.Copy(encoded, xEnc.Length + 1, yEnc, 0, yEnc.Length); p = new FpPoint(this, new FpFieldElement(this.q, new BigInteger(1, xEnc)), new FpFieldElement(this.q, new BigInteger(1, yEnc))); break; default: throw new FormatException("Invalid point encoding " + encoded[0]); } return(p); }
// D.1.4 91 /** * return a sqrt root - the routine verifies that the calculation * returns the right value - if none exists it returns null. */ 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 ECFieldElement z = new FpFieldElement(q, x.ModPow(q.ShiftRight(2).Add(BigInteger.One), q)); return this.Equals(z.Square()) ? z : null; } // p mod 4 == 1 BigInteger qMinusOne = q.Subtract(BigInteger.One); BigInteger legendreExponent = qMinusOne.ShiftRight(1); if (!(x.ModPow(legendreExponent, q).Equals(BigInteger.One))) return null; BigInteger u = qMinusOne.ShiftRight(2); BigInteger k = u.ShiftLeft(1).Add(BigInteger.One); BigInteger Q = this.x; BigInteger fourQ = Q.ShiftLeft(2).Mod(q); BigInteger U, V; do { Random rand = new Random(); BigInteger P; do { P = new BigInteger(q.BitLength, rand); } while (P.CompareTo(q) >= 0 || !(P.Multiply(P).Subtract(fourQ).ModPow(legendreExponent, q).Equals(qMinusOne))); BigInteger[] result = fastLucasSequence(q, P, Q, k); U = result[0]; V = result[1]; if (V.Multiply(V).Mod(q).Equals(fourQ)) { // 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; // BigInteger qMinusOne = q.Subtract(BigInteger.One); // // BigInteger legendreExponent = qMinusOne.ShiftRight(1); // if (!(x.ModPow(legendreExponent, q).Equals(BigInteger.One))) // return null; // // Random rand = new Random(); // BigInteger fourX = x.ShiftLeft(2); // // BigInteger r; // do // { // r = new BigInteger(q.BitLength, rand); // } // while (r.CompareTo(q) >= 0 // || !(r.Multiply(r).Subtract(fourX).ModPow(legendreExponent, q).Equals(qMinusOne))); // // BigInteger n1 = qMinusOne.ShiftRight(2); // BigInteger n2 = n1.Add(BigInteger.One); // // BigInteger wOne = WOne(r, x, q); // BigInteger wSum = W(n1, wOne, q).Add(W(n2, wOne, q)).Mod(q); // BigInteger twoR = r.ShiftLeft(1); // // BigInteger root = twoR.ModPow(q.Subtract(BigInteger.Two), q) // .Multiply(x).Mod(q) // .Multiply(wSum).Mod(q); // // return new FpFieldElement(q, root); }
/** * Decode a point on this curve from its ASN.1 encoding. The different * encodings are taken account of, including point compression for * <code>F<sub>p</sub></code> (X9.62 s 4.2.1 pg 17). * @return The decoded point. */ public override ECPoint DecodePoint( byte[] encoded) { ECPoint p = null; switch (encoded[0]) { // compressed case 0x02: case 0x03: int ytilde = encoded[0] & 1; byte[] i = new byte[encoded.Length - 1]; Array.Copy(encoded, 1, i, 0, i.Length); ECFieldElement x = new FpFieldElement(this.q, new BigInteger(1, i)); ECFieldElement alpha = x.Multiply(x.Square()).Add(x.Multiply(a).Add(b)); ECFieldElement beta = alpha.Sqrt(); // // if we can't find a sqrt we haven't got a point on the // curve - run! // if (beta == null) throw new ArithmeticException("Invalid point compression"); BigInteger betaValue = beta.ToBigInteger(); int bit0 = betaValue.TestBit(0) ? 1 : 0; if (bit0 != ytilde) { // Use the other root beta = new FpFieldElement(q, q.Subtract(betaValue)); } p = new FpPoint(this, x, beta, true); break; case 0x04: byte[] xEnc = new byte[(encoded.Length - 1) / 2]; byte[] yEnc = new byte[(encoded.Length - 1) / 2]; Array.Copy(encoded, 1, xEnc, 0, xEnc.Length); Array.Copy(encoded, xEnc.Length + 1, yEnc, 0, yEnc.Length); p = new FpPoint(this, new FpFieldElement(this.q, new BigInteger(1, xEnc)), new FpFieldElement(this.q, new BigInteger(1, yEnc))); break; default: throw new FormatException("Invalid point encoding " + encoded[0]); } return p; }
// D.1.4 91 /** * return a sqrt root - the routine verifies that the calculation * returns the right value - if none exists it returns null. */ 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 ECFieldElement z = new FpFieldElement(q, x.ModPow(q.ShiftRight(2).Add(BigInteger.One), q)); return(z.Square().Equals(this) ? z : null); } // p mod 4 == 1 BigInteger qMinusOne = q.Subtract(BigInteger.One); BigInteger legendreExponent = qMinusOne.ShiftRight(1); if (!(x.ModPow(legendreExponent, q).Equals(BigInteger.One))) { return(null); } BigInteger u = qMinusOne.ShiftRight(2); BigInteger k = u.ShiftLeft(1).Add(BigInteger.One); BigInteger Q = this.x; BigInteger fourQ = Q.ShiftLeft(2).Mod(q); BigInteger U, V; do { Random rand = new Random(); BigInteger P; do { P = new BigInteger(q.BitLength, rand); }while (P.CompareTo(q) >= 0 || !(P.Multiply(P).Subtract(fourQ).ModPow(legendreExponent, q).Equals(qMinusOne))); BigInteger[] result = fastLucasSequence(q, P, Q, k); U = result[0]; V = result[1]; if (V.Multiply(V).Mod(q).Equals(fourQ)) { // 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); // BigInteger qMinusOne = q.Subtract(BigInteger.One); // // BigInteger legendreExponent = qMinusOne.ShiftRight(1); // if (!(x.ModPow(legendreExponent, q).Equals(BigInteger.One))) // return null; // // Random rand = new Random(); // BigInteger fourX = x.ShiftLeft(2); // // BigInteger r; // do // { // r = new BigInteger(q.BitLength, rand); // } // while (r.CompareTo(q) >= 0 // || !(r.Multiply(r).Subtract(fourX).ModPow(legendreExponent, q).Equals(qMinusOne))); // // BigInteger n1 = qMinusOne.ShiftRight(2); // BigInteger n2 = n1.Add(BigInteger.One); // // BigInteger wOne = WOne(r, x, q); // BigInteger wSum = W(n1, wOne, q).Add(W(n2, wOne, q)).Mod(q); // BigInteger twoR = r.ShiftLeft(1); // // BigInteger root = twoR.ModPow(q.Subtract(BigInteger.Two), q) // .Multiply(x).Mod(q) // .Multiply(wSum).Mod(q); // // return new FpFieldElement(q, root); }