/** * 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; }
public ECFieldElement multiplyPlusProduct( ECFieldElement b, ECFieldElement x, ECFieldElement y) { BigInteger ax = this.x, bx = b.toBigInteger(), xx = x.toBigInteger(), yx = y.toBigInteger(); BigInteger ab = ax.multiply(bx); BigInteger xy = xx.multiply(yx); return new Fp(q, r, modReduce(ab.add(xy))); }
/** * 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); }
/** * 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; }
public ECFieldElement squarePlusProduct(ECFieldElement x, ECFieldElement y) { BigInteger ax = this.x, xx = x.toBigInteger(), yx = y.toBigInteger(); BigInteger aa = ax.multiply(ax); BigInteger xy = xx.multiply(yx); return new Fp(q, r, modReduce(aa.add(xy))); }
public ECFieldElement divide(ECFieldElement b) { return new Fp(q, r, modMult(x, modInverse(b.toBigInteger()))); }
public ECFieldElement subtract(ECFieldElement b) { return new Fp(q, r, modSubtract(x, b.toBigInteger())); }
public ECFieldElement multiply(ECFieldElement b) { return new Fp(q, r, modMult(x, b.toBigInteger())); }
public ECFieldElement add(ECFieldElement b) { return new Fp(q, r, modAdd(x, b.toBigInteger())); }
public ECFieldElement divide(ECFieldElement b) { return new Fp(q, x.multiply(b.toBigInteger().modInverse(q)).mod(q)); }
public ECFieldElement multiply(ECFieldElement b) { return new Fp(q, x.multiply(b.toBigInteger()).mod(q)); }
public ECFieldElement subtract(ECFieldElement b) { return new Fp(q, x.subtract(b.toBigInteger()).mod(q)); }
public ECFieldElement add(ECFieldElement b) { return new Fp(q, x.add(b.toBigInteger()).mod(q)); }