more tests for mixer
parent
8f75bebaea
commit
8a07f86c0f
|
@ -13,6 +13,7 @@ import qilin.primitives.RandomOracle;
|
||||||
import qilin.primitives.concrete.ECGroup;
|
import qilin.primitives.concrete.ECGroup;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
@ -95,14 +96,16 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier {
|
||||||
return verifyElGamaOrProof(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,orProof,orProofOrder);
|
return verifyElGamaOrProof(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,orProof,orProofOrder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean verifyElGamaOrProof(ElGamalCiphertext e1,
|
|
||||||
ElGamalCiphertext e2,
|
|
||||||
ElGamalCiphertext e1New,
|
|
||||||
ElGamalCiphertext e2New,
|
|
||||||
Mixing.ZeroKnowledgeProof.OrProof orProof, ProofOrganizer.OrProofOrder orProofOrder)
|
|
||||||
{
|
|
||||||
|
|
||||||
Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle =
|
|
||||||
|
private ECPoint g1,g2,h1,h2;
|
||||||
|
private ECPoint g1Tag,g2Tag,h1Tag,h2Tag;
|
||||||
|
private ECPoint u,v,uTag,vTag;
|
||||||
|
private BigInteger c1,c2,z,zTag;
|
||||||
|
private Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle;
|
||||||
|
|
||||||
|
private void parseOrProof(Mixing.ZeroKnowledgeProof.OrProof orProof){
|
||||||
|
forRandomOracle =
|
||||||
Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle.newBuilder()
|
Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle.newBuilder()
|
||||||
.setG1(orProof.getG1())
|
.setG1(orProof.getG1())
|
||||||
.setH1(orProof.getH1())
|
.setH1(orProof.getH1())
|
||||||
|
@ -117,9 +120,6 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier {
|
||||||
.setUTag(orProof.getUTag())
|
.setUTag(orProof.getUTag())
|
||||||
.setVTag(orProof.getVTag())
|
.setVTag(orProof.getVTag())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
ECPoint g1,g2,h1,h2;
|
|
||||||
ECPoint g1Tag,g2Tag,h1Tag,h2Tag;
|
|
||||||
g1 = convert2ECPoint(orProof.getG1());
|
g1 = convert2ECPoint(orProof.getG1());
|
||||||
g2 = convert2ECPoint(orProof.getG2());
|
g2 = convert2ECPoint(orProof.getG2());
|
||||||
h1 = convert2ECPoint(orProof.getH1());
|
h1 = convert2ECPoint(orProof.getH1());
|
||||||
|
@ -128,97 +128,83 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier {
|
||||||
g2Tag = convert2ECPoint(orProof.getG2Tag());
|
g2Tag = convert2ECPoint(orProof.getG2Tag());
|
||||||
h1Tag = convert2ECPoint(orProof.getH1Tag());
|
h1Tag = convert2ECPoint(orProof.getH1Tag());
|
||||||
h2Tag = convert2ECPoint(orProof.getH2Tag());
|
h2Tag = convert2ECPoint(orProof.getH2Tag());
|
||||||
|
|
||||||
ECPoint u,v,uTag,vTag;
|
|
||||||
u = convert2ECPoint(orProof.getU());
|
u = convert2ECPoint(orProof.getU());
|
||||||
v = convert2ECPoint(orProof.getV());
|
v = convert2ECPoint(orProof.getV());
|
||||||
uTag = convert2ECPoint(orProof.getUTag());
|
uTag = convert2ECPoint(orProof.getUTag());
|
||||||
vTag = convert2ECPoint(orProof.getVTag());
|
vTag = convert2ECPoint(orProof.getVTag());
|
||||||
|
|
||||||
BigInteger c1,c2,z,zTag;
|
|
||||||
c1 = new BigInteger(orProof.getC1().toByteArray());
|
c1 = new BigInteger(orProof.getC1().toByteArray());
|
||||||
c2 = new BigInteger(orProof.getC2().toByteArray());
|
c2 = new BigInteger(orProof.getC2().toByteArray());
|
||||||
z = new BigInteger(orProof.getZ().toByteArray());
|
z = new BigInteger(orProof.getZ().toByteArray());
|
||||||
zTag = new BigInteger(orProof.getZTag().toByteArray());
|
zTag = new BigInteger(orProof.getZTag().toByteArray());
|
||||||
|
}
|
||||||
|
|
||||||
ECPoint[] given = new ECPoint[12];
|
private List<Condition> createConditionsList(ElGamalCiphertext e1,
|
||||||
ECPoint[] expected = new ECPoint[12];
|
ElGamalCiphertext e2,
|
||||||
String[] description = new String[12];
|
ElGamalCiphertext e1New,
|
||||||
int i = 0;
|
ElGamalCiphertext e2New){
|
||||||
given[i++] = g1;
|
List<Condition> conditions = new ArrayList<Condition>();
|
||||||
given[i++] = h1;
|
conditions.add(new Condition<ECPoint>( g1,g,"g1 != g"));
|
||||||
given[i++] = g2;
|
conditions.add(new Condition<ECPoint>( h1,group.add(convert2ECPoint(e1New.getC1()),
|
||||||
given[i++] = h2;
|
group.negate(convert2ECPoint(e1.getC1()))),"h1 != e1New.c1/e1.c1"));
|
||||||
given[i++] = g1Tag;
|
conditions.add(new Condition<ECPoint>( g2,h,"g2 != h"));
|
||||||
given[i++] = h1Tag;
|
conditions.add(new Condition<ECPoint>( h2,group.add(convert2ECPoint(e1New.getC2()),
|
||||||
given[i++] = g2Tag;
|
group.negate(convert2ECPoint(e1.getC2()))),"h2 != e1New.c2/e1.c2"));
|
||||||
given[i++] = h2Tag;
|
conditions.add(new Condition<ECPoint>( g1Tag,g,"g1Tag != g"));
|
||||||
given[i++] = group.multiply(g1, z);
|
conditions.add(new Condition<ECPoint>( h1Tag,group.add(convert2ECPoint(e2New.getC1()),
|
||||||
given[i++] = group.multiply(g2, z);
|
group.negate(convert2ECPoint(e2.getC1()))),"h1Tag != e2New.c1/e2.c1"));
|
||||||
given[i++] = group.multiply(g1Tag, zTag);
|
conditions.add(new Condition<ECPoint>( g2Tag,h,"g2Tag != h"));
|
||||||
given[i] = group.multiply(g2Tag, zTag);
|
conditions.add(new Condition<ECPoint>( h2Tag,group.add(convert2ECPoint(e2New.getC2()),
|
||||||
i = 0;
|
group.negate(convert2ECPoint(e2.getC2()))),"h2Tag != e2New.c2/e2.c2"));
|
||||||
expected[i++] = g;
|
conditions.add(new Condition<BigInteger>(c1.add(c2).mod(group.orderUpperBound()),
|
||||||
expected[i++] = group.add(convert2ECPoint(e1New.getC1()), group.negate(convert2ECPoint(e1.getC1())));
|
hash(forRandomOracle).mod(group.orderUpperBound()).mod(group.orderUpperBound()),
|
||||||
expected[i++] = h;
|
"(c1 + c2 ) % group size == hash (imput + step1) % group size"));
|
||||||
expected[i++] = group.add(convert2ECPoint(e1New.getC2()), group.negate(convert2ECPoint(e1.getC2())));
|
conditions.add(new Condition<ECPoint>( group.multiply(g1, z),
|
||||||
expected[i++] = g;
|
group.add(u, group.multiply(h1,c1)),"g1 ^ z != u * ( h1 ^ c1 )"));
|
||||||
expected[i++] = group.add(convert2ECPoint(e2New.getC1()), group.negate(convert2ECPoint(e2.getC1())));
|
conditions.add(new Condition<ECPoint>( group.multiply(g2, z),
|
||||||
expected[i++] = h;
|
group.add(v, group.multiply(h2,c1)),"g2 ^ z != v * ( h2 ^ c1 )"));
|
||||||
expected[i++] = group.add(convert2ECPoint(e2New.getC2()), group.negate(convert2ECPoint(e2.getC2())));
|
conditions.add(new Condition<ECPoint>( group.multiply(g1Tag, zTag),
|
||||||
expected[i++] = group.add(u, group.multiply(h1,c1));
|
group.add(uTag, group.multiply(h1Tag,c2)),"g1Tag ^ zTag != uTag * ( h1Tag ^ c2 )"));
|
||||||
expected[i++] = group.add(v, group.multiply(h2,c1));
|
conditions.add(new Condition<ECPoint>( group.multiply(g2Tag, zTag),
|
||||||
expected[i++] = group.add(uTag, group.multiply(h1Tag,c2));
|
group.add(vTag, group.multiply(h2Tag,c2)),"g2Tag ^ zTag != vTag * ( h2Tag ^ c2 )"));
|
||||||
expected[i] = group.add(vTag, group.multiply(h2Tag,c2));
|
return conditions;
|
||||||
i = 0;
|
}
|
||||||
description[i++] = "g1 != g";
|
|
||||||
description[i++] = "h1 != e1New.c1/e1.c1";
|
public boolean verifyElGamaOrProof(ElGamalCiphertext e1,
|
||||||
description[i++] = "g2 != h";
|
ElGamalCiphertext e2,
|
||||||
description[i++] = "h2 != e1New.c2/e1.c2";
|
ElGamalCiphertext e1New,
|
||||||
description[i++] = "g1Tag != g";
|
ElGamalCiphertext e2New,
|
||||||
description[i++] = "h1Tag != e2New.c1/e2.c1";
|
Mixing.ZeroKnowledgeProof.OrProof orProof, ProofOrganizer.OrProofOrder orProofOrder)
|
||||||
description[i++] = "g2Tag != h";
|
{
|
||||||
description[i++] = "h2Tag != e2New.c2/e2.c2";
|
parseOrProof(orProof);
|
||||||
description[i++] = "g1 ^ z != u * ( h1 ^ c1 )";
|
List<Condition> conditions = createConditionsList(e1,e2,e1New,e2New);
|
||||||
description[i++] = "g2 ^ z != v * ( h2 ^ c1 )";
|
|
||||||
description[i++] = "g1Tag ^ zTag != uTag * ( h1Tag ^ c2 )";
|
boolean result = true;
|
||||||
description[i] = "g2Tag ^ zTag != vTag * ( h2Tag ^ c2 )";
|
for (Condition condition: conditions) {
|
||||||
boolean first = true;
|
if(!condition.test()){
|
||||||
for (int j = 0; j < given.length ; j++){
|
if (result){
|
||||||
if(!given[j].equals(expected[j])){
|
result = false;
|
||||||
if (first){
|
|
||||||
first = false;
|
|
||||||
System.out.print("\n\n\n");
|
System.out.print("\n\n\n");
|
||||||
System.out.println(orProofOrder.toString());
|
System.out.println(orProofOrder.toString());
|
||||||
}
|
}
|
||||||
System.out.println(description[j]);
|
System.out.println(condition.errorDescripton);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return //input
|
private class Condition<T>{
|
||||||
g1.equals(g)&&
|
|
||||||
h1.equals(group.add(convert2ECPoint(e1New.getC1())
|
|
||||||
, group.negate(convert2ECPoint(e1.getC1()))))&&
|
|
||||||
g2.equals(h)&&
|
|
||||||
h2.equals(group.add(convert2ECPoint(e1New.getC2())
|
|
||||||
, group.negate(convert2ECPoint(e1.getC2()))))&&
|
|
||||||
// input'
|
|
||||||
g1Tag.equals(g)&&
|
|
||||||
h1Tag.equals(group.add(convert2ECPoint(e2New.getC1())
|
|
||||||
, group.negate(convert2ECPoint(e2.getC1()))))&&
|
|
||||||
g2Tag.equals(h)&&
|
|
||||||
h2Tag.equals(group.add(convert2ECPoint(e2New.getC2())
|
|
||||||
, group.negate(convert2ECPoint(e2.getC2())))) &&
|
|
||||||
// hash
|
|
||||||
// assert (c1 + c2 ) % group size == hash (imput + step1) % group size
|
|
||||||
new BigInteger(orProof.getC1().toByteArray()).add(new BigInteger(orProof.getC2().toByteArray())).mod(group.orderUpperBound())
|
|
||||||
.equals(hash(forRandomOracle).mod(group.orderUpperBound()).mod(group.orderUpperBound()))&&
|
|
||||||
// proof
|
|
||||||
// g1 ^ z == u * ( h1 ^ c1 ) && g2 ^ z == v * ( h2 ^ c1 ) && the same for tag case
|
|
||||||
group.multiply(g1, z).equals(group.add(u, group.multiply(h1,c1))) &&
|
|
||||||
group.multiply(g2, z).equals(group.add(v, group.multiply(h2,c1))) &&
|
|
||||||
group.multiply(g1Tag, zTag).equals(group.add(uTag, group.multiply(h1Tag,c2))) &&
|
|
||||||
group.multiply(g2Tag, zTag).equals(group.add(vTag, group.multiply(h2Tag,c2)));
|
|
||||||
|
|
||||||
|
T given, expected;
|
||||||
|
String errorDescripton;
|
||||||
|
|
||||||
|
Condition(T given,T expected,String descripton){
|
||||||
|
this.given = given;
|
||||||
|
this.errorDescripton = descripton;
|
||||||
|
this.expected = expected;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean test(){
|
||||||
|
return given.equals(expected);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ package mixer;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
@ -16,7 +15,6 @@ public class MixNetworkTest {
|
||||||
|
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
int logn = 10;
|
int logn = 10;
|
||||||
|
|
||||||
int n = 1 << logn;
|
int n = 1 << logn;
|
||||||
int layers = 2*logn - 1;
|
int layers = 2*logn - 1;
|
||||||
RandomPermutation randomPermutation = new RandomPermutation(n,random);
|
RandomPermutation randomPermutation = new RandomPermutation(n,random);
|
||||||
|
|
|
@ -3,33 +3,24 @@ package mixer;
|
||||||
/**
|
/**
|
||||||
* Created by Tzlil on 12/30/2015.
|
* Created by Tzlil on 12/30/2015.
|
||||||
*/
|
*/
|
||||||
import com.google.protobuf.ByteString;
|
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
import com.google.protobuf.Message;
|
|
||||||
import meerkat.crypto.concrete.ECElGamalEncryption;
|
import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||||
import meerkat.crypto.concrete.GlobalCryptoSetup;
|
|
||||||
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver;
|
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver;
|
||||||
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier;
|
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier;
|
||||||
import meerkat.protobuf.ConcreteCrypto;
|
|
||||||
import meerkat.protobuf.Crypto;
|
import meerkat.protobuf.Crypto;
|
||||||
import meerkat.protobuf.Mixing;
|
import meerkat.protobuf.Mixing;
|
||||||
import org.bouncycastle.jce.spec.ECParameterSpec;
|
import meerkat.protobuf.Voting;
|
||||||
import org.bouncycastle.jce.spec.ECPublicKeySpec;
|
import org.junit.Before;
|
||||||
import org.bouncycastle.math.ec.ECPoint;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import prover.Prover;
|
import prover.Prover;
|
||||||
import qilin.primitives.RandomOracle;
|
import qilin.primitives.RandomOracle;
|
||||||
import qilin.primitives.concrete.DigestOracle;
|
import qilin.primitives.concrete.DigestOracle;
|
||||||
import qilin.primitives.concrete.ECElGamal;
|
import qilin.primitives.concrete.ECElGamal;
|
||||||
import qilin.primitives.concrete.ECGroup;
|
import qilin.primitives.concrete.ECGroup;
|
||||||
import qilin.primitives.generic.ElGamal;
|
|
||||||
import qilin.util.Pair;
|
import qilin.util.Pair;
|
||||||
import verifier.Verifier;
|
import verifier.Verifier;
|
||||||
import verifier.VerifyTable;
|
import verifier.VerifyTable;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.security.KeyFactory;
|
|
||||||
import java.security.PublicKey;
|
|
||||||
import java.security.spec.InvalidKeySpecException;
|
import java.security.spec.InvalidKeySpecException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -39,74 +30,48 @@ public class MixingText {
|
||||||
|
|
||||||
ECElGamalEncryption encryptor;
|
ECElGamalEncryption encryptor;
|
||||||
ECGroup group;
|
ECGroup group;
|
||||||
Random random ;
|
Random random,randomMixer,randomProver;
|
||||||
private BigInteger sk;
|
RandomOracle randomOracle;
|
||||||
private ECElGamal.SK key;
|
Mix2ZeroKnowledgeVerifier verifier;
|
||||||
private ConcreteCrypto.ElGamalPublicKey serializedPk;
|
Mix2ZeroKnowledgeProver prover;
|
||||||
|
meerkat.crypto.mixnet.Mixer mixer;
|
||||||
|
private int layers;
|
||||||
|
private int n;
|
||||||
|
|
||||||
public final static String ENCRYPTION_KEY_ALGORITHM = "ECDH";
|
|
||||||
/**
|
|
||||||
* Serialize an El-Gamal public key into a form acceptable by {@link ECElGamalEncryption}
|
|
||||||
* @param pk
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static ConcreteCrypto.ElGamalPublicKey serializePk(ECGroup group, ElGamal.PK<ECPoint> pk) {
|
|
||||||
ECPoint pkPoint = pk.getPK();
|
|
||||||
ECParameterSpec params = group.getCurveParams();
|
|
||||||
|
|
||||||
ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(pkPoint, params);
|
@Before
|
||||||
|
public void setup() throws InvalidKeySpecException {
|
||||||
try {
|
|
||||||
KeyFactory fact = KeyFactory.getInstance(ENCRYPTION_KEY_ALGORITHM,
|
|
||||||
GlobalCryptoSetup.getBouncyCastleProvider());
|
|
||||||
PublicKey javaPk = fact.generatePublic(pubKeySpec);
|
|
||||||
ConcreteCrypto.ElGamalPublicKey serializedPk = ConcreteCrypto.ElGamalPublicKey.newBuilder()
|
|
||||||
.setSubjectPublicKeyInfo(ByteString.copyFrom(javaPk.getEncoded())).build();
|
|
||||||
|
|
||||||
return serializedPk;
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("Error converting public key!", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void mixingTest() throws InvalidProtocolBufferException, InvalidKeySpecException {
|
|
||||||
// initialization
|
// initialization
|
||||||
random = new Random();
|
random = new Random();
|
||||||
group = new ECGroup("secp256k1");
|
group = new ECGroup("secp256k1");
|
||||||
sk = ECElGamal.generateSecretKey(group, random);
|
|
||||||
key = new ECElGamal.SK(group, sk);
|
|
||||||
serializedPk = serializePk(group, key);
|
|
||||||
encryptor = new ECElGamalEncryption();
|
encryptor = new ECElGamalEncryption();
|
||||||
encryptor.init(serializedPk);
|
encryptor.init(Utiles.serializePk(group, new ECElGamal.SK(group, ECElGamal.generateSecretKey(group, random))));
|
||||||
|
randomMixer = new Random();
|
||||||
|
randomProver = new Random();
|
||||||
Random randomMixer = new Random();
|
randomOracle = new DigestOracle();
|
||||||
Random randomProver = new Random();
|
verifier = new Verifier(encryptor,randomOracle);
|
||||||
RandomOracle randomOracle = new DigestOracle();
|
prover = new Prover(randomProver,encryptor,randomOracle,verifier);
|
||||||
|
mixer = new Mixer(randomMixer,prover,encryptor);
|
||||||
Mix2ZeroKnowledgeVerifier verifier = new Verifier(encryptor,randomOracle);
|
|
||||||
Mix2ZeroKnowledgeProver prover = new Prover(randomProver,encryptor,randomOracle,verifier);
|
|
||||||
meerkat.crypto.mixnet.Mixer mixer = new Mixer(randomMixer,prover,encryptor);
|
|
||||||
ECGroup group = encryptor.getGroup();
|
|
||||||
|
|
||||||
|
|
||||||
// generate n
|
// generate n
|
||||||
int logN = 7; // + random.nextInt(8)
|
int logN = 8; // + random.nextInt(8)
|
||||||
int layers = 2*logN - 1;
|
layers = 2*logN - 1;
|
||||||
int n = 1 << logN;
|
n = 1 << logN;
|
||||||
|
|
||||||
// generate MixerInput
|
|
||||||
List<Crypto.RerandomizableEncryptedMessage> mixerInput = new ArrayList<Crypto.RerandomizableEncryptedMessage>();
|
|
||||||
Message message;
|
|
||||||
for (int i = 0; i < n ; i++){
|
|
||||||
message = Mixing.Plaintext.newBuilder()
|
|
||||||
.setData(ByteString.copyFrom(group.encode(group.sample(random))))
|
|
||||||
.build();
|
|
||||||
mixerInput.add(encryptor.encrypt(message, encryptor.generateRandomness(random)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Pair<Mixing.ZeroKnowledgeProof[][], Crypto.RerandomizableEncryptedMessage[][]> mixerOutput = mixer.mix(mixerInput);
|
public List<Crypto.RerandomizableEncryptedMessage> generateMixerInput(){
|
||||||
|
List<Crypto.RerandomizableEncryptedMessage> result = new ArrayList<Crypto.RerandomizableEncryptedMessage>();
|
||||||
|
Voting.PlaintextBallot msg;
|
||||||
|
for (int i = 0; i < n ; i++){
|
||||||
|
msg = Utiles.genRandomBallot(2,3,16);
|
||||||
|
result.add(encryptor.encrypt(msg, encryptor.generateRandomness(random)));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// assert (VerifyTable.verifyTable(verifier,n,mixerOutput));
|
@Test
|
||||||
|
public void mixingTest() throws InvalidProtocolBufferException {
|
||||||
|
Pair<Mixing.ZeroKnowledgeProof[][], Crypto.RerandomizableEncryptedMessage[][]> mixerOutput = mixer.mix(generateMixerInput());
|
||||||
|
assert (VerifyTable.verifyTable(verifier,n,mixerOutput));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
package mixer;
|
||||||
|
|
||||||
|
import com.google.protobuf.ByteString;
|
||||||
|
import com.google.protobuf.GeneratedMessage;
|
||||||
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
|
import com.google.protobuf.Message;
|
||||||
|
import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||||
|
import meerkat.crypto.concrete.GlobalCryptoSetup;
|
||||||
|
import meerkat.protobuf.ConcreteCrypto;
|
||||||
|
import meerkat.protobuf.Crypto;
|
||||||
|
import meerkat.protobuf.Voting;
|
||||||
|
import org.bouncycastle.jce.spec.ECParameterSpec;
|
||||||
|
import org.bouncycastle.jce.spec.ECPublicKeySpec;
|
||||||
|
import org.bouncycastle.math.ec.ECPoint;
|
||||||
|
import qilin.primitives.concrete.ECElGamal;
|
||||||
|
import qilin.primitives.concrete.ECGroup;
|
||||||
|
import qilin.primitives.generic.ElGamal;
|
||||||
|
import qilin.util.Pair;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Tzlil on 1/1/2016.
|
||||||
|
*/
|
||||||
|
public class Utiles {
|
||||||
|
|
||||||
|
|
||||||
|
public final static String ENCRYPTION_KEY_ALGORITHM = "ECDH";
|
||||||
|
/**
|
||||||
|
* Serialize an El-Gamal public key into a form acceptable by {@link ECElGamalEncryption}
|
||||||
|
* @param pk
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ConcreteCrypto.ElGamalPublicKey serializePk(ECGroup group, ElGamal.PK<ECPoint> pk) {
|
||||||
|
ECPoint pkPoint = pk.getPK();
|
||||||
|
ECParameterSpec params = group.getCurveParams();
|
||||||
|
|
||||||
|
ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(pkPoint, params);
|
||||||
|
|
||||||
|
try {
|
||||||
|
KeyFactory fact = KeyFactory.getInstance(ENCRYPTION_KEY_ALGORITHM,
|
||||||
|
GlobalCryptoSetup.getBouncyCastleProvider());
|
||||||
|
PublicKey javaPk = fact.generatePublic(pubKeySpec);
|
||||||
|
ConcreteCrypto.ElGamalPublicKey serializedPk = ConcreteCrypto.ElGamalPublicKey.newBuilder()
|
||||||
|
.setSubjectPublicKeyInfo(ByteString.copyFrom(javaPk.getEncoded())).build();
|
||||||
|
|
||||||
|
return serializedPk;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Error converting public key!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Standard (non-threshold) decryption for testing purposes.
|
||||||
|
* @param secretKey
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static <T extends Message> T decrypt(Class<T> plaintextMessageType, ECElGamal.SK secretKey, ECGroup group, Crypto.RerandomizableEncryptedMessage opaqueCipher)
|
||||||
|
throws InvalidProtocolBufferException {
|
||||||
|
ConcreteCrypto.ElGamalCiphertext cipherText = ConcreteCrypto.ElGamalCiphertext.parseFrom(opaqueCipher.getData());
|
||||||
|
ByteString c1encoded = cipherText.getC1();
|
||||||
|
ByteString c2encoded = cipherText.getC2();
|
||||||
|
|
||||||
|
ECPoint c1 = group.decode(c1encoded.toByteArray());
|
||||||
|
ECPoint c2 = group.decode(c2encoded.toByteArray());
|
||||||
|
|
||||||
|
assert (group.contains(c1));
|
||||||
|
assert (group.contains(c2));
|
||||||
|
|
||||||
|
ECPoint plaintextEncoded = secretKey.decrypt(new Pair<ECPoint, ECPoint>(c1, c2));
|
||||||
|
|
||||||
|
byte[] plaintext = group.injectiveDecode(plaintextEncoded);
|
||||||
|
|
||||||
|
ByteArrayInputStream in = new ByteArrayInputStream(plaintext);
|
||||||
|
|
||||||
|
try {
|
||||||
|
java.lang.reflect.Method newBuilder = plaintextMessageType.getMethod("newBuilder");
|
||||||
|
GeneratedMessage.Builder builder = (GeneratedMessage.Builder) newBuilder.invoke(plaintextMessageType);
|
||||||
|
builder.mergeDelimitedFrom(in);
|
||||||
|
return plaintextMessageType.cast(builder.build());
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new InvalidProtocolBufferException("Plaintext protobuf error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Random random = new Random();
|
||||||
|
|
||||||
|
public static Voting.PlaintextBallot genRandomBallot(int numQuestions, int numAnswers, int maxAnswer) {
|
||||||
|
Voting.PlaintextBallot.Builder ballot = Voting.PlaintextBallot.newBuilder();
|
||||||
|
ballot.setSerialNumber(random.nextInt(1000000));
|
||||||
|
for (int i = 0; i < numQuestions; ++i) {
|
||||||
|
Voting.BallotAnswer.Builder answers = ballot.addAnswersBuilder();
|
||||||
|
for (int j = 0; j < numAnswers; ++j) {
|
||||||
|
answers.addAnswer(random.nextInt(maxAnswer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ballot.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,20 +1,12 @@
|
||||||
package mixer;
|
package mixer;
|
||||||
|
|
||||||
import com.google.protobuf.ByteString;
|
|
||||||
import com.google.protobuf.GeneratedMessage;
|
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
import com.google.protobuf.Message;
|
|
||||||
import meerkat.crypto.concrete.ECElGamalEncryption;
|
import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||||
import meerkat.crypto.concrete.GlobalCryptoSetup;
|
|
||||||
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver;
|
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver;
|
||||||
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier;
|
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier;
|
||||||
import meerkat.protobuf.ConcreteCrypto;
|
import meerkat.protobuf.ConcreteCrypto;
|
||||||
import meerkat.protobuf.Crypto;
|
import meerkat.protobuf.Crypto;
|
||||||
import meerkat.protobuf.Mixing;
|
|
||||||
import meerkat.protobuf.Voting;
|
import meerkat.protobuf.Voting;
|
||||||
import org.bouncycastle.jce.spec.ECParameterSpec;
|
|
||||||
import org.bouncycastle.jce.spec.ECPublicKeySpec;
|
|
||||||
import org.bouncycastle.math.ec.ECPoint;
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import prover.Prover;
|
import prover.Prover;
|
||||||
|
@ -22,87 +14,16 @@ import qilin.primitives.RandomOracle;
|
||||||
import qilin.primitives.concrete.DigestOracle;
|
import qilin.primitives.concrete.DigestOracle;
|
||||||
import qilin.primitives.concrete.ECElGamal;
|
import qilin.primitives.concrete.ECElGamal;
|
||||||
import qilin.primitives.concrete.ECGroup;
|
import qilin.primitives.concrete.ECGroup;
|
||||||
import qilin.primitives.generic.ElGamal;
|
|
||||||
import qilin.util.Pair;
|
|
||||||
import verifier.Verifier;
|
import verifier.Verifier;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.security.KeyFactory;
|
|
||||||
import java.security.PublicKey;
|
|
||||||
import java.security.spec.InvalidKeySpecException;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Tzlil on 12/31/2015.
|
* Created by Tzlil on 12/31/2015.
|
||||||
*/
|
*/
|
||||||
public class ZeroKnowledgeProofTest {
|
public class ZeroKnowledgeProofTest {
|
||||||
|
|
||||||
|
Random rand;
|
||||||
public final static String ENCRYPTION_KEY_ALGORITHM = "ECDH";
|
|
||||||
/**
|
|
||||||
* Serialize an El-Gamal public key into a form acceptable by {@link ECElGamalEncryption}
|
|
||||||
* @param pk
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static ConcreteCrypto.ElGamalPublicKey serializePk(ECGroup group, ElGamal.PK<ECPoint> pk) {
|
|
||||||
ECPoint pkPoint = pk.getPK();
|
|
||||||
ECParameterSpec params = group.getCurveParams();
|
|
||||||
|
|
||||||
ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(pkPoint, params);
|
|
||||||
|
|
||||||
try {
|
|
||||||
KeyFactory fact = KeyFactory.getInstance(ENCRYPTION_KEY_ALGORITHM,
|
|
||||||
GlobalCryptoSetup.getBouncyCastleProvider());
|
|
||||||
PublicKey javaPk = fact.generatePublic(pubKeySpec);
|
|
||||||
ConcreteCrypto.ElGamalPublicKey serializedPk = ConcreteCrypto.ElGamalPublicKey.newBuilder()
|
|
||||||
.setSubjectPublicKeyInfo(ByteString.copyFrom(javaPk.getEncoded())).build();
|
|
||||||
|
|
||||||
return serializedPk;
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("Error converting public key!", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Standard (non-threshold) decryption for testing purposes.
|
|
||||||
* @param secretKey
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static <T extends Message> T decrypt(Class<T> plaintextMessageType, ECElGamal.SK secretKey, ECGroup group, Crypto.RerandomizableEncryptedMessage opaqueCipher)
|
|
||||||
throws InvalidProtocolBufferException {
|
|
||||||
ConcreteCrypto.ElGamalCiphertext cipherText = ConcreteCrypto.ElGamalCiphertext.parseFrom(opaqueCipher.getData());
|
|
||||||
ByteString c1encoded = cipherText.getC1();
|
|
||||||
ByteString c2encoded = cipherText.getC2();
|
|
||||||
|
|
||||||
ECPoint c1 = group.decode(c1encoded.toByteArray());
|
|
||||||
ECPoint c2 = group.decode(c2encoded.toByteArray());
|
|
||||||
|
|
||||||
assert (group.contains(c1));
|
|
||||||
assert (group.contains(c2));
|
|
||||||
|
|
||||||
ECPoint plaintextEncoded = secretKey.decrypt(new Pair<ECPoint, ECPoint>(c1, c2));
|
|
||||||
|
|
||||||
byte[] plaintext = group.injectiveDecode(plaintextEncoded);
|
|
||||||
|
|
||||||
ByteArrayInputStream in = new ByteArrayInputStream(plaintext);
|
|
||||||
|
|
||||||
try {
|
|
||||||
java.lang.reflect.Method newBuilder = plaintextMessageType.getMethod("newBuilder");
|
|
||||||
GeneratedMessage.Builder builder = (GeneratedMessage.Builder) newBuilder.invoke(plaintextMessageType);
|
|
||||||
builder.mergeDelimitedFrom(in);
|
|
||||||
return plaintextMessageType.cast(builder.build());
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new InvalidProtocolBufferException("Plaintext protobuf error");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Random rand = new Random(0); // Insecure deterministic random for testing.
|
|
||||||
|
|
||||||
ECElGamal.SK key;
|
ECElGamal.SK key;
|
||||||
ECGroup group;
|
ECGroup group;
|
||||||
ECElGamalEncryption enc;
|
ECElGamalEncryption enc;
|
||||||
|
@ -112,14 +33,12 @@ public class ZeroKnowledgeProofTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() throws Exception {
|
public void setup() throws Exception {
|
||||||
|
rand = new Random();
|
||||||
group = new ECGroup("secp256k1");
|
group = new ECGroup("secp256k1");
|
||||||
BigInteger sk = ECElGamal.generateSecretKey(group, rand);
|
BigInteger sk = ECElGamal.generateSecretKey(group, rand);
|
||||||
key = new ECElGamal.SK(group, sk);
|
key = new ECElGamal.SK(group, sk);
|
||||||
serializedPk = serializePk(group, key);
|
serializedPk = Utiles.serializePk(group, key);
|
||||||
|
|
||||||
|
|
||||||
enc = new ECElGamalEncryption();
|
enc = new ECElGamalEncryption();
|
||||||
|
|
||||||
enc.init(serializedPk);
|
enc.init(serializedPk);
|
||||||
RandomOracle randomOracle = new DigestOracle();
|
RandomOracle randomOracle = new DigestOracle();
|
||||||
verifier = new Verifier(enc,randomOracle);
|
verifier = new Verifier(enc,randomOracle);
|
||||||
|
@ -127,23 +46,13 @@ public class ZeroKnowledgeProofTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Voting.PlaintextBallot genRandomBallot(int numQuestions, int numAnswers, int maxAnswer) {
|
|
||||||
Voting.PlaintextBallot.Builder ballot = Voting.PlaintextBallot.newBuilder();
|
|
||||||
ballot.setSerialNumber(rand.nextInt(1000000));
|
|
||||||
for (int i = 0; i < numQuestions; ++i) {
|
|
||||||
Voting.BallotAnswer.Builder answers = ballot.addAnswersBuilder();
|
|
||||||
for (int j = 0; j < numAnswers; ++j) {
|
|
||||||
answers.addAnswer(rand.nextInt(maxAnswer));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ballot.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void oneZKPTest() throws InvalidProtocolBufferException {
|
public void oneZKPTest() throws InvalidProtocolBufferException {
|
||||||
|
|
||||||
Voting.PlaintextBallot msg1 = genRandomBallot(2,3,16); // 2 questions with 3 answers each, in range 0-15.
|
Voting.PlaintextBallot msg1 = Utiles.genRandomBallot(2,3,16); // 2 questions with 3 answers each, in range 0-15.
|
||||||
Voting.PlaintextBallot msg2 = genRandomBallot(2,3,16);
|
Voting.PlaintextBallot msg2 = Utiles.genRandomBallot(2,3,16);
|
||||||
Crypto.EncryptionRandomness r1 = enc.generateRandomness(rand);
|
Crypto.EncryptionRandomness r1 = enc.generateRandomness(rand);
|
||||||
Crypto.EncryptionRandomness r2 = enc.generateRandomness(rand);
|
Crypto.EncryptionRandomness r2 = enc.generateRandomness(rand);
|
||||||
|
|
||||||
|
@ -151,10 +60,10 @@ public class ZeroKnowledgeProofTest {
|
||||||
Crypto.RerandomizableEncryptedMessage e2 = enc.encrypt(msg2, enc.generateRandomness(rand));
|
Crypto.RerandomizableEncryptedMessage e2 = enc.encrypt(msg2, enc.generateRandomness(rand));
|
||||||
Crypto.RerandomizableEncryptedMessage e1Tag = enc.rerandomize(e1, r1);
|
Crypto.RerandomizableEncryptedMessage e1Tag = enc.rerandomize(e1, r1);
|
||||||
Crypto.RerandomizableEncryptedMessage e2Tag = enc.rerandomize(e2, r2);
|
Crypto.RerandomizableEncryptedMessage e2Tag = enc.rerandomize(e2, r2);
|
||||||
assert (decrypt(Voting.PlaintextBallot.class, key, group, e1).equals(msg1));
|
assert (Utiles.decrypt(Voting.PlaintextBallot.class, key, group, e1).equals(msg1));
|
||||||
assert (decrypt(Voting.PlaintextBallot.class, key, group, e1Tag).equals(msg1));
|
assert (Utiles.decrypt(Voting.PlaintextBallot.class, key, group, e1Tag).equals(msg1));
|
||||||
assert (decrypt(Voting.PlaintextBallot.class, key, group, e2).equals(msg2));
|
assert (Utiles.decrypt(Voting.PlaintextBallot.class, key, group, e2).equals(msg2));
|
||||||
assert (decrypt(Voting.PlaintextBallot.class, key, group, e2Tag).equals(msg2));
|
assert (Utiles.decrypt(Voting.PlaintextBallot.class, key, group, e2Tag).equals(msg2));
|
||||||
assert (verifier.verify(e1,e2,e1Tag,e2Tag,prover.prove(e1,e2,e1Tag,e2Tag,false,0,0,0,r1,r2)));
|
assert (verifier.verify(e1,e2,e1Tag,e2Tag,prover.prove(e1,e2,e1Tag,e2Tag,false,0,0,0,r1,r2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue