package threshold.mr04; import java.io.IOException; import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Random; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.sec.SECNamedCurves; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.asn1.x9.X9ECPoint; import org.bouncycastle.crypto.params.ECDomainParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.crypto.signers.ECDSASigner; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.ec.ECPoint; import threshold.mr04.data.PublicParameters; public class Util { /** * 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; } } // modified from bitcoinj ECKEy public static ECPoint compressPoint(ECPoint uncompressed, ECDomainParameters CURVE) { return new ECPoint.Fp(CURVE.getCurve(), uncompressed.getX(), uncompressed.getY(), true); } 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; } } public static byte[] getBytes(BigInteger n) { return n.toByteArray(); } public static byte[] getBytes(ECPoint e) { // ASK ROSARIO 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; } /** * Returns an element from Z_n randomly seleted using the randomness from * {@code rand} * * @param n * the modulus */ 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 isElementOfZn(BigInteger element, BigInteger n) { return (element.compareTo(BigInteger.ZERO) != -1) && (element.compareTo(n) == -1); } /** * Returns an element from Z_n^* randomly seleted 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 PublicParameters generateParamsforBitcoin(int k, int kPrime, SecureRandom rand, PaillierPublicKey alicesPaillierPubKey) { X9ECParameters params = SECNamedCurves.getByName("secp256k1"); ECDomainParameters CURVE = new ECDomainParameters(params.getCurve(), params.getG(), params.getN(), params.getH()); Paillier otherPaillier = new Paillier(kPrime, k); PaillierPublicKey otherPaillierPubKey = new PaillierPublicKey(otherPaillier.n, otherPaillier.g); 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)); 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, alicesPaillierPubKey, otherPaillierPubKey); }; }