/** * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). * * @param xEnc The encoding of field element xp. * @param ypBit ~yp, an indication bit for the decompression of yp. * @return the decompressed point. */ private ECPoint decompressPoint(byte[] xEnc, int ypBit) { ECFieldElement xp = new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3, new BigInteger(1, xEnc)); ECFieldElement yp = null; if (xp.toBigInteger().equals(ECConstants.ZERO)) { yp = (ECFieldElement.F2m) b; for (int i = 0; i < m - 1; i++) { yp = yp.square(); } } else { ECFieldElement beta = xp.add(a).add(b.multiply(xp.square().invert())); ECFieldElement z = solveQuadradicEquation(beta); if (z == null) { throw new RuntimeException("Invalid point compression"); } int zBit = 0; if (z.toBigInteger().testBit(0)) { zBit = 1; } if (zBit != ypBit) { z = z.add(new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3, ECConstants.ONE)); } yp = xp.multiply(z); } return new ECPoint.F2m(this, xp, yp); }
/** * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62 D.1.6) The other * solution is <code>z + 1</code>. * * @param beta The value to solve the qradratic equation for. * @return the solution for <code>z<sup>2</sup> + z = beta</code> or <code>null</code> if no * solution exists. */ private ECFieldElement solveQuadradicEquation(ECFieldElement beta) { ECFieldElement zeroElement = new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3, ECConstants.ZERO); if (beta.toBigInteger().equals(ECConstants.ZERO)) { return zeroElement; } ECFieldElement z = null; ECFieldElement gamma = zeroElement; Random rand = new Random(); do { ECFieldElement t = new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3, new BigInteger(m, rand)); z = zeroElement; ECFieldElement w = beta; for (int i = 1; i <= m - 1; i++) { ECFieldElement w2 = w.square(); z = z.square().add(w2.multiply(t)); w = w2.add(beta); } if (!w.toBigInteger().equals(ECConstants.ZERO)) { return null; } gamma = z.square().add(z); } while (gamma.toBigInteger().equals(ECConstants.ZERO)); return z; }
/** * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62 D.1.6) The other * solution is <code>z + 1</code>. * * @param beta The value to solve the quadratic equation for. * @return the solution for <code>z<sup>2</sup> + z = beta</code> or <code>null</code> if no * solution exists. */ private ECFieldElement solveQuadraticEquation(ECFieldElement beta) { if (beta.isZero()) { return beta; } ECFieldElement zeroElement = fromBigInteger(ECConstants.ZERO); ECFieldElement z = null; ECFieldElement gamma = null; Random rand = new Random(); do { ECFieldElement t = fromBigInteger(new BigInteger(m, rand)); z = zeroElement; ECFieldElement w = beta; for (int i = 1; i <= m - 1; i++) { ECFieldElement w2 = w.square(); z = z.square().add(w2.multiply(t)); w = w2.add(beta); } if (!w.isZero()) { return null; } gamma = z.square().add(z); } while (gamma.isZero()); return z; }
/** * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). * * @param yTilde ~yp, an indication bit for the decompression of yp. * @param X1 The field element xp. * @return the decompressed point. */ protected ECPoint decompressPoint(int yTilde, BigInteger X1) { ECFieldElement xp = fromBigInteger(X1); ECFieldElement yp = null; if (xp.isZero()) { yp = (ECFieldElement.F2m) b; for (int i = 0; i < m - 1; i++) { yp = yp.square(); } } else { ECFieldElement beta = xp.add(a).add(b.multiply(xp.square().invert())); ECFieldElement z = solveQuadraticEquation(beta); if (z == null) { throw new IllegalArgumentException("Invalid point compression"); } if (z.testBitZero() != (yTilde == 1)) { z = z.addOne(); } yp = xp.multiply(z); switch (this.getCoordinateSystem()) { case COORD_LAMBDA_AFFINE: case COORD_LAMBDA_PROJECTIVE: { yp = yp.divide(xp).add(xp); break; } default: { break; } } } return new ECPoint.F2m(this, xp, yp, true); }
protected ECPoint decompressPoint(int yTilde, BigInteger X1) { ECFieldElement x = fromBigInteger(X1); ECFieldElement alpha = x.square().add(a).multiply(x).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 RuntimeException("Invalid point compression"); } if (beta.testBitZero() != (yTilde == 1)) { // Use the other root beta = beta.negate(); } return new ECPoint.Fp(this, x, beta, true); }
/** * 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 ECPoint decodePoint(byte[] encoded) { ECPoint p = null; switch (encoded[0]) { // infinity case 0x00: p = getInfinity(); break; // compressed case 0x02: case 0x03: int ytilde = encoded[0] & 1; byte[] i = new byte[encoded.length - 1]; System.arraycopy(encoded, 1, i, 0, i.length); ECFieldElement x = new ECFieldElement.Fp(this.q, new BigInteger(1, i)); ECFieldElement alpha = x.multiply(x.square().add(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 RuntimeException("Invalid point compression"); } int bit0 = (beta.toBigInteger().testBit(0) ? 1 : 0); if (bit0 == ytilde) { p = new ECPoint.Fp(this, x, beta, true); } else { p = new ECPoint.Fp( this, x, new ECFieldElement.Fp(this.q, q.subtract(beta.toBigInteger())), true); } break; // uncompressed case 0x04: // hybrid case 0x06: case 0x07: byte[] xEnc = new byte[(encoded.length - 1) / 2]; byte[] yEnc = new byte[(encoded.length - 1) / 2]; System.arraycopy(encoded, 1, xEnc, 0, xEnc.length); System.arraycopy(encoded, xEnc.length + 1, yEnc, 0, yEnc.length); p = new ECPoint.Fp( this, new ECFieldElement.Fp(this.q, new BigInteger(1, xEnc)), new ECFieldElement.Fp(this.q, new BigInteger(1, yEnc))); break; default: throw new RuntimeException( "Invalid point encoding 0x" + Integer.toString(encoded[0], 16)); } return p; }
private ECFieldElement checkSqrt(ECFieldElement z) { return z.square().equals(this) ? z : null; }
/** * return a sqrt root - the routine verifies that the calculation returns the right value - if * none exists it returns null. */ public ECFieldElement sqrt() { if (!q.testBit(0)) { throw new RuntimeException("not done yet"); } // p mod 4 == 3 if (q.testBit(1)) { // z = g^(u+1) + p, p = 4u + 3 ECFieldElement z = new Fp(q, x.modPow(q.shiftRight(2).add(ONE), q)); return z.square().equals(this) ? z : null; } // p mod 4 == 1 BigInteger qMinusOne = q.subtract(ECConstants.ONE); BigInteger legendreExponent = qMinusOne.shiftRight(1); if (!(x.modPow(legendreExponent, q).equals(ECConstants.ONE))) { return null; } BigInteger u = qMinusOne.shiftRight(2); BigInteger k = u.shiftLeft(1).add(ECConstants.ONE); BigInteger Q = this.x; BigInteger fourQ = Q.shiftLeft(2).mod(q); BigInteger U, V; Random rand = new Random(); do { 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 = lucasSequence(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); // assert V.multiply(V).mod(q).equals(x); return new ECFieldElement.Fp(q, V); } } while (U.equals(ECConstants.ONE) || U.equals(qMinusOne)); return null; // BigInteger qMinusOne = q.subtract(ECConstants.ONE); // BigInteger legendreExponent = qMinusOne.shiftRight(1); //divide(ECConstants.TWO); // if (!(x.modPow(legendreExponent, q).equals(ECConstants.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); //.divide(ECConstants.FOUR); // BigInteger n2 = n1.add(ECConstants.ONE); // //q.add(ECConstants.THREE).divide(ECConstants.FOUR); // // BigInteger wOne = WOne(r, x, q); // BigInteger wSum = W(n1, wOne, q).add(W(n2, wOne, q)).mod(q); // BigInteger twoR = r.shiftLeft(1); //ECConstants.TWO.multiply(r); // // BigInteger root = twoR.modPow(q.subtract(ECConstants.TWO), q) // .multiply(x).mod(q) // .multiply(wSum).mod(q); // // return new Fp(q, root); }