18212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrompackage org.bouncycastle.math.ec; 28212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 38212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport java.math.BigInteger; 4d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport java.util.Hashtable; 58212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport java.util.Random; 68212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 7d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport org.bouncycastle.math.ec.endo.ECEndomorphism; 8d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport org.bouncycastle.math.ec.endo.GLVEndomorphism; 9d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport org.bouncycastle.math.field.FiniteField; 10d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport org.bouncycastle.math.field.FiniteFields; 115db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Rootimport org.bouncycastle.util.BigIntegers; 12d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport org.bouncycastle.util.Integers; 135db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom/** 158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * base class for an elliptic curve 168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrompublic abstract class ECCurve 188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom{ 195db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root public static final int COORD_AFFINE = 0; 205db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root public static final int COORD_HOMOGENEOUS = 1; 215db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root public static final int COORD_JACOBIAN = 2; 225db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root public static final int COORD_JACOBIAN_CHUDNOVSKY = 3; 235db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root public static final int COORD_JACOBIAN_MODIFIED = 4; 245db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root public static final int COORD_LAMBDA_AFFINE = 5; 255db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root public static final int COORD_LAMBDA_PROJECTIVE = 6; 265db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root public static final int COORD_SKEWED = 7; 275db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 285db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root public static int[] getAllCoordinateSystems() 295db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 305db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return new int[]{ COORD_AFFINE, COORD_HOMOGENEOUS, COORD_JACOBIAN, COORD_JACOBIAN_CHUDNOVSKY, 315db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root COORD_JACOBIAN_MODIFIED, COORD_LAMBDA_AFFINE, COORD_LAMBDA_PROJECTIVE, COORD_SKEWED }; 325db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 335db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 345db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root public class Config 355db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 365db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root protected int coord; 37d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root protected ECEndomorphism endomorphism; 385db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root protected ECMultiplier multiplier; 395db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 40d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root Config(int coord, ECEndomorphism endomorphism, ECMultiplier multiplier) 415db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 425db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root this.coord = coord; 43d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root this.endomorphism = endomorphism; 445db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root this.multiplier = multiplier; 455db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 465db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 475db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root public Config setCoordinateSystem(int coord) 485db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 495db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root this.coord = coord; 505db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return this; 515db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 525db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 53d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public Config setEndomorphism(ECEndomorphism endomorphism) 54d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 55d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root this.endomorphism = endomorphism; 56d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return this; 57d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 58d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 595db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root public Config setMultiplier(ECMultiplier multiplier) 605db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 615db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root this.multiplier = multiplier; 625db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return this; 635db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 645db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 655db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root public ECCurve create() 665db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 675db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root if (!supportsCoordinateSystem(coord)) 685db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 695db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root throw new IllegalStateException("unsupported coordinate system"); 705db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 715db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 725db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root ECCurve c = cloneCurve(); 735db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root if (c == ECCurve.this) 745db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 755db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root throw new IllegalStateException("implementation returned current curve"); 765db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 775db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 785db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root c.coord = coord; 79d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root c.endomorphism = endomorphism; 805db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root c.multiplier = multiplier; 815db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 825db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return c; 835db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 845db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 855db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 86d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root protected FiniteField field; 875db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root protected ECFieldElement a, b; 88d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root protected BigInteger order, cofactor; 89d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 905db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root protected int coord = COORD_AFFINE; 91d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root protected ECEndomorphism endomorphism = null; 925db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root protected ECMultiplier multiplier = null; 938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 94d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root protected ECCurve(FiniteField field) 95d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 96d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root this.field = field; 97d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 98d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public abstract int getFieldSize(); 1008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 1018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public abstract ECFieldElement fromBigInteger(BigInteger x); 1028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 1035db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root public Config configure() 1045db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 105d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return new Config(this.coord, this.endomorphism, this.multiplier); 106d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 107d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 108d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public ECPoint validatePoint(BigInteger x, BigInteger y) 109d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 110d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root ECPoint p = createPoint(x, y); 111d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (!p.isValid()) 112d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 113d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root throw new IllegalArgumentException("Invalid point coordinates"); 114d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 115d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return p; 116d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 117d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 118d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root /** 119d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root * @deprecated per-point compression property will be removed, use {@link #validatePoint(BigInteger, BigInteger)} 120d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root * and refer {@link ECPoint#getEncoded(boolean)} 121d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root */ 122d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public ECPoint validatePoint(BigInteger x, BigInteger y, boolean withCompression) 123d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 124d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root ECPoint p = createPoint(x, y, withCompression); 125d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (!p.isValid()) 126d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 127d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root throw new IllegalArgumentException("Invalid point coordinates"); 128d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 129d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return p; 1305db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 1315db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 1325db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root public ECPoint createPoint(BigInteger x, BigInteger y) 1335db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 1345db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return createPoint(x, y, false); 1355db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 1365db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 1375db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root /** 1385db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root * @deprecated per-point compression property will be removed, use {@link #createPoint(BigInteger, BigInteger)} 1395db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root * and refer {@link ECPoint#getEncoded(boolean)} 1405db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root */ 1415db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression) 1425db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 1435db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return createRawPoint(fromBigInteger(x), fromBigInteger(y), withCompression); 1445db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 1455db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 1465db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root protected abstract ECCurve cloneCurve(); 1475db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 1485db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root protected abstract ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression); 1495db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 150d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root protected abstract ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression); 151d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 1525db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root protected ECMultiplier createDefaultMultiplier() 1535db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 154d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (endomorphism instanceof GLVEndomorphism) 155d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 156d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return new GLVMultiplier(this, (GLVEndomorphism)endomorphism); 157d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 158d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 1595db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return new WNafL2RMultiplier(); 1605db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 1615db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 1625db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root public boolean supportsCoordinateSystem(int coord) 1635db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 1645db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return coord == COORD_AFFINE; 1655db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 1665db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 167d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public PreCompInfo getPreCompInfo(ECPoint point, String name) 1685db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 169d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root checkPoint(point); 170d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root synchronized (point) 171d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 172d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root Hashtable table = point.preCompTable; 173d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return table == null ? null : (PreCompInfo)table.get(name); 174d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 1755db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 1765db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 1775db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root /** 178d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root * Adds <code>PreCompInfo</code> for a point on this curve, under a given name. Used by 1795db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root * <code>ECMultiplier</code>s to save the precomputation for this <code>ECPoint</code> for use 1805db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root * by subsequent multiplication. 1815db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root * 1825db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root * @param point 1835db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root * The <code>ECPoint</code> to store precomputations for. 184d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root * @param name 185d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root * A <code>String</code> used to index precomputations of different types. 1865db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root * @param preCompInfo 1875db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root * The values precomputed by the <code>ECMultiplier</code>. 1885db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root */ 189d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public void setPreCompInfo(ECPoint point, String name, PreCompInfo preCompInfo) 1905db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 1915db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root checkPoint(point); 192d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root synchronized (point) 193d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 194d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root Hashtable table = point.preCompTable; 195d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (null == table) 196d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 197d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root point.preCompTable = table = new Hashtable(4); 198d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 199d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root table.put(name, preCompInfo); 200d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 2015db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 2025db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 2035db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root public ECPoint importPoint(ECPoint p) 2045db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 2055db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root if (this == p.getCurve()) 2065db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 2075db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return p; 2085db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 2095db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root if (p.isInfinity()) 2105db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 2115db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return getInfinity(); 2125db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 2135db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 2145db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root // TODO Default behaviour could be improved if the two curves have the same coordinate system by copying any Z coordinates. 2155db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root p = p.normalize(); 2165db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 217d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return validatePoint(p.getXCoord().toBigInteger(), p.getYCoord().toBigInteger(), p.withCompression); 2185db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 2195db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 2205db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root /** 2215db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root * Normalization ensures that any projective coordinate is 1, and therefore that the x, y 2225db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root * coordinates reflect those of the equivalent point in an affine coordinate system. Where more 2235db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root * than one point is to be normalized, this method will generally be more efficient than 2245db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root * normalizing each point separately. 2255db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root * 2265db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root * @param points 2275db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root * An array of points that will be updated in place with their normalized versions, 2285db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root * where necessary 2295db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root */ 2305db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root public void normalizeAll(ECPoint[] points) 2315db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 232028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro normalizeAll(points, 0, points.length, null); 233028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro } 2345db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 235028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro /** 236028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro * Normalization ensures that any projective coordinate is 1, and therefore that the x, y 237028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro * coordinates reflect those of the equivalent point in an affine coordinate system. Where more 238028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro * than one point is to be normalized, this method will generally be more efficient than 239028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro * normalizing each point separately. An (optional) z-scaling factor can be applied; effectively 240028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro * each z coordinate is scaled by this value prior to normalization (but only one 241028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro * actual multiplication is needed). 242028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro * 243028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro * @param points 244028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro * An array of points that will be updated in place with their normalized versions, 245028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro * where necessary 246028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro * @param off 247028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro * The start of the range of points to normalize 248028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro * @param len 249028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro * The length of the range of points to normalize 250028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro * @param iso 251028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro * The (optional) z-scaling factor - can be null 252028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro */ 253028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro public void normalizeAll(ECPoint[] points, int off, int len, ECFieldElement iso) 254028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro { 255028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro checkPoints(points, off, len); 256028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro 257028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro switch (this.getCoordinateSystem()) 258028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro { 259028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro case ECCurve.COORD_AFFINE: 260028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro case ECCurve.COORD_LAMBDA_AFFINE: 2615db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 262028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro if (iso != null) 263028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro { 264028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro throw new IllegalArgumentException("'iso' not valid for affine coordinates"); 265028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro } 2665db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return; 2675db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 268028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro } 2695db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 2705db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root /* 2715db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root * Figure out which of the points actually need to be normalized 2725db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root */ 273028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro ECFieldElement[] zs = new ECFieldElement[len]; 274028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro int[] indices = new int[len]; 2755db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root int count = 0; 276028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro for (int i = 0; i < len; ++i) 2775db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 278028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro ECPoint p = points[off + i]; 279028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro if (null != p && (iso != null || !p.isNormalized())) 2805db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 2815db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root zs[count] = p.getZCoord(0); 282028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro indices[count++] = off + i; 2835db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 2845db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 2855db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 2865db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root if (count == 0) 2875db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 2885db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return; 2895db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 2905db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 291028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro ECAlgorithms.montgomeryTrick(zs, 0, count, iso); 2925db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 2935db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root for (int j = 0; j < count; ++j) 2945db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 2955db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root int index = indices[j]; 2965db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root points[index] = points[index].normalize(zs[j]); 2975db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 2985db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 2998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 3008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public abstract ECPoint getInfinity(); 3018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 302d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public FiniteField getField() 303d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 304d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return field; 305d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 306d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 3078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public ECFieldElement getA() 3088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 3098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return a; 3108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 3118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 3128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public ECFieldElement getB() 3138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 3148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return b; 3158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 3168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 317d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public BigInteger getOrder() 318d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 319d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return order; 320d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 321d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 322d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public BigInteger getCofactor() 323d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 324d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return cofactor; 325d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 326d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 3275db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root public int getCoordinateSystem() 3285db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 3295db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return coord; 3305db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 3315db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 332a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom protected abstract ECPoint decompressPoint(int yTilde, BigInteger X1); 333a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom 334d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public ECEndomorphism getEndomorphism() 335d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 336d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return endomorphism; 337d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 338d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 339a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom /** 3405db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root * Sets the default <code>ECMultiplier</code>, unless already set. 3415db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root */ 342d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public synchronized ECMultiplier getMultiplier() 3435db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 3445db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root if (this.multiplier == null) 3455db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 3465db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root this.multiplier = createDefaultMultiplier(); 3475db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 3485db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return this.multiplier; 3495db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 3505db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 3515db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root /** 352a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom * Decode a point on this curve from its ASN.1 encoding. The different 353a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom * encodings are taken account of, including point compression for 354a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom * <code>F<sub>p</sub></code> (X9.62 s 4.2.1 pg 17). 355a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom * @return The decoded point. 356a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom */ 357a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom public ECPoint decodePoint(byte[] encoded) 358a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom { 359a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom ECPoint p = null; 360a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom int expectedLength = (getFieldSize() + 7) / 8; 361a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom 362d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root byte type = encoded[0]; 363d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root switch (type) 364a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom { 365a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom case 0x00: // infinity 366a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom { 367a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom if (encoded.length != 1) 368a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom { 369a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom throw new IllegalArgumentException("Incorrect length for infinity encoding"); 370a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom } 371a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom 372a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom p = getInfinity(); 373a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom break; 374a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom } 375a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom case 0x02: // compressed 376a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom case 0x03: // compressed 377a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom { 378a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom if (encoded.length != (expectedLength + 1)) 379a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom { 380a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom throw new IllegalArgumentException("Incorrect length for compressed encoding"); 381a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom } 382a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom 383d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root int yTilde = type & 1; 3845db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength); 385a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom 3865db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root p = decompressPoint(yTilde, X); 387d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (!p.satisfiesCofactor()) 388d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 389d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root throw new IllegalArgumentException("Invalid point"); 390d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 391d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 392a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom break; 393a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom } 394a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom case 0x04: // uncompressed 395d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 396d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (encoded.length != (2 * expectedLength + 1)) 397d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 398d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root throw new IllegalArgumentException("Incorrect length for uncompressed encoding"); 399d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 400d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 401d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength); 402d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root BigInteger Y = BigIntegers.fromUnsignedByteArray(encoded, 1 + expectedLength, expectedLength); 403d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 404d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root p = validatePoint(X, Y); 405d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root break; 406d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 407a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom case 0x06: // hybrid 408a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom case 0x07: // hybrid 409a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom { 410a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom if (encoded.length != (2 * expectedLength + 1)) 411a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom { 412d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root throw new IllegalArgumentException("Incorrect length for hybrid encoding"); 413a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom } 414a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom 4155db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength); 4165db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root BigInteger Y = BigIntegers.fromUnsignedByteArray(encoded, 1 + expectedLength, expectedLength); 417a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom 418d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (Y.testBit(0) != (type == 0x07)) 419d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 420d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root throw new IllegalArgumentException("Inconsistent Y coordinate in hybrid encoding"); 421d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 422d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 423d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root p = validatePoint(X, Y); 424a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom break; 425a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom } 426a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom default: 427d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root throw new IllegalArgumentException("Invalid point encoding 0x" + Integer.toString(type, 16)); 428d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 429d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 430d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (type != 0x00 && p.isInfinity()) 431d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 432d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root throw new IllegalArgumentException("Invalid infinity encoding"); 433a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom } 434a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom 435a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom return p; 436a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom } 437a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom 4385db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root protected void checkPoint(ECPoint point) 439a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom { 4405db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root if (null == point || (this != point.getCurve())) 4415db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 4425db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root throw new IllegalArgumentException("'point' must be non-null and on this curve"); 4435db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 4445db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 4455db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 4465db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root protected void checkPoints(ECPoint[] points) 4475db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 448028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro checkPoints(points, 0, points.length); 449028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro } 450028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro 451028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro protected void checkPoints(ECPoint[] points, int off, int len) 452028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro { 4535db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root if (points == null) 4545db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 4555db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root throw new IllegalArgumentException("'points' cannot be null"); 4565db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 457028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro if (off < 0 || len < 0 || (off > (points.length - len))) 458028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro { 459028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro throw new IllegalArgumentException("invalid range specified for 'points'"); 460028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro } 4615db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 462028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro for (int i = 0; i < len; ++i) 4635db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 464028ab6e01e3b911024b9b9243e9a0f4ac377c0faSergio Giro ECPoint point = points[off + i]; 4655db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root if (null != point && this != point.getCurve()) 4665db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 4675db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root throw new IllegalArgumentException("'points' entries must be null or on this curve"); 4685db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 4695db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 470a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom } 471a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom 472d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public boolean equals(ECCurve other) 473d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 474d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return this == other 475d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root || (null != other 476d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root && getField().equals(other.getField()) 477d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root && getA().toBigInteger().equals(other.getA().toBigInteger()) 478d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root && getB().toBigInteger().equals(other.getB().toBigInteger())); 479d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 480d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 481d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public boolean equals(Object obj) 482d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 483d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return this == obj || (obj instanceof ECCurve && equals((ECCurve)obj)); 484d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 485d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 486d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public int hashCode() 487d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 488d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return getField().hashCode() 489d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root ^ Integers.rotateLeft(getA().toBigInteger().hashCode(), 8) 490d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root ^ Integers.rotateLeft(getB().toBigInteger().hashCode(), 16); 491d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 492d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 493d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public static abstract class AbstractFp extends ECCurve 494d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 495d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root protected AbstractFp(BigInteger q) 496d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 497d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root super(FiniteFields.getPrimeField(q)); 498d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 499d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 500d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root protected ECPoint decompressPoint(int yTilde, BigInteger X1) 501d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 502d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root ECFieldElement x = this.fromBigInteger(X1); 503d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root ECFieldElement rhs = x.square().add(a).multiply(x).add(b); 504d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root ECFieldElement y = rhs.sqrt(); 505d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 506d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root /* 507d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root * If y is not a square, then we haven't got a point on the curve 508d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root */ 509d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (y == null) 510d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 511d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root throw new IllegalArgumentException("Invalid point compression"); 512d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 513d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 514d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (y.testBitZero() != (yTilde == 1)) 515d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 516d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root // Use the other root 517d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root y = y.negate(); 518d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 519d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 520d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return this.createRawPoint(x, y, true); 521d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 522d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 523d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 5248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 5258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Elliptic curve over Fp 5268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 527d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public static class Fp extends AbstractFp 5288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 5295db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root private static final int FP_DEFAULT_COORDS = COORD_JACOBIAN_MODIFIED; 5305db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 5315db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root BigInteger q, r; 5328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECPoint.Fp infinity; 5338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 5348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public Fp(BigInteger q, BigInteger a, BigInteger b) 5358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 536d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root this(q, a, b, null, null); 537d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 538d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 539d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public Fp(BigInteger q, BigInteger a, BigInteger b, BigInteger order, BigInteger cofactor) 540d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 541d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root super(q); 542d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 5438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom this.q = q; 5445db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root this.r = ECFieldElement.Fp.calculateResidue(q); 5455db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root this.infinity = new ECPoint.Fp(this, null, null); 5465db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 5478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom this.a = fromBigInteger(a); 5488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom this.b = fromBigInteger(b); 549d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root this.order = order; 550d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root this.cofactor = cofactor; 5515db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root this.coord = FP_DEFAULT_COORDS; 5525db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 5535db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 5545db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root protected Fp(BigInteger q, BigInteger r, ECFieldElement a, ECFieldElement b) 5555db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 556d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root this(q, r, a, b, null, null); 557d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 558d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 559d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root protected Fp(BigInteger q, BigInteger r, ECFieldElement a, ECFieldElement b, BigInteger order, BigInteger cofactor) 560d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 561d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root super(q); 562d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 5635db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root this.q = q; 5645db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root this.r = r; 5658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom this.infinity = new ECPoint.Fp(this, null, null); 5665db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 5675db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root this.a = a; 5685db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root this.b = b; 569d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root this.order = order; 570d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root this.cofactor = cofactor; 5715db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root this.coord = FP_DEFAULT_COORDS; 5725db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 5735db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 5745db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root protected ECCurve cloneCurve() 5755db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 576d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return new Fp(q, r, a, b, order, cofactor); 5775db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 5785db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 5795db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root public boolean supportsCoordinateSystem(int coord) 5805db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 5815db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root switch (coord) 5825db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 5835db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root case COORD_AFFINE: 5845db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root case COORD_HOMOGENEOUS: 5855db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root case COORD_JACOBIAN: 5865db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root case COORD_JACOBIAN_MODIFIED: 5875db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return true; 5885db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root default: 5895db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return false; 5905db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 5918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 5928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 5938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public BigInteger getQ() 5948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 5958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return q; 5968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 5978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 5988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public int getFieldSize() 5998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 6008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return q.bitLength(); 6018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 6028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 6038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public ECFieldElement fromBigInteger(BigInteger x) 6048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 6055db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return new ECFieldElement.Fp(this.q, this.r, x); 6068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 6078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 6085db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression) 6098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 6105db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return new ECPoint.Fp(this, x, y, withCompression); 6115db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 6125db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 613d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression) 614d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 615d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return new ECPoint.Fp(this, x, y, zs, withCompression); 616d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 617d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 6185db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root public ECPoint importPoint(ECPoint p) 6195db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 6205db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root if (this != p.getCurve() && this.getCoordinateSystem() == COORD_JACOBIAN && !p.isInfinity()) 6215db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 6225db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root switch (p.getCurve().getCoordinateSystem()) 6235db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 6245db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root case COORD_JACOBIAN: 6255db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root case COORD_JACOBIAN_CHUDNOVSKY: 6265db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root case COORD_JACOBIAN_MODIFIED: 6275db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return new ECPoint.Fp(this, 6285db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root fromBigInteger(p.x.toBigInteger()), 6295db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root fromBigInteger(p.y.toBigInteger()), 6305db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root new ECFieldElement[]{ fromBigInteger(p.zs[0].toBigInteger()) }, 6315db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root p.withCompression); 6325db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root default: 6335db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root break; 6345db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 6355db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 6365db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 6375db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return super.importPoint(p); 6388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 6398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 640d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public ECPoint getInfinity() 6418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 642d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return infinity; 643d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 644d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 645a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom 646d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public static abstract class AbstractF2m extends ECCurve 647d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 648d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root private static FiniteField buildField(int m, int k1, int k2, int k3) 649d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 650d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (k1 == 0) 6518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 652d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root throw new IllegalArgumentException("k1 must be > 0"); 653a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom } 6548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 655d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (k2 == 0) 656a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom { 657d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (k3 != 0) 658d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 659d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root throw new IllegalArgumentException("k3 must be 0 if k2 == 0"); 660d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 6618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 662d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return FiniteFields.getBinaryExtensionField(new int[]{ 0, k1, m }); 663d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 6648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 665d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (k2 <= k1) 6668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 667d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root throw new IllegalArgumentException("k2 must be > k1"); 6688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 6698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 670d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (k3 <= k2) 6718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 672d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root throw new IllegalArgumentException("k3 must be > k2"); 6738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 6748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 675d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return FiniteFields.getBinaryExtensionField(new int[]{ 0, k1, k2, k3, m }); 6768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 6778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 678d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root protected AbstractF2m(int m, int k1, int k2, int k3) 6798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 680d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root super(buildField(m, k1, k2, k3)); 6818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 6828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 6838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 6848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 6858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Elliptic curves over F2m. The Weierstrass equation is given by 6868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * <code>y<sup>2</sup> + xy = x<sup>3</sup> + ax<sup>2</sup> + b</code>. 6878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 688d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root public static class F2m extends AbstractF2m 6898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 690d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root private static final int F2M_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE; 6915db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 6928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 6938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>. 6948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 6958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom private int m; // can't be final - JDK 1.1 6968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 6978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 6988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * TPB: The integer <code>k</code> where <code>x<sup>m</sup> + 6998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * x<sup>k</sup> + 1</code> represents the reduction polynomial 7008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * <code>f(z)</code>.<br> 7018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> + 7028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 7038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * represents the reduction polynomial <code>f(z)</code>.<br> 7048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 7058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom private int k1; // can't be final - JDK 1.1 7068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 7078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 7088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * TPB: Always set to <code>0</code><br> 7098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> + 7108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 7118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * represents the reduction polynomial <code>f(z)</code>.<br> 7128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 7138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom private int k2; // can't be final - JDK 1.1 7148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 7158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 7168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * TPB: Always set to <code>0</code><br> 7178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> + 7188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 7198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * represents the reduction polynomial <code>f(z)</code>.<br> 7208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 7218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom private int k3; // can't be final - JDK 1.1 7228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 7238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 7248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * The point at infinity on this curve. 7258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 7268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom private ECPoint.F2m infinity; // can't be final - JDK 1.1 7278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 7288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 7298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * The parameter <code>μ</code> of the elliptic curve if this is 7308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * a Koblitz curve. 7318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 7328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom private byte mu = 0; 7338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 7348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 7358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * The auxiliary values <code>s<sub>0</sub></code> and 7368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * <code>s<sub>1</sub></code> used for partial modular reduction for 7378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Koblitz curves. 7388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 7398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom private BigInteger[] si = null; 7408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 7418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 7428212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Constructor for Trinomial Polynomial Basis (TPB). 7438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param m The exponent <code>m</code> of 7448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * <code>F<sub>2<sup>m</sup></sub></code>. 7458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param k The integer <code>k</code> where <code>x<sup>m</sup> + 7468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * x<sup>k</sup> + 1</code> represents the reduction 7478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * polynomial <code>f(z)</code>. 7488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param a The coefficient <code>a</code> in the Weierstrass equation 7498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * for non-supersingular elliptic curves over 7508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * <code>F<sub>2<sup>m</sup></sub></code>. 7518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param b The coefficient <code>b</code> in the Weierstrass equation 7528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * for non-supersingular elliptic curves over 7538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * <code>F<sub>2<sup>m</sup></sub></code>. 7548212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 7558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public F2m( 7568212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom int m, 7578212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom int k, 7588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom BigInteger a, 7598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom BigInteger b) 7608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 7618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom this(m, k, 0, 0, a, b, null, null); 7628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 7638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 7648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 7658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Constructor for Trinomial Polynomial Basis (TPB). 7668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param m The exponent <code>m</code> of 7678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * <code>F<sub>2<sup>m</sup></sub></code>. 7688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param k The integer <code>k</code> where <code>x<sup>m</sup> + 7698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * x<sup>k</sup> + 1</code> represents the reduction 7708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * polynomial <code>f(z)</code>. 7718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param a The coefficient <code>a</code> in the Weierstrass equation 7728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * for non-supersingular elliptic curves over 7738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * <code>F<sub>2<sup>m</sup></sub></code>. 7748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param b The coefficient <code>b</code> in the Weierstrass equation 7758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * for non-supersingular elliptic curves over 7768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * <code>F<sub>2<sup>m</sup></sub></code>. 777d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root * @param order The order of the main subgroup of the elliptic curve. 778d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root * @param cofactor The cofactor of the elliptic curve, i.e. 7798212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>. 7808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 7818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public F2m( 7828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom int m, 7838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom int k, 7848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom BigInteger a, 7858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom BigInteger b, 786d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root BigInteger order, 787d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root BigInteger cofactor) 7888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 789d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root this(m, k, 0, 0, a, b, order, cofactor); 7908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 7918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 7928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 7938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Constructor for Pentanomial Polynomial Basis (PPB). 7948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param m The exponent <code>m</code> of 7958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * <code>F<sub>2<sup>m</sup></sub></code>. 7968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> + 7978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 7988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * represents the reduction polynomial <code>f(z)</code>. 7998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> + 8008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 8018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * represents the reduction polynomial <code>f(z)</code>. 8028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> + 8038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 8048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * represents the reduction polynomial <code>f(z)</code>. 8058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param a The coefficient <code>a</code> in the Weierstrass equation 8068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * for non-supersingular elliptic curves over 8078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * <code>F<sub>2<sup>m</sup></sub></code>. 8088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param b The coefficient <code>b</code> in the Weierstrass equation 8098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * for non-supersingular elliptic curves over 8108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * <code>F<sub>2<sup>m</sup></sub></code>. 8118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 8128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public F2m( 8138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom int m, 8148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom int k1, 8158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom int k2, 8168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom int k3, 8178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom BigInteger a, 8188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom BigInteger b) 8198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 8208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom this(m, k1, k2, k3, a, b, null, null); 8218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 8228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 8238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 8248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Constructor for Pentanomial Polynomial Basis (PPB). 8258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param m The exponent <code>m</code> of 8268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * <code>F<sub>2<sup>m</sup></sub></code>. 8278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> + 8288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 8298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * represents the reduction polynomial <code>f(z)</code>. 8308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> + 8318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 8328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * represents the reduction polynomial <code>f(z)</code>. 8338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> + 8348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> 8358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * represents the reduction polynomial <code>f(z)</code>. 8368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param a The coefficient <code>a</code> in the Weierstrass equation 8378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * for non-supersingular elliptic curves over 8388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * <code>F<sub>2<sup>m</sup></sub></code>. 8398212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param b The coefficient <code>b</code> in the Weierstrass equation 8408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * for non-supersingular elliptic curves over 8418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * <code>F<sub>2<sup>m</sup></sub></code>. 842d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root * @param order The order of the main subgroup of the elliptic curve. 843d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root * @param cofactor The cofactor of the elliptic curve, i.e. 8448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>. 8458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 8468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public F2m( 8478212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom int m, 8488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom int k1, 8498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom int k2, 8508212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom int k3, 8518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom BigInteger a, 8528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom BigInteger b, 853d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root BigInteger order, 854d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root BigInteger cofactor) 8558212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 856d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root super(m, k1, k2, k3); 857d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 8588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom this.m = m; 8598212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom this.k1 = k1; 8608212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom this.k2 = k2; 8618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom this.k3 = k3; 862d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root this.order = order; 863d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root this.cofactor = cofactor; 8648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 8655db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root this.infinity = new ECPoint.F2m(this, null, null); 8668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom this.a = fromBigInteger(a); 8678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom this.b = fromBigInteger(b); 8685db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root this.coord = F2M_DEFAULT_COORDS; 8695db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 8705db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 871d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root protected F2m(int m, int k1, int k2, int k3, ECFieldElement a, ECFieldElement b, BigInteger order, BigInteger cofactor) 8725db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 873d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root super(m, k1, k2, k3); 874d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 8755db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root this.m = m; 8765db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root this.k1 = k1; 8775db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root this.k2 = k2; 8785db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root this.k3 = k3; 879d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root this.order = order; 880d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root this.cofactor = cofactor; 8815db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 8828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom this.infinity = new ECPoint.F2m(this, null, null); 8835db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root this.a = a; 8845db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root this.b = b; 8855db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root this.coord = F2M_DEFAULT_COORDS; 8865db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 8875db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 8885db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root protected ECCurve cloneCurve() 8895db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 890d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return new F2m(m, k1, k2, k3, a, b, order, cofactor); 8915db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 8925db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 8935db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root public boolean supportsCoordinateSystem(int coord) 8945db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 8955db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root switch (coord) 8965db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 8975db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root case COORD_AFFINE: 8985db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root case COORD_HOMOGENEOUS: 8995db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root case COORD_LAMBDA_PROJECTIVE: 9005db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return true; 9015db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root default: 9025db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return false; 9035db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 9045db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 9055db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 9065db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root protected ECMultiplier createDefaultMultiplier() 9075db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 9085db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root if (isKoblitz()) 9095db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 9105db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return new WTauNafMultiplier(); 9115db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 9125db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 9135db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return super.createDefaultMultiplier(); 9148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 9158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 9168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public int getFieldSize() 9178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 9188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return m; 9198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 9208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 9218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public ECFieldElement fromBigInteger(BigInteger x) 9228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 9238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3, x); 9248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 9258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 9268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression) 9278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 9285db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root ECFieldElement X = fromBigInteger(x), Y = fromBigInteger(y); 9295db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 9305db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root switch (this.getCoordinateSystem()) 9315db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 9325db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root case COORD_LAMBDA_AFFINE: 9335db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root case COORD_LAMBDA_PROJECTIVE: 9345db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 935d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (X.isZero()) 936d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 937d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (!Y.square().equals(this.getB())) 938d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 939d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root throw new IllegalArgumentException(); 940d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 941d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 942d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root else 9435db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 9445db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root // Y becomes Lambda (X + Y/X) here 9455db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root Y = Y.divide(X).add(X); 9465db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 9475db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root break; 9485db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 9495db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root default: 9505db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 9515db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root break; 9525db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 9535db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 9545db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 9555db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return createRawPoint(X, Y, withCompression); 9565db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 9575db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 9585db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression) 9595db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 9605db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return new ECPoint.F2m(this, x, y, withCompression); 9618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 9628212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 963d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression) 964d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 965d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return new ECPoint.F2m(this, x, y, zs, withCompression); 966d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 967d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 9688212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public ECPoint getInfinity() 9698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 9708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return infinity; 9718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 9728212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 9738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 9748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Returns true if this is a Koblitz curve (ABC curve). 9758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @return true if this is a Koblitz curve (ABC curve), false otherwise 9768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 9778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public boolean isKoblitz() 9788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 979d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return order != null && cofactor != null && b.isOne() && (a.isZero() || a.isOne()); 9808212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 9818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 9828212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 9838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Returns the parameter <code>μ</code> of the elliptic curve. 9848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @return <code>μ</code> of the elliptic curve. 9858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @throws IllegalArgumentException if the given ECCurve is not a 9868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Koblitz curve. 9878212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 9888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom synchronized byte getMu() 9898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 9908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (mu == 0) 9918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 9928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom mu = Tnaf.getMu(this); 9938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 9948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return mu; 9958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 9968212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 9978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 9988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @return the auxiliary values <code>s<sub>0</sub></code> and 9998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * <code>s<sub>1</sub></code> used for partial modular reduction for 10008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Koblitz curves. 10018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 10028212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom synchronized BigInteger[] getSi() 10038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 10048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom if (si == null) 10058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 10068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom si = Tnaf.getSi(this); 10078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 10088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return si; 10098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 10108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 10118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 10128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). 10138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * 1014a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom * @param yTilde 10158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * ~yp, an indication bit for the decompression of yp. 1016a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom * @param X1 1017a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom * The field element xp. 10188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @return the decompressed point. 10198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 1020a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom protected ECPoint decompressPoint(int yTilde, BigInteger X1) 10218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 1022d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root ECFieldElement x = fromBigInteger(X1), y = null; 1023d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (x.isZero()) 10248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 1025d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root y = b.sqrt(); 10268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 10278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom else 10288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 1029d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root ECFieldElement beta = x.square().invert().multiply(b).add(a).add(x); 10305db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root ECFieldElement z = solveQuadraticEquation(beta); 1031d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (z != null) 10328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 1033d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (z.testBitZero() != (yTilde == 1)) 1034d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 1035d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root z = z.addOne(); 1036d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 1037d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 1038d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root switch (this.getCoordinateSystem()) 1039d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 1040d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root case COORD_LAMBDA_AFFINE: 1041d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root case COORD_LAMBDA_PROJECTIVE: 1042d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 1043d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root y = z.add(x); 1044d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root break; 1045d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 1046d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root default: 1047d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 1048d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root y = z.multiply(x); 1049d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root break; 1050d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 1051d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 10528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 1053d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root } 10545db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 1055d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root if (y == null) 1056d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root { 1057d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root throw new IllegalArgumentException("Invalid point compression"); 10588212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 1059a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom 1060d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return this.createRawPoint(x, y, true); 10618212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 1062d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root 10638212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 10648212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62 10658212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * D.1.6) The other solution is <code>z + 1</code>. 10668212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * 10678212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @param beta 10685db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root * The value to solve the quadratic equation for. 10698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @return the solution for <code>z<sup>2</sup> + z = beta</code> or 10708212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * <code>null</code> if no solution exists. 10718212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 10725db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root private ECFieldElement solveQuadraticEquation(ECFieldElement beta) 10738212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 10745db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root if (beta.isZero()) 10758212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 10765db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return beta; 10778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 10788212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 10795db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root ECFieldElement zeroElement = fromBigInteger(ECConstants.ZERO); 10805db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root 10818212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECFieldElement z = null; 10825db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root ECFieldElement gamma = null; 10838212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 10848212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom Random rand = new Random(); 10858212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom do 10868212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 10875db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root ECFieldElement t = fromBigInteger(new BigInteger(m, rand)); 10888212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom z = zeroElement; 10898212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECFieldElement w = beta; 10908212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom for (int i = 1; i <= m - 1; i++) 10918212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 10928212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom ECFieldElement w2 = w.square(); 10938212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom z = z.square().add(w2.multiply(t)); 10948212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom w = w2.add(beta); 10958212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 10965db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root if (!w.isZero()) 10978212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 10988212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return null; 10998212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 11008212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom gamma = z.square().add(z); 11018212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 11025db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root while (gamma.isZero()); 11038212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 11048212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return z; 11058212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 11068212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 11078212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public int getM() 11088212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 11098212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return m; 11108212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 11118212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 11128212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom /** 11138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Return true if curve uses a Trinomial basis. 11148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * 11158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * @return true if curve Trinomial, false otherwise. 11168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 11178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public boolean isTrinomial() 11188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 11198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return k2 == 0 && k3 == 0; 11208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 11218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 11228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public int getK1() 11238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 11248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return k1; 11258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 11268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 11278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public int getK2() 11288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 11298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return k2; 11308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 11318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 11328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public int getK3() 11338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 11348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom return k3; 11358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 11368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 1137d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root /** 1138d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root * @deprecated use {@link #getOrder()} instead 1139d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root */ 11408212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public BigInteger getN() 11418212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 1142d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return order; 11438212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 11448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 1145d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root /** 1146d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root * @deprecated use {@link #getCofactor()} instead 1147d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root */ 11488212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public BigInteger getH() 11498212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 1150d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root return cofactor; 11518212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 11528212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 11538212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom} 1154