zkp verification fails from time to time

mixer
tzlil.gon 2015-12-31 18:58:25 +02:00
parent 75c411a5e7
commit 026a879de3
15 changed files with 627 additions and 191 deletions

View File

@ -109,6 +109,15 @@ public class ECElGamalEncryption extends GlobalCryptoSetup implements Encryption
.build(); .build();
} }
public static ConcreteCrypto.ElGamalCiphertext rerandomizableEncryptedMessage2ElGamalCiphertext(Crypto.RerandomizableEncryptedMessage msg) throws InvalidProtocolBufferException {
return ConcreteCrypto.ElGamalCiphertext.parseFrom(msg.getData());
}
public static Crypto.RerandomizableEncryptedMessage elGamalCiphertext2RerandomizableEncryptedMessage(ConcreteCrypto.ElGamalCiphertext msg) {
return Crypto.RerandomizableEncryptedMessage.newBuilder()
.setData(msg.toByteString()).build();
}
@Override @Override
public Crypto.RerandomizableEncryptedMessage rerandomize(Crypto.RerandomizableEncryptedMessage msg, Crypto.EncryptionRandomness rnd) throws InvalidProtocolBufferException { public Crypto.RerandomizableEncryptedMessage rerandomize(Crypto.RerandomizableEncryptedMessage msg, Crypto.EncryptionRandomness rnd) throws InvalidProtocolBufferException {
BigInteger rndInt = BigIntegers.fromUnsignedByteArray(rnd.getData().toByteArray()); BigInteger rndInt = BigIntegers.fromUnsignedByteArray(rnd.getData().toByteArray());

View File

@ -1,5 +1,6 @@
package meerkat.crypto.mixnet; package meerkat.crypto.mixnet;
import com.google.protobuf.InvalidProtocolBufferException;
import meerkat.protobuf.Crypto; import meerkat.protobuf.Crypto;
import meerkat.protobuf.Mixing; import meerkat.protobuf.Mixing;
@ -13,7 +14,7 @@ public interface Mix2ZeroKnowledgeProver {
Crypto.RerandomizableEncryptedMessage out2, Crypto.RerandomizableEncryptedMessage out2,
boolean switched,int i,int j, int layer, // switch info boolean switched,int i,int j, int layer, // switch info
Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r1,
Crypto.EncryptionRandomness r2); Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException;
} }

View File

@ -1,5 +1,6 @@
package meerkat.crypto.mixnet; package meerkat.crypto.mixnet;
import com.google.protobuf.InvalidProtocolBufferException;
import meerkat.protobuf.Crypto; import meerkat.protobuf.Crypto;
import meerkat.protobuf.Mixing; import meerkat.protobuf.Mixing;
@ -19,5 +20,5 @@ public interface Mix2ZeroKnowledgeVerifier {
Crypto.RerandomizableEncryptedMessage in2, Crypto.RerandomizableEncryptedMessage in2,
Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out1,
Crypto.RerandomizableEncryptedMessage out2, Crypto.RerandomizableEncryptedMessage out2,
Mixing.ZeroKnowledgeProof proof); Mixing.ZeroKnowledgeProof proof) throws InvalidProtocolBufferException;
} }

View File

