/* This file is part of Wattzap Community Edition. * * Wattzap Community Edtion is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Wattzap Community Edition is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Wattzap. If not, see <http://www.gnu.org/licenses/>. */ package ecc.elliptic; /**An implementation of an elliptic curve over a -finite- field. * */ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.math.BigInteger; public class EllipticCurve { private BigInteger a, b, p, order; private ECPoint generator; private BigInteger ppodbf; private int pointcmpsize; private String name; public static final BigInteger COEFA = new BigInteger("4"); public static final BigInteger COEFB = new BigInteger("27"); public static final int PRIMESECURITY = 500; /** * Constructs an elliptic curve over the finite field of 'mod' elements. The * equation of the curve is on the form : y^2 = x^3 + ax + b. * * @param a * the value of 'a' where y^2 = x^3 + ax + b * @param b * the value of 'b' where y^2 = x^3 + ax + b * @param mod * The number of elements in the field. IMPORTANT: Must a prime * number! * @exception InsecureCurveException * if the curve defined by a and b are singular, * supersingular, trace one/anomalous. This ensures well * defined operations and security. */ public EllipticCurve(BigInteger a, BigInteger b, BigInteger p) throws InsecureCurveException { this.a = a; this.b = b; this.p = p; if (!p.isProbablePrime(PRIMESECURITY)) { // System.out.println("THIS CANNOT HAPPEN!!! "+p+" is not a prime!"); // throw new // InsecureCurveException(InsecureCurveException.NONPRIMEMODULUS,this); } if (isSingular()) throw new InsecureCurveException(InsecureCurveException.SINGULAR, this); byte[] pb = p.toByteArray(); if (pb[0] == 0) pointcmpsize = pb.length; else pointcmpsize = pb.length + 1; // ppodbf = (p.add(BigInteger.ONE)).shiftRight(2); name = ""; // FIXME compute the order of the group // FIXME compute a generator for the group } public EllipticCurve(ECParameters ecp) throws InsecureCurveException { this(ecp.a(), ecp.b(), ecp.p()); order = ecp.order(); name = ecp.toString(); try { generator = new ECPoint(this, ecp.generatorX(), ecp.generatorY()); generator.fastCache(); } catch (NotOnMotherException e) { System.out .println("Error defining EllipticCurve: generator not on mother!"); } } public void writeCurve(DataOutputStream output) throws IOException { byte[] ab = a.toByteArray(); output.writeInt(ab.length); output.write(ab); byte[] bb = b.toByteArray(); output.writeInt(bb.length); output.write(bb); byte[] pb = p.toByteArray(); output.writeInt(pb.length); output.write(pb); byte[] ob = order.toByteArray(); output.writeInt(ob.length); output.write(ob); byte[] gb = generator.compress(); output.writeInt(gb.length); output.write(gb); byte[] ppb = getPPODBF().toByteArray(); output.writeInt(ppb.length); output.write(ppb); output.writeInt(pointcmpsize); output.writeUTF(name); } protected EllipticCurve(DataInputStream input) throws IOException { byte[] ab = new byte[input.readInt()]; input.read(ab); a = new BigInteger(ab); byte[] bb = new byte[input.readInt()]; input.read(bb); b = new BigInteger(bb); byte[] pb = new byte[input.readInt()]; input.read(pb); p = new BigInteger(pb); byte[] ob = new byte[input.readInt()]; input.read(ob); order = new BigInteger(ob); byte[] gb = new byte[input.readInt()]; input.read(gb); generator = new ECPoint(gb, this); byte[] ppb = new byte[input.readInt()]; input.read(ppb); ppodbf = new BigInteger(ppb); pointcmpsize = input.readInt(); name = input.readUTF(); generator.fastCache(); } public boolean isSingular() { BigInteger aa = a.pow(3); BigInteger bb = b.pow(2); BigInteger result = ((aa.multiply(COEFA)).add(bb.multiply(COEFB))) .mod(p); if (result.compareTo(BigInteger.ZERO) == 0) return true; else return false; } // FIXME!!!!!!!!!! public BigInteger calculateOrder() { return null; } // FIXME!!!!!!!! public ECPoint calculateGenerator() { return null; } public boolean onCurve(ECPoint q) { if (q.isZero()) return true; BigInteger y_square = (q.gety()).modPow(new BigInteger("2"), p); BigInteger x_cube = (q.getx()).modPow(new BigInteger("3"), p); BigInteger x = q.getx(); BigInteger dum = ((x_cube.add(a.multiply(x))).add(b)).mod(p); if (y_square.compareTo(dum) == 0) return true; else return false; } /** Returns the order of the group */ public BigInteger getOrder() { return order; } public ECPoint getZero() { return new ECPoint(this); } public BigInteger geta() { return a; } public BigInteger getb() { return b; } public BigInteger getp() { return p; } public int getPCS() { return pointcmpsize; } /** Returns a generator for this EllipticCurve. */ public ECPoint getGenerator() { return generator; } public String toString() { if (name == null) return "y^2 = x^3 + " + a + "x + " + b + " ( mod " + p + " )"; else if (name.equals("")) return "y^2 = x^3 + " + a + "x + " + b + " ( mod " + p + " )"; else return name; } public BigInteger getPPODBF() { if (ppodbf == null) { ppodbf = p.add(BigInteger.ONE).shiftRight(2); } return ppodbf; } }