All Downloads are FREE. Search and download functionalities are using the official Maven repository.

exchange.apexpro.connector.impl.utils.ecdsa.EcMath Maven / Gradle / Ivy

There is a newer version: 2.0.2
Show newest version
package exchange.apexpro.connector.impl.utils.ecdsa;
import java.math.BigInteger;


public final class EcMath {

    /**
     * Fast way to multiply point and scalar in elliptic curves
     */
    public static Point multiply(Point p, BigInteger n, BigInteger N, BigInteger A, BigInteger P) {
        return fromJacobian(jacobianMultiply(toJacobian(p), n, N, A, P), P);
    }

    /**
     * Fast way to add two points in elliptic curves
     */
    public static Point add(Point p, Point q, BigInteger A, BigInteger P) {
        return fromJacobian(jacobianAdd(toJacobian(p), toJacobian(q), A, P), P);
    }

    /**
     * Extended Euclidean Algorithm. It's the 'division' in elliptic curves
     */
    public static BigInteger inv(BigInteger x, BigInteger n) {
        if (x.compareTo(BigInteger.ZERO) == 0) {
            return BigInteger.ZERO;
        }
        BigInteger lm = BigInteger.ONE;
        BigInteger hm = BigInteger.ZERO;
        BigInteger high = n;
        BigInteger low = x.mod(n);
        BigInteger r, nm, nw;
        while (low.compareTo(BigInteger.ONE) > 0) {
            r = high.divide(low);
            nm = hm.subtract(lm.multiply(r));
            nw = high.subtract(low.multiply(r));
            high = low;
            hm = lm;
            low = nw;
            lm = nm;
        }
        return lm.mod(n);
    }

    /**
     * Convert point to Jacobian coordinates
     */
    public static Point toJacobian(Point p) {

        return new Point(p.x, p.y, BigInteger.ONE);
    }

    /**
     * Convert point back from Jacobian coordinates
     */
    public static Point fromJacobian(Point p, BigInteger P) {
        BigInteger z = inv(p.z, P);
        BigInteger x = p.x.multiply(z.pow(2)).mod(P);
        BigInteger y = p.y.multiply(z.pow(3)).mod(P);
        return new Point(x, y, BigInteger.ZERO);
    }

    /**
     * Double a point in elliptic curves
     */
    public static Point jacobianDouble(Point p, BigInteger A, BigInteger P) {
        if (p.y == null || p.y.equals(BigInteger.ZERO)) {
            return new Point(BigInteger.ZERO, BigInteger.ZERO, BigInteger.ZERO);
        }
        BigInteger ysq = p.y.pow(2).mod(P);
        BigInteger S = BigInteger.valueOf(4).multiply(p.x).multiply(ysq).mod(P);
        BigInteger M = BigInteger.valueOf(3).multiply(p.x.pow(2)).add(A.multiply(p.z.pow(4))).mod(P);
        BigInteger nx = M.pow(2).subtract(BigInteger.valueOf(2).multiply(S)).mod(P);
        BigInteger ny = M.multiply(S.subtract(nx)).subtract(BigInteger.valueOf(8).multiply(ysq.pow(2))).mod(P);
        BigInteger nz = BigInteger.valueOf(2).multiply(p.y).multiply(p.z).mod(P);
        return new Point(nx, ny, nz);
    }

    /**
     * Add two points in elliptic curves
     */
    public static Point jacobianAdd(Point p, Point q, BigInteger A, BigInteger P) {
        if (p.y == null || p.y.equals(BigInteger.ZERO)) {
            return q;
        }
        if (q.y == null || q.y.equals(BigInteger.ZERO)) {
            return p;
        }
        BigInteger U1 = p.x.multiply(q.z.pow(2)).mod(P);
        BigInteger U2 = q.x.multiply(p.z.pow(2)).mod(P);
        BigInteger S1 = p.y.multiply(q.z.pow(3)).mod(P);
        BigInteger S2 = q.y.multiply(p.z.pow(3)).mod(P);
        if (U1.compareTo(U2) == 0) {
            if (S1.compareTo(S2) != 0) {
                return new Point(BigInteger.ZERO, BigInteger.ZERO, BigInteger.ONE);
            }
            return jacobianDouble(p, A, P);
        }
        BigInteger H = U2.subtract(U1);
        BigInteger R = S2.subtract(S1);
        BigInteger H2 = H.multiply(H).mod(P);
        BigInteger H3 = H.multiply(H2).mod(P);
        BigInteger U1H2 = U1.multiply(H2).mod(P);
        BigInteger nx = R.pow(2).subtract(H3).subtract(BigInteger.valueOf(2).multiply(U1H2)).mod(P);
        BigInteger ny = R.multiply(U1H2.subtract(nx)).subtract(S1.multiply(H3)).mod(P);
        BigInteger nz = H.multiply(p.z).multiply(q.z).mod(P);
        return new Point(nx, ny, nz);
    }

    /**
     * Multiply point and scalar in elliptic curves
     */
    public static Point jacobianMultiply(Point p, BigInteger n, BigInteger N, BigInteger A, BigInteger P) {
        if (BigInteger.ZERO.compareTo(p.y) == 0 || BigInteger.ZERO.compareTo(n) == 0) {
            return new Point(BigInteger.ZERO, BigInteger.ZERO, BigInteger.ONE);
        }
        if (BigInteger.ONE.compareTo(n) == 0) {
            return p;
        }
        if (n.compareTo(BigInteger.ZERO) < 0 || n.compareTo(N) >= 0) {
            return jacobianMultiply(p, n.mod(N), N, A, P);
        }
        if (n.mod(BigInteger.valueOf(2)).compareTo(BigInteger.ZERO) == 0) {
            return jacobianDouble(jacobianMultiply(p, n.divide(BigInteger.valueOf(2)), N, A, P), A, P);
        }
        if (n.mod(BigInteger.valueOf(2)).compareTo(BigInteger.ONE) == 0) {
            return jacobianAdd(jacobianDouble(jacobianMultiply(p, n.divide(BigInteger.valueOf(2)), N, A, P), A, P), p, A, P);
        }
        return null;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy