ACNS.thresholdDSA.Util.java Source code

Java tutorial

Introduction

Here is the source code for ACNS.thresholdDSA.Util.java

Source

/* Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package ACNS.thresholdDSA;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Random;

import org.bouncycastle.asn1.sec.SECNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.signers.ECDSASigner;
import org.bouncycastle.math.ec.ECPoint;

import paillierp.key.KeyGen;
import paillierp.key.PaillierKey;
import ACNS.ZeroKnowledgeProofs.PublicParameters;

public class Util {
    public static BigInteger randomFromZn(BigInteger n, Random rand) {
        BigInteger result;
        do {
            result = new BigInteger(n.bitLength(), rand);
            // check that it's in Zn
        } while (result.compareTo(n) != -1);
        return result;
    }

    public static boolean verifySignature(byte[] message, BigInteger r, BigInteger s, byte[] pub,
            ECDomainParameters Curve) {
        ECDSASigner signer = new ECDSASigner();
        ECPublicKeyParameters params = new ECPublicKeyParameters(Curve.getCurve().decodePoint(pub), Curve);
        signer.init(false, params);
        try {
            return signer.verifySignature(message, r, s);
        } catch (NullPointerException e) {
            // Bouncy Castle contains a bug that can cause NPEs given specially
            // crafted signatures. Those signatures
            // are inherently invalid/attack sigs so we just fail them here
            // rather than crash the thread.
            System.out.println("Caught NPE inside bouncy castle");
            e.printStackTrace();
            return false;
        }
    }

    // modified from bitcoinj ECKEy
    @SuppressWarnings("deprecation")
    public static ECPoint compressPoint(ECPoint uncompressed, ECDomainParameters CURVE) {
        return new ECPoint.Fp(CURVE.getCurve(), uncompressed.getX(), uncompressed.getY(), true);
    }

    /**
     * Method taken (renamed) from SpongyCastle ECDSASigner class. Cannot call
     * from there since it's private and non static.
     */
    public static BigInteger calculateMPrime(BigInteger n, byte[] message) {
        if (n.bitLength() > message.length * 8) {
            return new BigInteger(1, message);
        } else {
            int messageBitLength = message.length * 8;
            BigInteger trunc = new BigInteger(1, message);

            if (messageBitLength - n.bitLength() > 0) {
                trunc = trunc.shiftRight(messageBitLength - n.bitLength());
            }
            return trunc;
        }
    }

    public static boolean isElementOfZn(BigInteger element, BigInteger n) {
        return (element.compareTo(BigInteger.ZERO) != -1) && (element.compareTo(n) == -1);
    }

    /**
     * Returns an element from Z_n^* randomly selected using the randomness from
     * {@code rand}
     * 
     * @param n
     *            the modulus
     */
    public static BigInteger randomFromZnStar(BigInteger n, Random rand) {
        BigInteger result;
        do {
            result = new BigInteger(n.bitLength(), rand);
            // check that it's in Zn*
        } while (result.compareTo(n) != -1 || !result.gcd(n).equals(BigInteger.ONE));
        return result;
    }

    public static byte[] sha256Hash(byte[]... inputs) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            for (byte[] input : inputs) {
                md.update(input);
            }
            return md.digest();

        } catch (NoSuchAlgorithmException ex) {
            throw new AssertionError();
        }
    }

    public static byte[] getBytes(BigInteger n) {
        return n.toByteArray();
    }

    @SuppressWarnings("deprecation")
    public static byte[] getBytes(ECPoint e) {
        byte[] x = e.getX().toBigInteger().toByteArray();
        byte[] y = e.getY().toBigInteger().toByteArray();
        byte[] output = new byte[x.length + y.length];
        System.arraycopy(x, 0, output, 0, x.length);
        System.arraycopy(y, 0, output, x.length, y.length);
        return output;
    }

    public static void generatePaillierKeyShares(String filename, SecureRandom rnd, int numPlayers, int threshold)
            throws IOException {
        // A value of 1025 will give us an N of order > 2048. We need N to be
        // O(q^8).
        // Since Bitcoin uses a curve where q is O(2^256), this is big
        // enough
        KeyGen.PaillierThresholdKey(filename, 1023, numPlayers, threshold, rnd.nextLong());
    }

    public static PublicParameters generateParamsforBitcoin(int k, int kPrime, SecureRandom rand,
            PaillierKey paillierPubKey) {

        X9ECParameters params = SECNamedCurves.getByName("secp256k1");
        ECDomainParameters CURVE = new ECDomainParameters(params.getCurve(), params.getG(), params.getN(),
                params.getH());

        int primeCertainty = k;
        BigInteger p;
        BigInteger q;
        BigInteger pPrime;
        BigInteger qPrime;
        BigInteger pPrimeqPrime;
        BigInteger nHat;

        do {
            p = new BigInteger(kPrime / 2, primeCertainty, rand);
        } while (!p.subtract(BigInteger.ONE).divide(BigInteger.valueOf(2)).isProbablePrime(primeCertainty));

        pPrime = p.subtract(BigInteger.ONE).divide(BigInteger.valueOf(2));

        do {
            q = new BigInteger(kPrime / 2, primeCertainty, rand);
        } while (!q.subtract(BigInteger.ONE).divide(BigInteger.valueOf(2)).isProbablePrime(primeCertainty));

        qPrime = q.subtract(BigInteger.ONE).divide(BigInteger.valueOf(2));

        // generate nhat. the product of two safe primes, each of length
        // kPrime/2
        nHat = p.multiply(q);

        BigInteger h2 = randomFromZnStar(nHat, rand);
        pPrimeqPrime = pPrime.multiply(qPrime);

        BigInteger x = randomFromZn(pPrimeqPrime, rand);
        BigInteger h1 = h2.modPow(x, nHat);

        return new PublicParameters(CURVE, nHat, kPrime, h1, h2, paillierPubKey);

    }

    public static byte[] serialize(Serializable obj) throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(obj);
        return bos.toByteArray();
    }

    public static Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
        ObjectInputStream ois = new ObjectInputStream(bis);
        return ois.readObject();

    }
}