more tests for mixer
parent
8f75bebaea
commit
8a07f86c0f
|
@ -13,6 +13,7 @@ import qilin.primitives.RandomOracle;
|
|||
import qilin.primitives.concrete.ECGroup;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
|
@ -95,14 +96,16 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier {
|
|||
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()
|
||||
.setG1(orProof.getG1())
|
||||
.setH1(orProof.getH1())
|
||||
|
@ -117,9 +120,6 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier {
|
|||
.setUTag(orProof.getUTag())
|
||||
.setVTag(orProof.getVTag())
|
||||
.build();
|
||||
|
||||
ECPoint g1,g2,h1,h2;
|
||||
ECPoint g1Tag,g2Tag,h1Tag,h2Tag;
|
||||
g1 = convert2ECPoint(orProof.getG1());
|
||||
g2 = convert2ECPoint(orProof.getG2());
|
||||
h1 = convert2ECPoint(orProof.getH1());
|
||||
|
@ -128,97 +128,83 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier {
|
|||
g2Tag = convert2ECPoint(orProof.getG2Tag());
|
||||
h1Tag = convert2ECPoint(orProof.getH1Tag());
|
||||
h2Tag = convert2ECPoint(orProof.getH2Tag());
|
||||
|
||||
ECPoint u,v,uTag,vTag;
|
||||
u = convert2ECPoint(orProof.getU());
|
||||
v = convert2ECPoint(orProof.getV());
|
||||
uTag = convert2ECPoint(orProof.getUTag());
|
||||
vTag = convert2ECPoint(orProof.getVTag());
|
||||
|
||||
BigInteger c1,c2,z,zTag;
|
||||
c1 = new BigInteger(orProof.getC1().toByteArray());
|
||||
c2 = new BigInteger(orProof.getC2().toByteArray());
|
||||
z = new BigInteger(orProof.getZ().toByteArray());
|
||||
zTag = new BigInteger(orProof.getZTag().toByteArray());
|
||||
}
|
||||
|
||||
ECPoint[] given = new ECPoint[12];
|
||||
ECPoint[] expected = new ECPoint[12];
|
||||
String[] description = new String[12];
|
||||
int i = 0;
|
||||
given[i++] = g1;
|
||||
given[i++] = h1;
|
||||
given[i++] = g2;
|
||||
given[i++] = h2;
|
||||
given[i++] = g1Tag;
|
||||
given[i++] = h1Tag;
|
||||
given[i++] = g2Tag;
|
||||
given[i++] = h2Tag;
|
||||
given[i++] = group.multiply(g1, z);
|
||||
given[i++] = group.multiply(g2, z);
|
||||
given[i++] = group.multiply(g1Tag, zTag);
|
||||
given[i] = group.multiply(g2Tag, zTag);
|
||||
i = 0;
|
||||
expected[i++] = g;
|
||||
expected[i++] = group.add(convert2ECPoint(e1New.getC1()), group.negate(convert2ECPoint(e1.getC1())));
|
||||
expected[i++] = h;
|
||||
expected[i++] = group.add(convert2ECPoint(e1New.getC2()), group.negate(convert2ECPoint(e1.getC2())));
|
||||
expected[i++] = g;
|
||||
expected[i++] = group.add(convert2ECPoint(e2New.getC1()), group.negate(convert2ECPoint(e2.getC1())));
|
||||
expected[i++] = h;
|
||||
expected[i++] = group.add(convert2ECPoint(e2New.getC2()), group.negate(convert2ECPoint(e2.getC2())));
|
||||
expected[i++] = group.add(u, group.multiply(h1,c1));
|
||||
expected[i++] = group.add(v, group.multiply(h2,c1));
|
||||
expected[i++] = group.add(uTag, group.multiply(h1Tag,c2));
|
||||
expected[i] = group.add(vTag, group.multiply(h2Tag,c2));
|
||||
i = 0;
|
||||
description[i++] = "g1 != g";
|
||||
description[i++] = "h1 != e1New.c1/e1.c1";
|
||||
description[i++] = "g2 != h";
|
||||
description[i++] = "h2 != e1New.c2/e1.c2";
|
||||
description[i++] = "g1Tag != g";
|
||||
description[i++] = "h1Tag != e2New.c1/e2.c1";
|
||||
description[i++] = "g2Tag != h";
|
||||
description[i++] = "h2Tag != e2New.c2/e2.c2";
|
||||
description[i++] = "g1 ^ z != u * ( h1 ^ c1 )";
|
||||
description[i++] = "g2 ^ z != v * ( h2 ^ c1 )";
|
||||
description[i++] = "g1Tag ^ zTag != uTag * ( h1Tag ^ c2 )";
|
||||
description[i] = "g2Tag ^ zTag != vTag * ( h2Tag ^ c2 )";
|
||||
boolean first = true;
|
||||
for (int j = 0; j < given.length ; j++){
|
||||
if(!given[j].equals(expected[j])){
|
||||
if (first){
|
||||
first = false;
|
||||
private List<Condition> createConditionsList(ElGamalCiphertext e1,
|
||||
ElGamalCiphertext e2,
|
||||
ElGamalCiphertext e1New,
|
||||
ElGamalCiphertext e2New){
|
||||
List<Condition> conditions = new ArrayList<Condition>();
|
||||
conditions.add(new Condition<ECPoint>( g1,g,"g1 != g"));
|
||||
conditions.add(new Condition<ECPoint>( h1,group.add(convert2ECPoint(e1New.getC1()),
|
||||
group.negate(convert2ECPoint(e1.getC1()))),"h1 != e1New.c1/e1.c1"));
|
||||
conditions.add(new Condition<ECPoint>( g2,h,"g2 != h"));
|
||||
conditions.add(new Condition<ECPoint>( h2,group.add(convert2ECPoint(e1New.getC2()),
|
||||
group.negate(convert2ECPoint(e1.getC2()))),"h2 != e1New.c2/e1.c2"));
|
||||
conditions.add(new Condition<ECPoint>( g1Tag,g,"g1Tag != g"));
|
||||
conditions.add(new Condition<ECPoint>( h1Tag,group.add(convert2ECPoint(e2New.getC1()),
|
||||
group.negate(convert2ECPoint(e2.getC1()))),"h1Tag != e2New.c1/e2.c1"));
|
||||
conditions.add(new Condition<ECPoint>( g2Tag,h,"g2Tag != h"));
|
||||
conditions.add(new Condition<ECPoint>( h2Tag,group.add(convert2ECPoint(e2New.getC2()),
|
||||
group.negate(convert2ECPoint(e2.getC2()))),"h2Tag != e2New.c2/e2.c2"));
|
||||
conditions.add(new Condition<BigInteger>(c1.add(c2).mod(group.orderUpperBound()),
|
||||
hash(forRandomOracle).mod(group.orderUpperBound()).mod(group.orderUpperBound()),
|
||||
"(c1 + c2 ) % group size == hash (imput + step1) % group size"));
|
||||
conditions.add(new Condition<ECPoint>( group.multiply(g1, z),
|
||||
group.add(u, group.multiply(h1,c1)),"g1 ^ z != u * ( h1 ^ c1 )"));
|
||||
conditions.add(new Condition<ECPoint>( group.multiply(g2, z),
|
||||
group.add(v, group.multiply(h2,c1)),"g2 ^ z != v * ( h2 ^ c1 )"));
|
||||
conditions.add(new Condition<ECPoint>( group.multiply(g1Tag, zTag),
|
||||
group.add(uTag, group.multiply(h1Tag,c2)),"g1Tag ^ zTag != uTag * ( h1Tag ^ c2 )"));
|
||||
conditions.add(new Condition<ECPoint>( group.multiply(g2Tag, zTag),
|
||||
group.add(vTag, group.multiply(h2Tag,c2)),"g2Tag ^ zTag != vTag * ( h2Tag ^ c2 )"));
|
||||
return conditions;
|
||||
}
|
||||
|
||||
public boolean verifyElGamaOrProof(ElGamalCiphertext e1,
|
||||
ElGamalCiphertext e2,
|
||||
ElGamalCiphertext e1New,
|
||||
ElGamalCiphertext e2New,
|
||||
Mixing.ZeroKnowledgeProof.OrProof orProof, ProofOrganizer.OrProofOrder orProofOrder)
|
||||
{
|
||||
parseOrProof(orProof);
|
||||
List<Condition> conditions = createConditionsList(e1,e2,e1New,e2New);
|
||||
|
||||
boolean result = true;
|
||||
for (Condition condition: conditions) {
|
||||
if(!condition.test()){
|
||||
if (result){
|
||||
result = false;
|
||||
System.out.print("\n\n\n");
|
||||
System.out.println(orProofOrder.toString());
|
||||
}
|
||||
System.out.println(description[j]);
|
||||
System.out.println(condition.errorDescripton);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return //input
|
||||
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)));
|
||||
private class Condition<T>{
|
||||
|
||||
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 java.util.Arrays;
|
||||
import java.util.Random;
|
||||
|
||||
|
@ -16,7 +15,6 @@ public class MixNetworkTest {
|
|||
|
||||
Random random = new Random();
|
||||
int logn = 10;
|
||||
|
||||
int n = 1 << logn;
|
||||
int layers = 2*logn - 1;
|
||||
RandomPermutation randomPermutation = new RandomPermutation(n,random);
|
||||
|
|
|
@ -3,33 +3,24 @@ package mixer;
|
|||
/**
|
||||
* Created by Tzlil on 12/30/2015.
|
||||
*/
|
||||
import com.google.protobuf.ByteString;
|
||||
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import com.google.protobuf.Message;
|
||||
import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||
import meerkat.crypto.concrete.GlobalCryptoSetup;
|
||||
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver;
|
||||
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier;
|
||||
import meerkat.protobuf.ConcreteCrypto;
|
||||
import meerkat.protobuf.Crypto;
|
||||
import meerkat.protobuf.Mixing;
|
||||
import org.bouncycastle.jce.spec.ECParameterSpec;
|
||||
import org.bouncycastle.jce.spec.ECPublicKeySpec;
|
||||
import org.bouncycastle.math.ec.ECPoint;
|
||||
import meerkat.protobuf.Voting;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import prover.Prover;
|
||||
import qilin.primitives.RandomOracle;
|
||||
import qilin.primitives.concrete.DigestOracle;
|
||||
import qilin.primitives.concrete.ECElGamal;
|
||||
import qilin.primitives.concrete.ECGroup;
|
||||
import qilin.primitives.generic.ElGamal;
|
||||
import qilin.util.Pair;
|
||||
import verifier.Verifier;
|
||||
import verifier.VerifyTable;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.PublicKey;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -39,74 +30,48 @@ public class MixingText {
|
|||
|
||||
ECElGamalEncryption encryptor;
|
||||
ECGroup group;
|
||||
Random random ;
|
||||
private BigInteger sk;
|
||||
private ECElGamal.SK key;
|
||||
private ConcreteCrypto.ElGamalPublicKey serializedPk;
|
||||
Random random,randomMixer,randomProver;
|
||||
RandomOracle randomOracle;
|
||||
Mix2ZeroKnowledgeVerifier verifier;
|
||||
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);
|
||||
|
||||
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 {
|
||||
@Before
|
||||
public void setup() throws InvalidKeySpecException {
|
||||
// initialization
|
||||
random = new Random();
|
||||
group = new ECGroup("secp256k1");
|
||||
sk = ECElGamal.generateSecretKey(group, random);
|
||||
key = new ECElGamal.SK(group, sk);
|
||||
serializedPk = serializePk(group, key);
|
||||
encryptor = new ECElGamalEncryption();
|
||||
encryptor.init(serializedPk);
|
||||
|
||||
|
||||
Random randomMixer = new Random();
|
||||
Random randomProver = new Random();
|
||||
RandomOracle randomOracle = new DigestOracle();
|
||||
|
||||
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();
|
||||
|
||||
encryptor.init(Utiles.serializePk(group, new ECElGamal.SK(group, ECElGamal.generateSecretKey(group, random))));
|
||||
randomMixer = new Random();
|
||||
randomProver = new Random();
|
||||
randomOracle = new DigestOracle();
|
||||
verifier = new Verifier(encryptor,randomOracle);
|
||||
prover = new Prover(randomProver,encryptor,randomOracle,verifier);
|
||||
mixer = new Mixer(randomMixer,prover,encryptor);
|
||||
|
||||
// generate n
|
||||
int logN = 7; // + random.nextInt(8)
|
||||
int layers = 2*logN - 1;
|
||||
int n = 1 << logN;
|
||||
int logN = 8; // + random.nextInt(8)
|
||||
layers = 2*logN - 1;
|
||||
n = 1 << logN;
|
||||
}
|
||||
|
||||
// generate MixerInput
|
||||
List<Crypto.RerandomizableEncryptedMessage> mixerInput = new ArrayList<Crypto.RerandomizableEncryptedMessage>();
|
||||
Message message;
|
||||
public List<Crypto.RerandomizableEncryptedMessage> generateMixerInput(){
|
||||
List<Crypto.RerandomizableEncryptedMessage> result = new ArrayList<Crypto.RerandomizableEncryptedMessage>();
|
||||
Voting.PlaintextBallot msg;
|
||||
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)));
|
||||
msg = Utiles.genRandomBallot(2,3,16);
|
||||
result.add(encryptor.encrypt(msg, encryptor.generateRandomness(random)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Pair<Mixing.ZeroKnowledgeProof[][], Crypto.RerandomizableEncryptedMessage[][]> mixerOutput = mixer.mix(mixerInput);
|
||||
|
||||
// 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;
|
||||
|
||||
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.crypto.mixnet.Mix2ZeroKnowledgeProver;
|
||||
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier;
|
||||
import meerkat.protobuf.ConcreteCrypto;
|
||||
import meerkat.protobuf.Crypto;
|
||||
import meerkat.protobuf.Mixing;
|
||||
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.Test;
|
||||
import prover.Prover;
|
||||
|
@ -22,87 +14,16 @@ import qilin.primitives.RandomOracle;
|
|||
import qilin.primitives.concrete.DigestOracle;
|
||||
import qilin.primitives.concrete.ECElGamal;
|
||||
import qilin.primitives.concrete.ECGroup;
|
||||
import qilin.primitives.generic.ElGamal;
|
||||
import qilin.util.Pair;
|
||||
import verifier.Verifier;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
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 static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 12/31/2015.
|
||||
*/
|
||||
public class ZeroKnowledgeProofTest {
|
||||
|
||||
|
||||
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.
|
||||
|
||||
Random rand;
|
||||
ECElGamal.SK key;
|
||||
ECGroup group;
|
||||
ECElGamalEncryption enc;
|
||||
|
@ -112,14 +33,12 @@ public class ZeroKnowledgeProofTest {
|
|||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
rand = new Random();
|
||||
group = new ECGroup("secp256k1");
|
||||
BigInteger sk = ECElGamal.generateSecretKey(group, rand);
|
||||
key = new ECElGamal.SK(group, sk);
|
||||
serializedPk = serializePk(group, key);
|
||||
|
||||
|
||||
serializedPk = Utiles.serializePk(group, key);
|
||||
enc = new ECElGamalEncryption();
|
||||
|
||||
enc.init(serializedPk);
|
||||
RandomOracle randomOracle = new DigestOracle();
|
||||
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 {
|
||||
|
||||
Voting.PlaintextBallot msg1 = genRandomBallot(2,3,16); // 2 questions with 3 answers each, in range 0-15.
|
||||
Voting.PlaintextBallot msg2 = genRandomBallot(2,3,16);
|
||||
Voting.PlaintextBallot msg1 = Utiles.genRandomBallot(2,3,16); // 2 questions with 3 answers each, in range 0-15.
|
||||
Voting.PlaintextBallot msg2 = Utiles.genRandomBallot(2,3,16);
|
||||
Crypto.EncryptionRandomness r1 = 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 e1Tag = enc.rerandomize(e1, r1);
|
||||
Crypto.RerandomizableEncryptedMessage e2Tag = enc.rerandomize(e2, r2);
|
||||
assert (decrypt(Voting.PlaintextBallot.class, key, group, e1).equals(msg1));
|
||||
assert (decrypt(Voting.PlaintextBallot.class, key, group, e1Tag).equals(msg1));
|
||||
assert (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, e1).equals(msg1));
|
||||
assert (Utiles.decrypt(Voting.PlaintextBallot.class, key, group, e1Tag).equals(msg1));
|
||||
assert (Utiles.decrypt(Voting.PlaintextBallot.class, key, group, e2).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)));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue