package org.bouncycastle.math.ec; import java.math.BigInteger; /** * base class for points on elliptic curves. */ public abstract class ECPoint { ECCurve curve; ECFieldElement x; ECFieldElement y; protected ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y) { this.curve = curve; this.x = x; this.y = y; } public ECFieldElement getX() { return x; } public ECFieldElement getY() { return y; } public boolean equals( Object other) { if ( other == this ) return true; if ( !(other instanceof ECPoint) ) return false; ECPoint o = (ECPoint)other; return x.equals(o.x) && y.equals(o.y); } public abstract byte[] getEncoded(); public abstract ECPoint add(ECPoint b); public abstract ECPoint subtract(ECPoint b); public abstract ECPoint twice(); public abstract ECPoint multiply(BigInteger b); /** * Elliptic curve points over Fp */ public static class Fp extends ECPoint { public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y) { super(curve, x, y); } /** * return the field element encoded with point compression. (S 4.3.6) */ public byte[] getEncoded() { byte PC; if (this.getY().toBigInteger().testBit(0)) { PC = 0x02; } else { PC = 0x03; } byte[] X = this.getX().toBigInteger().toByteArray(); byte[] PO = new byte[X.length + 1]; PO[0] = PC; System.arraycopy(X, 0, PO, 1, X.length); return PO; } // B.3 pg 62 public ECPoint add(ECPoint b) { ECFieldElement gamma = b.y.subtract(y).divide(b.x.subtract(x)); ECFieldElement x3 = gamma.multiply(gamma).subtract(x).subtract(b.x); ECFieldElement y3 = gamma.multiply(x.subtract(x3)).subtract(y); return new ECPoint.Fp(curve, x3, y3); } // B.3 pg 62 public ECPoint twice() { ECFieldElement TWO = curve.fromBigInteger(BigInteger.valueOf(2)); ECFieldElement THREE = curve.fromBigInteger(BigInteger.valueOf(3)); ECFieldElement gamma = x.multiply(x).multiply(THREE).add(curve.a).divide(y.multiply(TWO)); ECFieldElement x3 = gamma.multiply(gamma).subtract(x.multiply(TWO)); ECFieldElement y3 = gamma.multiply(x.subtract(x3)).subtract(y); return new ECPoint.Fp(curve, x3, y3); } // D.3.2 pg 102 (see Note:) public ECPoint subtract(ECPoint p2) { return add(new ECPoint.Fp(curve, p2.x, p2.y.negate())); } // D.3.2 pg 101 public ECPoint multiply(BigInteger k) { // BigInteger e = k.mod(n); // n == order this BigInteger e = k; BigInteger h = e.multiply(BigInteger.valueOf(3)); ECPoint R = this; for (int i = h.bitLength() - 2; i > 0; i--) { R = R.twice(); if ( h.testBit(i) && !e.testBit(i) ) { //System.out.print("+"); R = R.add(this); } else if ( !h.testBit(i) && e.testBit(i) ) { //System.out.print("-"); R = R.subtract(this); } // else // System.out.print("."); } // System.out.println(); return R; } } }