/** * 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; }
public ECPoint twicePlus(ECPoint b) { if (this == b) { return threeTimes(); } if (this.isInfinity()) { return b; } if (b.isInfinity()) { return twice(); } ECFieldElement Y1 = this.y; if (Y1.isZero()) { return b; } return twice().add(b); }
public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression) { ECFieldElement X = fromBigInteger(x), Y = fromBigInteger(y); switch (this.getCoordinateSystem()) { case COORD_LAMBDA_AFFINE: case COORD_LAMBDA_PROJECTIVE: { if (!X.isZero()) { // Y becomes Lambda (X + Y/X) here Y = Y.divide(X).add(X); } break; } default: { break; } } return createRawPoint(X, Y, withCompression); }
/** * 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); }