18212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrompackage org.bouncycastle.math.ec; 28212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 38212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport java.math.BigInteger; 48212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 58212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.asn1.x9.X9IntegerConverter; 68212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 78212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom/** 88212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * base class for points on elliptic curves. 98212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrompublic abstract class ECPoint 118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom{ 128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECCurve curve; 138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECFieldElement x; 148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECFieldElement y; 158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom protected boolean withCompression; 178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom protected ECMultiplier multiplier = null; 198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom protected PreCompInfo preCompInfo = null; 218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom private static X9IntegerConverter converter = new X9IntegerConverter(); 238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom protected ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y) 258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom this.curve = curve; 278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom this.x = x; 288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom this.y = y; 298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public ECCurve getCurve() 328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return curve; 348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public ECFieldElement getX() 378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return x; 398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public ECFieldElement getY() 428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return y; 448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public boolean isInfinity() 478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return x == null && y == null; 498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public boolean isCompressed() 528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return withCompression; 548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public boolean equals( 578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom Object other) 588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (other == this) 608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return true; 628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (!(other instanceof ECPoint)) 658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return false; 678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECPoint o = (ECPoint)other; 708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (this.isInfinity()) 728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return o.isInfinity(); 748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return x.equals(o.x) && y.equals(o.y); 778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public int hashCode() 808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (this.isInfinity()) 828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return 0; 848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return x.hashCode() ^ y.hashCode(); 878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom// /** 908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom// * Mainly for testing. Explicitly set the <code>ECMultiplier</code>. 918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom// * @param multiplier The <code>ECMultiplier</code> to be used to multiply 928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom// * this <code>ECPoint</code>. 938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom// */ 948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom// public void setECMultiplier(ECMultiplier multiplier) 958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom// { 968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom// this.multiplier = multiplier; 978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom// } 988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 1008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Sets the <code>PreCompInfo</code>. Used by <code>ECMultiplier</code>s 1018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * to save the precomputation for this <code>ECPoint</code> to store the 1028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * precomputation result for use by subsequent multiplication. 1038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param preCompInfo The values precomputed by the 1048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * <code>ECMultiplier</code>. 1058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 1068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom void setPreCompInfo(PreCompInfo preCompInfo) 1078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 1088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom this.preCompInfo = preCompInfo; 1098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 1108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 1118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public abstract byte[] getEncoded(); 1128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 1138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public abstract ECPoint add(ECPoint b); 1148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public abstract ECPoint subtract(ECPoint b); 1158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public abstract ECPoint negate(); 1168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public abstract ECPoint twice(); 1178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 1188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 1198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Sets the default <code>ECMultiplier</code>, unless already set. 1208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 1218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom synchronized void assertECMultiplier() 1228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 1238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (this.multiplier == null) 1248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 1258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom this.multiplier = new FpNafMultiplier(); 1268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 1278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 1288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 1298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 1308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Multiplies this <code>ECPoint</code> by the given number. 1318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param k The multiplicator. 1328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @return <code>k * this</code>. 1338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 1348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public ECPoint multiply(BigInteger k) 1358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 1366e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom if (k.signum() < 0) 1376e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 1386e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom throw new IllegalArgumentException("The multiplicator cannot be negative"); 1396e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 1406e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 1418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (this.isInfinity()) 1428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 1438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return this; 1448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 1458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 1468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (k.signum() == 0) 1478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 1488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return this.curve.getInfinity(); 1498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 1508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 1518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom assertECMultiplier(); 1528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return this.multiplier.multiply(this, k, preCompInfo); 1538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 1548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 1558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 1568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Elliptic curve points over Fp 1578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 1588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public static class Fp extends ECPoint 1598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 1608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 1618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 1628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Create a point which encodes with point compression. 1638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * 1648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param curve the curve to use 1658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param x affine x co-ordinate 1668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param y affine y co-ordinate 1678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 1688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y) 1698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 1708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom this(curve, x, y, false); 1718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 1728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 1738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 1748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Create a point that encodes with or without point compresion. 1758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * 1768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param curve the curve to use 1778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param x affine x co-ordinate 1788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param y affine y co-ordinate 1798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param withCompression if true encode with point compression 1808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 1818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression) 1828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 1838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom super(curve, x, y); 1848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 1858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if ((x != null && y == null) || (x == null && y != null)) 1868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 1878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom throw new IllegalArgumentException("Exactly one of the field elements is null"); 1888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 1898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 1908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom this.withCompression = withCompression; 1918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 1928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 1938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 1948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * return the field element encoded with point compression. (S 4.3.6) 1958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 1968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public byte[] getEncoded() 1978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 1988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (this.isInfinity()) 1998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 2008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return new byte[1]; 2018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 2028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 2038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom int qLength = converter.getByteLength(x); 2048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 2058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (withCompression) 2068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 2078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom byte PC; 2088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 2098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (this.getY().toBigInteger().testBit(0)) 2108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 2118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom PC = 0x03; 2128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 2138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom else 2148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 2158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom PC = 0x02; 2168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 2178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 2188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom byte[] X = converter.integerToBytes(this.getX().toBigInteger(), qLength); 2198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom byte[] PO = new byte[X.length + 1]; 2208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 2218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom PO[0] = PC; 2228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom System.arraycopy(X, 0, PO, 1, X.length); 2238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 2248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return PO; 2258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 2268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom else 2278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 2288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom byte[] X = converter.integerToBytes(this.getX().toBigInteger(), qLength); 2298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom byte[] Y = converter.integerToBytes(this.getY().toBigInteger(), qLength); 2308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom byte[] PO = new byte[X.length + Y.length + 1]; 2318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 2328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom PO[0] = 0x04; 2338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom System.arraycopy(X, 0, PO, 1, X.length); 2348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom System.arraycopy(Y, 0, PO, X.length + 1, Y.length); 2358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 2368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return PO; 2378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 2388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 2398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 2408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // B.3 pg 62 2418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public ECPoint add(ECPoint b) 2428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 2438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (this.isInfinity()) 2448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 2458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return b; 2468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 2478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 2488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (b.isInfinity()) 2498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 2508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return this; 2518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 2528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 2538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // Check if b = this or b = -this 2548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (this.x.equals(b.x)) 2558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 2568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (this.y.equals(b.y)) 2578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 2588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // this = b, i.e. this must be doubled 2598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return this.twice(); 2608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 2618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 2628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // this = -b, i.e. the result is the point at infinity 2638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return this.curve.getInfinity(); 2648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 2658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 2668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECFieldElement gamma = b.y.subtract(this.y).divide(b.x.subtract(this.x)); 2678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 2688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECFieldElement x3 = gamma.square().subtract(this.x).subtract(b.x); 2698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECFieldElement y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y); 2708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 2718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return new ECPoint.Fp(curve, x3, y3); 2728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 2738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 2748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // B.3 pg 62 2758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public ECPoint twice() 2768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 2778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (this.isInfinity()) 2788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 2798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // Twice identity element (point at infinity) is identity 2808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return this; 2818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 2828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 2838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (this.y.toBigInteger().signum() == 0) 2848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 2858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // if y1 == 0, then (x1, y1) == (x1, -y1) 2868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // and hence this = -this and thus 2(x1, y1) == infinity 2878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return this.curve.getInfinity(); 2888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 2898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 2908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECFieldElement TWO = this.curve.fromBigInteger(BigInteger.valueOf(2)); 2918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECFieldElement THREE = this.curve.fromBigInteger(BigInteger.valueOf(3)); 2928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECFieldElement gamma = this.x.square().multiply(THREE).add(curve.a).divide(y.multiply(TWO)); 2938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 2948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECFieldElement x3 = gamma.square().subtract(this.x.multiply(TWO)); 2958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECFieldElement y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y); 2968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 2978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return new ECPoint.Fp(curve, x3, y3, this.withCompression); 2988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 2998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 3008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // D.3.2 pg 102 (see Note:) 3018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public ECPoint subtract(ECPoint b) 3028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 3038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (b.isInfinity()) 3048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 3058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return this; 3068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 3078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 3088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // Add -b 3098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return add(b.negate()); 3108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 3118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 3128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public ECPoint negate() 3138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 3148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return new ECPoint.Fp(curve, this.x, this.y.negate(), this.withCompression); 3158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 3168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 3176e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom /** 3186e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom * Sets the default <code>ECMultiplier</code>, unless already set. 3196e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom */ 3206e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom synchronized void assertECMultiplier() 3216e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 3226e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom if (this.multiplier == null) 3236e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 3246e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom this.multiplier = new WNafMultiplier(); 3256e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 3266e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 3278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 3288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 3298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 3308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Elliptic curve points over F2m 3318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 3328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public static class F2m extends ECPoint 3338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 3348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 3358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param curve base curve 3368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param x x point 3378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param y y point 3388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 3398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y) 3408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 3418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom this(curve, x, y, false); 3428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 3438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 3448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 3458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param curve base curve 3468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param x x point 3478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param y y point 3488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param withCompression true if encode with point compression. 3498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 3508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression) 3518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 3528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom super(curve, x, y); 3538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 3548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if ((x != null && y == null) || (x == null && y != null)) 3558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 3568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom throw new IllegalArgumentException("Exactly one of the field elements is null"); 3578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 3588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 3598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (x != null) 3608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 3618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // Check if x and y are elements of the same field 3628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECFieldElement.F2m.checkFieldElements(this.x, this.y); 3638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 3648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // Check if x and a are elements of the same field 3658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (curve != null) 3668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 3678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECFieldElement.F2m.checkFieldElements(this.x, this.curve.getA()); 3688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 3698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 3708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 3718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom this.withCompression = withCompression; 3728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 3738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 3748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /* (non-Javadoc) 3758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @see org.bouncycastle.math.ec.ECPoint#getEncoded() 3768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 3778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public byte[] getEncoded() 3788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 3798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (this.isInfinity()) 3808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 3818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return new byte[1]; 3828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 3838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 3848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom int byteCount = converter.getByteLength(this.x); 3858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom byte[] X = converter.integerToBytes(this.getX().toBigInteger(), byteCount); 3868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom byte[] PO; 3878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 3888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (withCompression) 3898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 3908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // See X9.62 4.3.6 and 4.2.2 3918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom PO = new byte[byteCount + 1]; 3928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 3938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom PO[0] = 0x02; 3948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // X9.62 4.2.2 and 4.3.6: 3958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // if x = 0 then ypTilde := 0, else ypTilde is the rightmost 3968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // bit of y * x^(-1) 3978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // if ypTilde = 0, then PC := 02, else PC := 03 3988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // Note: PC === PO[0] 3998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (!(this.getX().toBigInteger().equals(ECConstants.ZERO))) 4008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 4018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (this.getY().multiply(this.getX().invert()) 4028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom .toBigInteger().testBit(0)) 4038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 4048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // ypTilde = 1, hence PC = 03 4058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom PO[0] = 0x03; 4068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 4078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 4088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 4098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom System.arraycopy(X, 0, PO, 1, byteCount); 4108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 4118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom else 4128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 4138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom byte[] Y = converter.integerToBytes(this.getY().toBigInteger(), byteCount); 4148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 4158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom PO = new byte[byteCount + byteCount + 1]; 4168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 4178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom PO[0] = 0x04; 4188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom System.arraycopy(X, 0, PO, 1, byteCount); 4198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom System.arraycopy(Y, 0, PO, byteCount + 1, byteCount); 4208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 4218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 4228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return PO; 4238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 4248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 4258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 4268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Check, if two <code>ECPoint</code>s can be added or subtracted. 4278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param a The first <code>ECPoint</code> to check. 4288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param b The second <code>ECPoint</code> to check. 4298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @throws IllegalArgumentException if <code>a</code> and <code>b</code> 4308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * cannot be added. 4318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 4328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom private static void checkPoints(ECPoint a, ECPoint b) 4338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 4348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // Check, if points are on the same curve 4358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (!(a.curve.equals(b.curve))) 4368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 4378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom throw new IllegalArgumentException("Only points on the same " 4388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom + "curve can be added or subtracted"); 4398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 4408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 4418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom// ECFieldElement.F2m.checkFieldElements(a.x, b.x); 4428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 4438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 4448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /* (non-Javadoc) 4458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @see org.bouncycastle.math.ec.ECPoint#add(org.bouncycastle.math.ec.ECPoint) 4468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 4478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public ECPoint add(ECPoint b) 4488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 4498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom checkPoints(this, b); 4508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return addSimple((ECPoint.F2m)b); 4518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 4528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 4538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 4548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Adds another <code>ECPoints.F2m</code> to <code>this</code> without 4558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * checking if both points are on the same curve. Used by multiplication 4568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * algorithms, because there all points are a multiple of the same point 4578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * and hence the checks can be omitted. 4588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param b The other <code>ECPoints.F2m</code> to add to 4598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * <code>this</code>. 4608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @return <code>this + b</code> 4618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 4628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public ECPoint.F2m addSimple(ECPoint.F2m b) 4638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 4648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECPoint.F2m other = b; 4658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (this.isInfinity()) 4668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 4678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return other; 4688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 4698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 4708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (other.isInfinity()) 4718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 4728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return this; 4738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 4748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 4758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECFieldElement.F2m x2 = (ECFieldElement.F2m)other.getX(); 4768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECFieldElement.F2m y2 = (ECFieldElement.F2m)other.getY(); 4778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 4788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // Check if other = this or other = -this 4798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (this.x.equals(x2)) 4808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 4818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (this.y.equals(y2)) 4828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 4838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // this = other, i.e. this must be doubled 4848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return (ECPoint.F2m)this.twice(); 4858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 4868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 4878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // this = -other, i.e. the result is the point at infinity 4888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return (ECPoint.F2m)this.curve.getInfinity(); 4898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 4908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 4918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECFieldElement.F2m lambda 4928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom = (ECFieldElement.F2m)(this.y.add(y2)).divide(this.x.add(x2)); 4938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 4948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECFieldElement.F2m x3 4958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom = (ECFieldElement.F2m)lambda.square().add(lambda).add(this.x).add(x2).add(this.curve.getA()); 4968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 4978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECFieldElement.F2m y3 4988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom = (ECFieldElement.F2m)lambda.multiply(this.x.add(x3)).add(x3).add(this.y); 4998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 5008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return new ECPoint.F2m(curve, x3, y3, withCompression); 5018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 5028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 5038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /* (non-Javadoc) 5048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @see org.bouncycastle.math.ec.ECPoint#subtract(org.bouncycastle.math.ec.ECPoint) 5058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 5068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public ECPoint subtract(ECPoint b) 5078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 5088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom checkPoints(this, b); 5098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return subtractSimple((ECPoint.F2m)b); 5108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 5118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 5128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 5138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Subtracts another <code>ECPoints.F2m</code> from <code>this</code> 5148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * without checking if both points are on the same curve. Used by 5158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * multiplication algorithms, because there all points are a multiple 5168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * of the same point and hence the checks can be omitted. 5178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param b The other <code>ECPoints.F2m</code> to subtract from 5188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * <code>this</code>. 5198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @return <code>this - b</code> 5208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 5218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public ECPoint.F2m subtractSimple(ECPoint.F2m b) 5228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 5238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (b.isInfinity()) 5248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 5258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return this; 5268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 5278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 5288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // Add -b 5298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return addSimple((ECPoint.F2m)b.negate()); 5308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 5318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 5328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /* (non-Javadoc) 5338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @see org.bouncycastle.math.ec.ECPoint#twice() 5348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 5358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public ECPoint twice() 5368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 5378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (this.isInfinity()) 5388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 5398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // Twice identity element (point at infinity) is identity 5408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return this; 5418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 5428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 5438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (this.x.toBigInteger().signum() == 0) 5448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 5458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // if x1 == 0, then (x1, y1) == (x1, x1 + y1) 5468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom // and hence this = -this and thus 2(x1, y1) == infinity 5478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return this.curve.getInfinity(); 5488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 5498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 5508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECFieldElement.F2m lambda 5518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom = (ECFieldElement.F2m)this.x.add(this.y.divide(this.x)); 5528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 5538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECFieldElement.F2m x3 5548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom = (ECFieldElement.F2m)lambda.square().add(lambda). 5558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom add(this.curve.getA()); 5568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 5578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECFieldElement ONE = this.curve.fromBigInteger(ECConstants.ONE); 5588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECFieldElement.F2m y3 5598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom = (ECFieldElement.F2m)this.x.square().add( 5608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom x3.multiply(lambda.add(ONE))); 5618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 5628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return new ECPoint.F2m(this.curve, x3, y3, withCompression); 5638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 5648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 5658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public ECPoint negate() 5668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 5678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return new ECPoint.F2m(curve, this.getX(), this.getY().add(this.getX()), withCompression); 5688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 5698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 5706e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom /** 5716e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom * Sets the appropriate <code>ECMultiplier</code>, unless already set. 5726e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom */ 5736e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom synchronized void assertECMultiplier() 5746e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 5756e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom if (this.multiplier == null) 5766e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 5776e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom if (((ECCurve.F2m)this.curve).isKoblitz()) 5786e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 5796e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom this.multiplier = new WTauNafMultiplier(); 5806e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 5816e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom else 5826e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 5836e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom this.multiplier = new WNafMultiplier(); 5846e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 5856e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 5866e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 5878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 5888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom} 589