@ -6,6 +6,10 @@ option java_package = "meerkat.protobuf";
import 'meerkat/crypto.proto'; import 'meerkat/crypto.proto';
message Plaintext{
bytes data = 1;
}
message ZeroKnowledgeProof { message ZeroKnowledgeProof {
message OrProof { message OrProof {
message ForRandomOracle{ message ForRandomOracle{

View File

@ -49,7 +49,7 @@ public class ECElGamalUtils {
.setSubjectPublicKeyInfo(ByteString.copyFrom(javaPk.getEncoded())).build(); .setSubjectPublicKeyInfo(ByteString.copyFrom(javaPk.getEncoded())).build();
return serializedPk; return serializedPk;
} catch (NoSuchAlgorithmException|InvalidKeySpecException e) { } catch (Exception e) {
logger.error("Should never happen!", e); logger.error("Should never happen!", e);
throw new RuntimeException("Error converting public key!", e); throw new RuntimeException("Error converting public key!", e);
} }

View File

@ -206,8 +206,7 @@ public class MainMixing {
} }
private boolean verifyTable() private boolean verifyTable() throws InvalidProtocolBufferException {
{
int index1,index2,layer; int index1,index2,layer;
//initialize locationChecksum table //initialize locationChecksum table

View File

@ -2,6 +2,8 @@ package mixer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier;
import qilin.util.Pair; import qilin.util.Pair;
import java.util.Random; import java.util.Random;
@ -12,20 +14,23 @@ import meerkat.protobuf.Mixing.*;
import meerkat.crypto.Encryption; import meerkat.crypto.Encryption;
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver;
import verifier.Verifier;
public class Mixer implements meerkat.crypto.mixnet.Mixer { public class Mixer implements meerkat.crypto.mixnet.Mixer {
private Random random; private Random random;
private Mix2ZeroKnowledgeProver prover; private Mix2ZeroKnowledgeProver prover;
private Encryption encryptor; private Encryption encryptor;
private Mix2ZeroKnowledgeVerifier verifier;
public Mixer(Random rand, Mix2ZeroKnowledgeProver prov, Encryption enc) { public Mixer(Random rand, Mix2ZeroKnowledgeProver prov, Encryption enc) {
this.random = rand; this.random = rand;
this.prover = prov; this.prover = prov;
this.encryptor = enc; this.encryptor = enc;
this.verifier = null;
} }
public Pair<ZeroKnowledgeProof[][], RerandomizableEncryptedMessage[][]> mix(List<RerandomizableEncryptedMessage> ciphertexts) throws InvalidProtocolBufferException { public Pair<ZeroKnowledgeProof[][], RerandomizableEncryptedMessage[][]> mix(List<RerandomizableEncryptedMessage> ciphertexts) throws InvalidProtocolBufferException {
int n = ciphertexts.size(); int n = ciphertexts.size();
@ -50,6 +55,7 @@ public class Mixer implements meerkat.crypto.mixnet.Mixer {
encryptionTable[0][j] = ciphertexts.get(j); encryptionTable[0][j] = ciphertexts.get(j);
} }
// main loop // main loop
for (int layer = 0; layer < layers; layer++) for (int layer = 0; layer < layers; layer++)
{ {
@ -73,6 +79,8 @@ public class Mixer implements meerkat.crypto.mixnet.Mixer {
prover.prove(e1, e2, encryptionTable[layer + 1][index1], prover.prove(e1, e2, encryptionTable[layer + 1][index1],
encryptionTable[layer + 1][index2], encryptionTable[layer + 1][index2],
sw.value, sw.i,sw.j,sw.layer, r1, r2); sw.value, sw.i,sw.j,sw.layer, r1, r2);
switchIndex = (switchIndex + 1) % nDiv2;
} }
} }
return new Pair<ZeroKnowledgeProof[][], RerandomizableEncryptedMessage[][]>(proofsTable, encryptionTable); return new Pair<ZeroKnowledgeProof[][], RerandomizableEncryptedMessage[][]>(proofsTable, encryptionTable);

View File

@ -14,4 +14,15 @@ public class Switch{
this.layer = layer; this.layer = layer;
this.value = value; this.value = value;
} }
@Override
public String toString() {
return "Switch{" +
"i=" + i +
", j=" + j +
", layer=" + layer +
", value=" + value +
'}';
}
} }

View File

@ -1,25 +0,0 @@
package necessary;
import meerkat.protobuf.ConcreteCrypto;
import meerkat.protobuf.Crypto;
import com.google.protobuf.ByteString;
import meerkat.protobuf.Mixing;
import java.math.BigInteger;
public interface General {
/*
given RerandomizableEncryptedMessage returns an equivalent ElGamalCiphertext
*/
ConcreteCrypto.ElGamalCiphertext calcRerandomizable2ElGamal(Crypto.RerandomizableEncryptedMessage enc);
ByteString getG();
ByteString getH();
/*
fiat shamir assumption
*/
BigInteger hash(Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle input);
}

View File

@ -1,46 +0,0 @@
package necessary;
import com.google.protobuf.ByteString;
import meerkat.protobuf.ConcreteCrypto;
import meerkat.protobuf.Crypto;
import meerkat.protobuf.Mixing;
import qilin.primitives.RandomOracle;
import java.math.BigInteger;
/**
* Created by Tzlil on 12/14/2015.
*/
public class GeneralImpl implements General {
private final RandomOracle rndomOracle;
private final ByteString h;
private final ByteString g;
public GeneralImpl(RandomOracle randomOracle,ByteString g,ByteString h) {
this.rndomOracle = randomOracle;
this.h = h;
this.g = g;
}
@Override
public ConcreteCrypto.ElGamalCiphertext calcRerandomizable2ElGamal(Crypto.RerandomizableEncryptedMessage enc) {
return null;
}
@Override
public ByteString getG() {
return g;
}
@Override
public ByteString getH() {
return h;
}
@Override
public BigInteger hash(Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle input) {
byte[] arr = input.toByteArray();
return new BigInteger(this.rndomOracle.hash(arr,arr.length));
}
}

View File

@ -0,0 +1,76 @@
package prover;
import meerkat.protobuf.Crypto;
/**
* Created by Tzlil on 12/30/2015.
*/
public class ProofOrganizer {
private final Crypto.RerandomizableEncryptedMessage e1;
private final Crypto.RerandomizableEncryptedMessage e2;
private final Crypto.RerandomizableEncryptedMessage e1New;
private final Crypto.RerandomizableEncryptedMessage e2New;
//in1, out1, in2, out1,
//in1, out1, in1, out2
//in2, out1, in2, out2,
//in1, out2, in2, out2
public ProofOrganizer(Crypto.RerandomizableEncryptedMessage e1,Crypto.RerandomizableEncryptedMessage e2
,Crypto.RerandomizableEncryptedMessage e1New,Crypto.RerandomizableEncryptedMessage e2New)
{
this.e1 = e1;
this.e2 = e2;
this.e1New = e1New;
this.e2New = e2New;
}
public enum OrProofOrder{
first,second,third,fourth
}
public Crypto.RerandomizableEncryptedMessage getE1(OrProofOrder orProofOrder)
{
switch (orProofOrder){
case third:
return e2;
default:
return e1;
}
}
public Crypto.RerandomizableEncryptedMessage getE1New(OrProofOrder orProofOrder)
{
switch (orProofOrder){
case fourth:
return e2New;
default:
return e1New;
}
}
public Crypto.RerandomizableEncryptedMessage getE2(OrProofOrder orProofOrder)
{
switch (orProofOrder){
case second:
return e1;
default:
return e2;
}
}
public Crypto.RerandomizableEncryptedMessage getE2New(OrProofOrder orProofOrder)
{
switch (orProofOrder){
case first:
return e1New;
default:
return e2New;
}
}
}

View File

@ -1,66 +1,135 @@
package prover; package prover;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import meerkat.crypto.Encryption; import com.google.protobuf.InvalidProtocolBufferException;
import meerkat.crypto.concrete.ECElGamalEncryption;
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver;
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier;
import meerkat.protobuf.ConcreteCrypto.ElGamalCiphertext; import meerkat.protobuf.ConcreteCrypto.ElGamalCiphertext;
import meerkat.protobuf.Crypto; import meerkat.protobuf.Crypto;
import meerkat.protobuf.Mixing; import meerkat.protobuf.Mixing;
import necessary.General; import org.bouncycastle.math.ec.ECPoint;
import qilin.primitives.Group; import qilin.primitives.RandomOracle;
import qilin.primitives.concrete.ECGroup;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.Random; import java.util.Random;
public class Prover implements Mix2ZeroKnowledgeProver { public class Prover implements Mix2ZeroKnowledgeProver {
Group<ByteString> group; ECGroup group;
General general; RandomOracle randomOracle;
Random rand; Random rand;
Encryption encryptor; ECElGamalEncryption ecElGamalEncryption;
ECPoint g,h;
Mix2ZeroKnowledgeVerifier verifier;
public Prover(Random rand,ECElGamalEncryption encryptor,RandomOracle randomOracle) {
public Prover(Group<ByteString> group,Random rand,Encryption encryptor,General general) {
this.group = group;
this.rand = rand; this.rand = rand;
this.encryptor = encryptor; this.ecElGamalEncryption = encryptor;
this.general = general; this.randomOracle = randomOracle;
this.group = ecElGamalEncryption.getGroup();
this.g = group.getGenerator();
this.h = ecElGamalEncryption.getElGamalPK().getPK();
verifier = null;
} }
public Prover(Random rand,ECElGamalEncryption encryptor,RandomOracle randomOracle,Mix2ZeroKnowledgeVerifier verifier) {
this.rand = rand;
this.ecElGamalEncryption = encryptor;
this.randomOracle = randomOracle;
this.group = ecElGamalEncryption.getGroup();
this.g = group.getGenerator();
this.h = ecElGamalEncryption.getElGamalPK().getPK();
this.verifier = verifier;
}
public Mixing.ZeroKnowledgeProof prove(Crypto.RerandomizableEncryptedMessage in1, public Mixing.ZeroKnowledgeProof prove(Crypto.RerandomizableEncryptedMessage in1,
Crypto.RerandomizableEncryptedMessage in2, Crypto.RerandomizableEncryptedMessage in2,
Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out1,
Crypto.RerandomizableEncryptedMessage out2, Crypto.RerandomizableEncryptedMessage out2,
boolean sw,int i,int j, int layer, boolean sw,int i,int j, int layer,
Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r1,
Crypto.EncryptionRandomness r2) { Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException {
Mixing.ZeroKnowledgeProof.OrProof first,second,third,fourth; Mixing.ZeroKnowledgeProof.OrProof first,second,third,fourth;
ProofOrganizer organizer = new ProofOrganizer(in1,in2,out1,out2);
if (!sw) if (!sw)
{ {
first = createOrProof(in1, out1, in2, out1, r1, true); first = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.first),
second = createOrProof(in1, out1, in1, out2, r1, true); organizer.getE2(ProofOrganizer.OrProofOrder.first),
third = createOrProof(in2, out1, in2, out2, r2, false); organizer.getE1New(ProofOrganizer.OrProofOrder.first),
fourth = createOrProof(in1, out2, in2, out2, r2, false); organizer.getE2New(ProofOrganizer.OrProofOrder.first),
r1, true);
second = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.second),
organizer.getE2(ProofOrganizer.OrProofOrder.second),
organizer.getE1New(ProofOrganizer.OrProofOrder.second),
organizer.getE2New(ProofOrganizer.OrProofOrder.second), r1, true);
third = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.third),
organizer.getE2(ProofOrganizer.OrProofOrder.third),
organizer.getE1New(ProofOrganizer.OrProofOrder.third),
organizer.getE2New(ProofOrganizer.OrProofOrder.third), r2, false);
fourth = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.fourth),
organizer.getE2(ProofOrganizer.OrProofOrder.fourth),
organizer.getE1New(ProofOrganizer.OrProofOrder.fourth),
organizer.getE2New(ProofOrganizer.OrProofOrder.fourth), r2, false);
} }
else else
{ {
first = createOrProof(in1, out1, in2, out1, r2, false); first = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.first),
second = createOrProof(in1, out1, in1, out2, r1, false); organizer.getE2(ProofOrganizer.OrProofOrder.first),
third = createOrProof(in2, out1, in2, out2, r2, true); organizer.getE1New(ProofOrganizer.OrProofOrder.first),
fourth = createOrProof(in1, out2, in2, out2, r1, true); organizer.getE2New(ProofOrganizer.OrProofOrder.first),
r2, false);
second = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.second),
organizer.getE2(ProofOrganizer.OrProofOrder.second),
organizer.getE1New(ProofOrganizer.OrProofOrder.second),
organizer.getE2New(ProofOrganizer.OrProofOrder.second),
r1, false);
third = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.third),
organizer.getE2(ProofOrganizer.OrProofOrder.third),
organizer.getE1New(ProofOrganizer.OrProofOrder.third),
organizer.getE2New(ProofOrganizer.OrProofOrder.third),
r2, true);
fourth = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.fourth),
organizer.getE2(ProofOrganizer.OrProofOrder.fourth),
organizer.getE1New(ProofOrganizer.OrProofOrder.fourth),
organizer.getE2New(ProofOrganizer.OrProofOrder.fourth),
r1, true);
} }
Mixing.ZeroKnowledgeProof.Location location = Mixing.ZeroKnowledgeProof.Location.newBuilder() Mixing.ZeroKnowledgeProof.Location location = Mixing.ZeroKnowledgeProof.Location.newBuilder()
.setI(i) .setI(i)
.setJ(j) .setJ(j)
.setLayer(layer) .setLayer(layer)
.build(); .build();
return Mixing.ZeroKnowledgeProof.newBuilder()
Mixing.ZeroKnowledgeProof result = Mixing.ZeroKnowledgeProof.newBuilder()
.setFirst(first) .setFirst(first)
.setSecond(second) .setSecond(second)
.setThird(third) .setThird(third)
.setFourth(fourth) .setFourth(fourth)
.setLocation(location) .setLocation(location)
.build(); .build();
//debuging
if (verifier != null){
if (!verifier.verify(in1,in2,out1,out2,result)){
System.out.print(location.toString());
System.out.println("switch value : " + sw);
}
}
return result;
} }
private Mixing.ZeroKnowledgeProof.OrProof createOrProof(Crypto.RerandomizableEncryptedMessage e1, private Mixing.ZeroKnowledgeProof.OrProof createOrProof(Crypto.RerandomizableEncryptedMessage e1,
@ -68,42 +137,51 @@ public class Prover implements Mix2ZeroKnowledgeProver {
Crypto.RerandomizableEncryptedMessage e1New, Crypto.RerandomizableEncryptedMessage e1New,
Crypto.RerandomizableEncryptedMessage e2New, Crypto.RerandomizableEncryptedMessage e2New,
Crypto.EncryptionRandomness x, Crypto.EncryptionRandomness x,
boolean flag){ boolean flag) throws InvalidProtocolBufferException {
ElGamalCiphertext e1ElGamal = general.calcRerandomizable2ElGamal(e1);
ElGamalCiphertext e2ElGamal = general.calcRerandomizable2ElGamal(e2);
ElGamalCiphertext e1TagElGamal = general.calcRerandomizable2ElGamal(e1New);
ElGamalCiphertext e2TagElGamal = general.calcRerandomizable2ElGamal(e2New);
ElGamalCiphertext e1ElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e1);
ElGamalCiphertext e2ElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e2);
ElGamalCiphertext e1TagElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e1New);
ElGamalCiphertext e2TagElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e2New);
return createOrProofElGamal(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,x,flag); return createOrProofElGamal(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,x,flag);
} }
private ECPoint convert2ECPoint(ByteString bs){
return group.decode(bs.toByteArray());
}
public BigInteger hash(Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle input) {
byte[] arr = input.toByteArray();
return new BigInteger(this.randomOracle.hash(arr,arr.length));
}
private Mixing.ZeroKnowledgeProof.OrProof createOrProofElGamal(ElGamalCiphertext e1, private Mixing.ZeroKnowledgeProof.OrProof createOrProofElGamal(ElGamalCiphertext e1,
ElGamalCiphertext e2, ElGamalCiphertext e2,
ElGamalCiphertext e1New, ElGamalCiphertext e1New,
ElGamalCiphertext e2New, ElGamalCiphertext e2New,
Crypto.EncryptionRandomness x, Crypto.EncryptionRandomness x,
boolean flag) { boolean flag) {
ByteString g1 = general.getG();
ByteString h1 = group.add(e1New.getC1(),group.negate(e1.getC1()));
ByteString g2 = general.getH();
ByteString h2 = group.add(e1New.getC2(),group.negate(e1.getC2()));
ByteString g1Tag = general.getG(); ECPoint g1 = g;
ByteString h1Tag = group.add(e2New.getC1(),group.negate(e2.getC1())); ECPoint h1 = group.add(convert2ECPoint(e1New.getC1()),group.negate(convert2ECPoint(e1.getC1())));
ByteString g2Tag = general.getH(); ECPoint g2 = h;
ByteString h2Tag = group.add(e2New.getC2(),group.negate(e2.getC2())); ECPoint h2 = group.add(convert2ECPoint(e1New.getC2()),group.negate(convert2ECPoint(e1.getC2())));
BigInteger r = new BigInteger(encryptor.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound()); ECPoint g1Tag = g;
ECPoint h1Tag = group.add(convert2ECPoint(e2New.getC1()),group.negate(convert2ECPoint(e2.getC1())));
ECPoint g2Tag = h;
ECPoint h2Tag = group.add(convert2ECPoint(e2New.getC2()),group.negate(convert2ECPoint(e2.getC2())));
BigInteger r = new BigInteger(ecElGamalEncryption.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound());
BigInteger c1,c2,z,zTag; BigInteger c1,c2,z,zTag;
ByteString u,v,uTag,vTag; ECPoint u,v,uTag,vTag;
if (flag) if (flag)
{ {
c2 = new BigInteger(encryptor.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound()); c2 = new BigInteger(ecElGamalEncryption.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound());
zTag = new BigInteger(encryptor.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound()); zTag = new BigInteger(ecElGamalEncryption.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound());
//step 1 //step 1
u = group.multiply(g1, r); u = group.multiply(g1, r);
v = group.multiply(g2, r); v = group.multiply(g2, r);
@ -113,28 +191,28 @@ public class Prover implements Mix2ZeroKnowledgeProver {
// c1 = (hash(input + step1) + group size - c2)% group size // c1 = (hash(input + step1) + group size - c2)% group size
Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle = Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle =
Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle.newBuilder() Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle.newBuilder()
.setG1(g1) .setG1(ByteString.copyFrom(group.encode(g1)))
.setH1(h1) .setH1(ByteString.copyFrom(group.encode(h1)))
.setG2(g2) .setG2(ByteString.copyFrom(group.encode(g2)))
.setH2(h2) .setH2(ByteString.copyFrom(group.encode(h2)))
.setG1Tag(g1Tag) .setG1Tag(ByteString.copyFrom(group.encode(g1Tag)))
.setH1Tag(h1Tag) .setH1Tag(ByteString.copyFrom(group.encode(h1Tag)))
.setG2Tag(g2Tag) .setG2Tag(ByteString.copyFrom(group.encode(g2Tag)))
.setH2Tag(h2Tag) .setH2Tag(ByteString.copyFrom(group.encode(h2Tag)))
.setU(u) .setU(ByteString.copyFrom(group.encode(u)))
.setV(v) .setV(ByteString.copyFrom(group.encode(v)))
.setUTag(uTag) .setUTag(ByteString.copyFrom(group.encode(uTag)))
.setVTag(vTag) .setVTag(ByteString.copyFrom(group.encode(vTag)))
.build(); .build();
c1 = general.hash(forRandomOracle).add(group.orderUpperBound().subtract(c2)).mod(group.orderUpperBound()); c1 = hash(forRandomOracle).add(group.orderUpperBound().subtract(c2)).mod(group.orderUpperBound());
//step 3 //step 3
//z = (r + c1 * x) % group size; //z = (r + c1 * x) % group size;
z = r.add(c1.multiply(new BigInteger(x.getData().toByteArray()))).mod(group.orderUpperBound()); z = r.add(c1.multiply(new BigInteger(x.getData().toByteArray()))).mod(group.orderUpperBound());
} }
else else
{ {
c1 = new BigInteger(encryptor.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound()); c1 = new BigInteger(ecElGamalEncryption.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound());
z = new BigInteger(encryptor.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound()); z = new BigInteger(ecElGamalEncryption.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound());
//step 1 //step 1
uTag = group.multiply(g1Tag, r); uTag = group.multiply(g1Tag, r);
vTag = group.multiply(g2Tag, r); vTag = group.multiply(g2Tag, r);
@ -144,37 +222,37 @@ public class Prover implements Mix2ZeroKnowledgeProver {
// c1 = (hash(input + step1) + group size - c1)% group size // c1 = (hash(input + step1) + group size - c1)% group size
Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle = Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle =
Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle.newBuilder() Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle.newBuilder()
.setG1(g1) .setG1(ByteString.copyFrom(group.encode(g1)))
.setH1(h1) .setH1(ByteString.copyFrom(group.encode(h1)))
.setG2(g2) .setG2(ByteString.copyFrom(group.encode(g2)))
.setH2(h2) .setH2(ByteString.copyFrom(group.encode(h2)))
.setG1Tag(g1Tag) .setG1Tag(ByteString.copyFrom(group.encode(g1Tag)))
.setH1Tag(h1Tag) .setH1Tag(ByteString.copyFrom(group.encode(h1Tag)))
.setG2Tag(g2Tag) .setG2Tag(ByteString.copyFrom(group.encode(g2Tag)))
.setH2Tag(h2Tag) .setH2Tag(ByteString.copyFrom(group.encode(h2Tag)))
.setU(u) .setU(ByteString.copyFrom(group.encode(u)))
.setV(v) .setV(ByteString.copyFrom(group.encode(v)))
.setUTag(uTag) .setUTag(ByteString.copyFrom(group.encode(uTag)))
.setVTag(vTag) .setVTag(ByteString.copyFrom(group.encode(vTag)))
.build(); .build();
c2 = general.hash(forRandomOracle).add(group.orderUpperBound().subtract(c1)).mod(group.orderUpperBound()); c2 = hash(forRandomOracle).add(group.orderUpperBound().subtract(c1)).mod(group.orderUpperBound());
//step 3 //step 3
//zTag = (r + c2 * x) % group size; //zTag = (r + c2 * x) % group size;
zTag = r.add(c2.multiply(new BigInteger(x.getData().toByteArray()))).mod(group.orderUpperBound()); zTag = r.add(c2.multiply(new BigInteger(x.getData().toByteArray()))).mod(group.orderUpperBound());
} }
return Mixing.ZeroKnowledgeProof.OrProof.newBuilder() return Mixing.ZeroKnowledgeProof.OrProof.newBuilder()
.setG1(g1) .setG1(ByteString.copyFrom(group.encode(g1)))
.setH1(h1) .setH1(ByteString.copyFrom(group.encode(h1)))
.setG2(g2) .setG2(ByteString.copyFrom(group.encode(g2)))
.setH2(h2) .setH2(ByteString.copyFrom(group.encode(h2)))
.setG1Tag(g1Tag) .setG1Tag(ByteString.copyFrom(group.encode(g1Tag)))
.setH1Tag(h1Tag) .setH1Tag(ByteString.copyFrom(group.encode(h1Tag)))
.setG2Tag(g2Tag) .setG2Tag(ByteString.copyFrom(group.encode(g2Tag)))
.setH2Tag(h2Tag) .setH2Tag(ByteString.copyFrom(group.encode(h2Tag)))
.setU(u) .setU(ByteString.copyFrom(group.encode(u)))
.setV(v) .setV(ByteString.copyFrom(group.encode(v)))
.setUTag(uTag) .setUTag(ByteString.copyFrom(group.encode(uTag)))
.setVTag(vTag) .setVTag(ByteString.copyFrom(group.encode(vTag)))
.setC1(ByteString.copyFrom(c1.toByteArray())) .setC1(ByteString.copyFrom(c1.toByteArray()))
.setC2(ByteString.copyFrom(c2.toByteArray())) .setC2(ByteString.copyFrom(c2.toByteArray()))
.setZ(ByteString.copyFrom(z.toByteArray())) .setZ(ByteString.copyFrom(z.toByteArray()))

View File

@ -1,17 +1,24 @@
package verifier; package verifier;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import meerkat.crypto.concrete.ECElGamalEncryption;
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier;
import meerkat.protobuf.ConcreteCrypto.ElGamalCiphertext; import meerkat.protobuf.ConcreteCrypto.ElGamalCiphertext;
import meerkat.protobuf.Crypto; import meerkat.protobuf.Crypto;
import meerkat.protobuf.Mixing; import meerkat.protobuf.Mixing;
import necessary.General; import org.bouncycastle.math.ec.ECPoint;
import qilin.primitives.Group; import prover.ProofOrganizer;
import qilin.primitives.RandomOracle;
import qilin.primitives.concrete.ECGroup;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.List;
public class Verifier implements Mix2ZeroKnowledgeVerifier { public class Verifier implements Mix2ZeroKnowledgeVerifier {
/** /**
* Return true iff the proof is valid. * Return true iff the proof is valid.
* @param in1 * @param in1
@ -21,38 +28,78 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier {
* @return * @return
*/ */
Group group; ECGroup group;
General general; RandomOracle randomOracle;
ECElGamalEncryption encryptor;
ECPoint g,h;
public Verifier(Group group,General general) { public Verifier(ECElGamalEncryption encryptor, RandomOracle randomOracle) {
this.group = group; this.encryptor = encryptor;
this.general = general; this.group = encryptor.getGroup();
this.g = group.getGenerator();
this.h = encryptor.getElGamalPK().getPK();
this.randomOracle = randomOracle;
} }
public BigInteger hash(Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle input) {
byte[] arr = input.toByteArray();
return new BigInteger(this.randomOracle.hash(arr,arr.length));
}
private ECPoint convert2ECPoint(ByteString bs){
return group.decode(bs.toByteArray());
}
public boolean verify(Crypto.RerandomizableEncryptedMessage in1, public boolean verify(Crypto.RerandomizableEncryptedMessage in1,
Crypto.RerandomizableEncryptedMessage in2, Crypto.RerandomizableEncryptedMessage in2,
Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out1,
Crypto.RerandomizableEncryptedMessage out2, Crypto.RerandomizableEncryptedMessage out2,
Mixing.ZeroKnowledgeProof proof) Mixing.ZeroKnowledgeProof proof) throws InvalidProtocolBufferException {
{
ElGamalCiphertext e1ElGamal = general.calcRerandomizable2ElGamal(in1); ProofOrganizer organizer = new ProofOrganizer(in1,in2,out1,out2);
ElGamalCiphertext e2ElGamal = general.calcRerandomizable2ElGamal(in2); return verifyOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.first),
ElGamalCiphertext e1TagElGamal = general.calcRerandomizable2ElGamal(out1); organizer.getE2(ProofOrganizer.OrProofOrder.first),
ElGamalCiphertext e2TagElGamal = general.calcRerandomizable2ElGamal(out2); organizer.getE1New(ProofOrganizer.OrProofOrder.first),
organizer.getE2New(ProofOrganizer.OrProofOrder.first),
proof.getFirst(),ProofOrganizer.OrProofOrder.first)&&
verifyOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.second),
organizer.getE2(ProofOrganizer.OrProofOrder.second),
organizer.getE1New(ProofOrganizer.OrProofOrder.second),
organizer.getE2New(ProofOrganizer.OrProofOrder.second),
proof.getSecond(),ProofOrganizer.OrProofOrder.second)&&
verifyOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.third),
organizer.getE2(ProofOrganizer.OrProofOrder.third),
organizer.getE1New(ProofOrganizer.OrProofOrder.third),
organizer.getE2New(ProofOrganizer.OrProofOrder.third),
proof.getThird(),ProofOrganizer.OrProofOrder.third)&&
verifyOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.fourth),
organizer.getE2(ProofOrganizer.OrProofOrder.fourth),
organizer.getE1New(ProofOrganizer.OrProofOrder.fourth),
organizer.getE2New(ProofOrganizer.OrProofOrder.fourth),
proof.getFourth(),ProofOrganizer.OrProofOrder.fourth);
}
return verifyElGamaOrProof(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,proof.getFirst()) &&
verifyElGamaOrProof(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,proof.getSecond()) && public boolean verifyOrProof(Crypto.RerandomizableEncryptedMessage e1,
verifyElGamaOrProof(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,proof.getThird()) && Crypto.RerandomizableEncryptedMessage e2,
verifyElGamaOrProof(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,proof.getFourth()); Crypto.RerandomizableEncryptedMessage e1Tag,
Crypto.RerandomizableEncryptedMessage e2Tag,
Mixing.ZeroKnowledgeProof.OrProof orProof, ProofOrganizer.OrProofOrder orProofOrder) throws InvalidProtocolBufferException {
ElGamalCiphertext e1ElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e1);
ElGamalCiphertext e2ElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e2);
ElGamalCiphertext e1TagElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e1Tag);
ElGamalCiphertext e2TagElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e2Tag);
return verifyElGamaOrProof(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,orProof,orProofOrder);
} }
public boolean verifyElGamaOrProof(ElGamalCiphertext e1, public boolean verifyElGamaOrProof(ElGamalCiphertext e1,
ElGamalCiphertext e2, ElGamalCiphertext e2,
ElGamalCiphertext e1New, ElGamalCiphertext e1New,
ElGamalCiphertext e2New, ElGamalCiphertext e2New,
Mixing.ZeroKnowledgeProof.OrProof orProof) Mixing.ZeroKnowledgeProof.OrProof orProof, ProofOrganizer.OrProofOrder orProofOrder)
{ {
Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle = Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle =
@ -71,30 +118,107 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier {
.setVTag(orProof.getVTag()) .setVTag(orProof.getVTag())
.build(); .build();
ECPoint g1,g2,h1,h2;
ECPoint g1Tag,g2Tag,h1Tag,h2Tag;
g1 = convert2ECPoint(orProof.getG1());
g2 = convert2ECPoint(orProof.getG2());
h1 = convert2ECPoint(orProof.getH1());
h2 = convert2ECPoint(orProof.getH2());
g1Tag = convert2ECPoint(orProof.getG1Tag());
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;
System.out.print("\n\n\n");
System.out.println(orProofOrder.toString());
}
System.out.println(description[j]);
}
}
return //input return //input
orProof.getG1().equals(general.getG())&& g1.equals(g)&&
orProof.getH1().equals(group.add(e1New.getC1(), group.negate(e1.getC1())))&& h1.equals(group.add(convert2ECPoint(e1New.getC1())
orProof.getG2().equals(general.getH())&& , group.negate(convert2ECPoint(e1.getC1()))))&&
orProof.getH2().equals(group.add(e1New.getC2(), group.negate(e1.getC2())))&& g2.equals(h)&&
h2.equals(group.add(convert2ECPoint(e1New.getC2())
, group.negate(convert2ECPoint(e1.getC2()))))&&
// input' // input'
orProof.getG1Tag().equals(general.getG())&& g1Tag.equals(g)&&
orProof.getH1Tag().equals(group.add(e2New.getC1(), group.negate(e2.getC1())))&& h1Tag.equals(group.add(convert2ECPoint(e2New.getC1())
orProof.getG2Tag().equals(general.getH())&& , group.negate(convert2ECPoint(e2.getC1()))))&&
orProof.getH2Tag().equals(group.add(e2New.getC2(), group.negate(e2.getC2()))) && g2Tag.equals(h)&&
h2Tag.equals(group.add(convert2ECPoint(e2New.getC2())
, group.negate(convert2ECPoint(e2.getC2())))) &&
// hash // hash
// assert (c1 + c2 ) % group size == hash (imput + step1) % group size // assert (c1 + c2 ) % group size == hash (imput + step1) % group size
new BigInteger(orProof.getC1().toByteArray()).add(new BigInteger(orProof.getC2().toByteArray())).mod(group.orderUpperBound()) new BigInteger(orProof.getC1().toByteArray()).add(new BigInteger(orProof.getC2().toByteArray())).mod(group.orderUpperBound())
.equals(general.hash(forRandomOracle).mod(group.orderUpperBound()).mod(group.orderUpperBound()))&& .equals(hash(forRandomOracle).mod(group.orderUpperBound()).mod(group.orderUpperBound()))&&
// proof // proof
// g1 ^ z == u * ( h1 ^ c1 ) && g2 ^ z == v * ( h2 ^ c1 ) && the same for tag case // g1 ^ z == u * ( h1 ^ c1 ) && g2 ^ z == v * ( h2 ^ c1 ) && the same for tag case
group.multiply(orProof.getG1(), new BigInteger(orProof.getZ().toByteArray())) group.multiply(g1, z).equals(group.add(u, group.multiply(h1,c1))) &&
.equals(group.add(orProof.getU(), group.multiply(orProof.getH1(),new BigInteger(orProof.getC1().toByteArray())))) && group.multiply(g2, z).equals(group.add(v, group.multiply(h2,c1))) &&
group.multiply(orProof.getG2(), new BigInteger(orProof.getZ().toByteArray())) group.multiply(g1Tag, zTag).equals(group.add(uTag, group.multiply(h1Tag,c2))) &&
.equals(group.add(orProof.getV(), group.multiply(orProof.getH2(),new BigInteger(orProof.getC1().toByteArray())))) && group.multiply(g2Tag, zTag).equals(group.add(vTag, group.multiply(h2Tag,c2)));
group.multiply(orProof.getG1Tag(), new BigInteger(orProof.getZTag().toByteArray()))
.equals(group.add(orProof.getUTag(), group.multiply(orProof.getH1Tag(),new BigInteger(orProof.getC2().toByteArray())))) &&
group.multiply(orProof.getG2Tag(), new BigInteger(orProof.getZTag().toByteArray()))
.equals(group.add(orProof.getVTag(), group.multiply(orProof.getH2Tag(),new BigInteger(orProof.getC2().toByteArray()))));
} }
} }

View File

@ -0,0 +1,83 @@
package verifier;
import com.google.protobuf.InvalidProtocolBufferException;
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier;
import meerkat.protobuf.Crypto;
import meerkat.protobuf.Mixing;
import qilin.util.Pair;
import java.util.Arrays;
/**
* Created by Tzlil on 12/30/2015.
*/
public final class VerifyTable {
public static boolean verifyTable(Mix2ZeroKnowledgeVerifier verifier,int n,Pair<Mixing.ZeroKnowledgeProof[][]
,Crypto.RerandomizableEncryptedMessage[][]> mixerOutput) throws InvalidProtocolBufferException {
int index1,index2,layer;
//assert n = 2^k
if ( (n &(n-1)) != 0)
throw new IllegalArgumentException("n");
int layers = 2*(int)(Math.log(n) / Math.log(2)) - 1;
//initialize locationChecksum table
// use for check BeneshNet validity
boolean[][] locationChecksum = new boolean[layers][n];
for (boolean[] locationChecksumLayer: locationChecksum) {
Arrays.fill(locationChecksumLayer,false);
}
Mixing.ZeroKnowledgeProof[][] zeroKnowledgeProofs = mixerOutput.a;
Crypto.RerandomizableEncryptedMessage[][] rerandomizableEncryptedMessages = mixerOutput.b;
for (Mixing.ZeroKnowledgeProof[] zkpLayer: zeroKnowledgeProofs) {
for (Mixing.ZeroKnowledgeProof zkp: zkpLayer) {
Mixing.ZeroKnowledgeProof.Location location = zkp.getLocation();
index1 = location.getI();
index2 = location.getJ();
layer = location.getLayer();
// check location validity
if (layer > layers >> 1) {
if (index2 - index1 != n >> (layers - layer))
return false;
}
else{
if (index2 - index1 != n >> (layer + 1))
return false;
}
// mark location in table
locationChecksum[layer][index1] = true;
locationChecksum[layer][index2] = true;
// verify proof
if(!verifier.verify(rerandomizableEncryptedMessages[layer][index1],
rerandomizableEncryptedMessages[layer][index2],
rerandomizableEncryptedMessages[layer + 1][index1],
rerandomizableEncryptedMessages[layer + 1][index2],
zkp)) {
verifier.verify(rerandomizableEncryptedMessages[layer][index1],
rerandomizableEncryptedMessages[layer][index2],
rerandomizableEncryptedMessages[layer + 1][index1],
rerandomizableEncryptedMessages[layer + 1][index2],
zkp);
System.out.print("\n\n\nlayer " + layer + " i , j " + index1 + " , " + index2 + "\n\n\n");
return false;
}
}
}
// verify all necessary locations for BeneshNet were proved
for (boolean[] checksumLayer: locationChecksum) {
for (boolean locationBoolean: checksumLayer) {
if (!locationBoolean)
return false;
}
}
return true;
}
}

View File

@ -0,0 +1,113 @@
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 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;
import java.util.Random;
public class MixingText {
ECElGamalEncryption encryptor;
ECGroup group;
Random random ;
private BigInteger sk;
private ECElGamal.SK key;
private ConcreteCrypto.ElGamalPublicKey serializedPk;
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);
}
}
@Test
public void mixingTest() throws InvalidProtocolBufferException, 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();
// generate n
int logN = 7; // + random.nextInt(8)
int layers = 2*logN - 1;
int 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);
// assert (VerifyTable.verifyTable(verifier,n,mixerOutput));
}
}