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();
}
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
public Crypto.RerandomizableEncryptedMessage rerandomize(Crypto.RerandomizableEncryptedMessage msg, Crypto.EncryptionRandomness rnd) throws InvalidProtocolBufferException {
BigInteger rndInt = BigIntegers.fromUnsignedByteArray(rnd.getData().toByteArray());

View File

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

View File

@ -1,5 +1,6 @@
package meerkat.crypto.mixnet;
import com.google.protobuf.InvalidProtocolBufferException;
import meerkat.protobuf.Crypto;
import meerkat.protobuf.Mixing;
@ -19,5 +20,5 @@ public interface Mix2ZeroKnowledgeVerifier {
Crypto.RerandomizableEncryptedMessage in2,
Crypto.RerandomizableEncryptedMessage out1,
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';
message Plaintext{
bytes data = 1;
}
message ZeroKnowledgeProof {
message OrProof {
message ForRandomOracle{

View File

@ -49,7 +49,7 @@ public class ECElGamalUtils {
.setSubjectPublicKeyInfo(ByteString.copyFrom(javaPk.getEncoded())).build();
return serializedPk;
} catch (NoSuchAlgorithmException|InvalidKeySpecException e) {
} catch (Exception e) {
logger.error("Should never happen!", 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;
//initialize locationChecksum table

View File

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

View File

@ -14,4 +14,15 @@ public class Switch{
this.layer = layer;
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;
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.Mix2ZeroKnowledgeVerifier;
import meerkat.protobuf.ConcreteCrypto.ElGamalCiphertext;
import meerkat.protobuf.Crypto;
import meerkat.protobuf.Mixing;
import necessary.General;
import qilin.primitives.Group;
import org.bouncycastle.math.ec.ECPoint;
import qilin.primitives.RandomOracle;
import qilin.primitives.concrete.ECGroup;
import java.math.BigInteger;
import java.util.Random;
public class Prover implements Mix2ZeroKnowledgeProver {
Group<ByteString> group;
General general;
ECGroup group;
RandomOracle randomOracle;
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.encryptor = encryptor;
this.general = general;
this.ecElGamalEncryption = encryptor;
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,
Crypto.RerandomizableEncryptedMessage in2,
Crypto.RerandomizableEncryptedMessage out1,
Crypto.RerandomizableEncryptedMessage out2,
boolean sw,int i,int j, int layer,
Crypto.EncryptionRandomness r1,
Crypto.EncryptionRandomness r2) {
Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException {
Mixing.ZeroKnowledgeProof.OrProof first,second,third,fourth;
ProofOrganizer organizer = new ProofOrganizer(in1,in2,out1,out2);
if (!sw)
{
first = createOrProof(in1, out1, in2, out1, r1, true);
second = createOrProof(in1, out1, in1, out2, r1, true);
third = createOrProof(in2, out1, in2, out2, r2, false);
fourth = createOrProof(in1, out2, in2, out2, r2, false);
first = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.first),
organizer.getE2(ProofOrganizer.OrProofOrder.first),
organizer.getE1New(ProofOrganizer.OrProofOrder.first),
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
{
first = createOrProof(in1, out1, in2, out1, r2, false);
second = createOrProof(in1, out1, in1, out2, r1, false);
third = createOrProof(in2, out1, in2, out2, r2, true);
fourth = createOrProof(in1, out2, in2, out2, r1, true);
first = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.first),
organizer.getE2(ProofOrganizer.OrProofOrder.first),
organizer.getE1New(ProofOrganizer.OrProofOrder.first),
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()
.setI(i)
.setJ(j)
.setLayer(layer)
.build();
return Mixing.ZeroKnowledgeProof.newBuilder()
Mixing.ZeroKnowledgeProof result = Mixing.ZeroKnowledgeProof.newBuilder()
.setFirst(first)
.setSecond(second)
.setThird(third)
.setFourth(fourth)
.setLocation(location)
.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,
@ -68,42 +137,51 @@ public class Prover implements Mix2ZeroKnowledgeProver {
Crypto.RerandomizableEncryptedMessage e1New,
Crypto.RerandomizableEncryptedMessage e2New,
Crypto.EncryptionRandomness x,
boolean flag){
ElGamalCiphertext e1ElGamal = general.calcRerandomizable2ElGamal(e1);
ElGamalCiphertext e2ElGamal = general.calcRerandomizable2ElGamal(e2);
ElGamalCiphertext e1TagElGamal = general.calcRerandomizable2ElGamal(e1New);
ElGamalCiphertext e2TagElGamal = general.calcRerandomizable2ElGamal(e2New);
boolean flag) throws InvalidProtocolBufferException {
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);
}
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,
ElGamalCiphertext e2,
ElGamalCiphertext e1New,
ElGamalCiphertext e2New,
Crypto.EncryptionRandomness x,
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();
ByteString h1Tag = group.add(e2New.getC1(),group.negate(e2.getC1()));
ByteString g2Tag = general.getH();
ByteString h2Tag = group.add(e2New.getC2(),group.negate(e2.getC2()));
ECPoint g1 = g;
ECPoint h1 = group.add(convert2ECPoint(e1New.getC1()),group.negate(convert2ECPoint(e1.getC1())));
ECPoint g2 = h;
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;
ByteString u,v,uTag,vTag;
ECPoint u,v,uTag,vTag;
if (flag)
{
c2 = new BigInteger(encryptor.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound());
zTag = new BigInteger(encryptor.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound());
c2 = new BigInteger(ecElGamalEncryption.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound());
zTag = new BigInteger(ecElGamalEncryption.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound());
//step 1
u = group.multiply(g1, r);
v = group.multiply(g2, r);
@ -113,28 +191,28 @@ public class Prover implements Mix2ZeroKnowledgeProver {
// c1 = (hash(input + step1) + group size - c2)% group size
Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle =
Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle.newBuilder()
.setG1(g1)
.setH1(h1)
.setG2(g2)
.setH2(h2)
.setG1Tag(g1Tag)
.setH1Tag(h1Tag)
.setG2Tag(g2Tag)
.setH2Tag(h2Tag)
.setU(u)
.setV(v)
.setUTag(uTag)
.setVTag(vTag)
.setG1(ByteString.copyFrom(group.encode(g1)))
.setH1(ByteString.copyFrom(group.encode(h1)))
.setG2(ByteString.copyFrom(group.encode(g2)))
.setH2(ByteString.copyFrom(group.encode(h2)))
.setG1Tag(ByteString.copyFrom(group.encode(g1Tag)))
.setH1Tag(ByteString.copyFrom(group.encode(h1Tag)))
.setG2Tag(ByteString.copyFrom(group.encode(g2Tag)))
.setH2Tag(ByteString.copyFrom(group.encode(h2Tag)))
.setU(ByteString.copyFrom(group.encode(u)))
.setV(ByteString.copyFrom(group.encode(v)))
.setUTag(ByteString.copyFrom(group.encode(uTag)))
.setVTag(ByteString.copyFrom(group.encode(vTag)))
.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
//z = (r + c1 * x) % group size;
z = r.add(c1.multiply(new BigInteger(x.getData().toByteArray()))).mod(group.orderUpperBound());
}
else
{
c1 = new BigInteger(encryptor.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound());
z = new BigInteger(encryptor.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound());
c1 = new BigInteger(ecElGamalEncryption.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound());
z = new BigInteger(ecElGamalEncryption.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound());
//step 1
uTag = group.multiply(g1Tag, r);
vTag = group.multiply(g2Tag, r);
@ -144,37 +222,37 @@ public class Prover implements Mix2ZeroKnowledgeProver {
// c1 = (hash(input + step1) + group size - c1)% group size
Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle =
Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle.newBuilder()
.setG1(g1)
.setH1(h1)
.setG2(g2)
.setH2(h2)
.setG1Tag(g1Tag)
.setH1Tag(h1Tag)
.setG2Tag(g2Tag)
.setH2Tag(h2Tag)
.setU(u)
.setV(v)
.setUTag(uTag)
.setVTag(vTag)
.setG1(ByteString.copyFrom(group.encode(g1)))
.setH1(ByteString.copyFrom(group.encode(h1)))
.setG2(ByteString.copyFrom(group.encode(g2)))
.setH2(ByteString.copyFrom(group.encode(h2)))
.setG1Tag(ByteString.copyFrom(group.encode(g1Tag)))
.setH1Tag(ByteString.copyFrom(group.encode(h1Tag)))
.setG2Tag(ByteString.copyFrom(group.encode(g2Tag)))
.setH2Tag(ByteString.copyFrom(group.encode(h2Tag)))
.setU(ByteString.copyFrom(group.encode(u)))
.setV(ByteString.copyFrom(group.encode(v)))
.setUTag(ByteString.copyFrom(group.encode(uTag)))
.setVTag(ByteString.copyFrom(group.encode(vTag)))
.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
//zTag = (r + c2 * x) % group size;
zTag = r.add(c2.multiply(new BigInteger(x.getData().toByteArray()))).mod(group.orderUpperBound());
}
return Mixing.ZeroKnowledgeProof.OrProof.newBuilder()
.setG1(g1)
.setH1(h1)
.setG2(g2)
.setH2(h2)
.setG1Tag(g1Tag)
.setH1Tag(h1Tag)
.setG2Tag(g2Tag)
.setH2Tag(h2Tag)
.setU(u)
.setV(v)
.setUTag(uTag)
.setVTag(vTag)
.setG1(ByteString.copyFrom(group.encode(g1)))
.setH1(ByteString.copyFrom(group.encode(h1)))
.setG2(ByteString.copyFrom(group.encode(g2)))
.setH2(ByteString.copyFrom(group.encode(h2)))
.setG1Tag(ByteString.copyFrom(group.encode(g1Tag)))
.setH1Tag(ByteString.copyFrom(group.encode(h1Tag)))
.setG2Tag(ByteString.copyFrom(group.encode(g2Tag)))
.setH2Tag(ByteString.copyFrom(group.encode(h2Tag)))
.setU(ByteString.copyFrom(group.encode(u)))
.setV(ByteString.copyFrom(group.encode(v)))
.setUTag(ByteString.copyFrom(group.encode(uTag)))
.setVTag(ByteString.copyFrom(group.encode(vTag)))
.setC1(ByteString.copyFrom(c1.toByteArray()))
.setC2(ByteString.copyFrom(c2.toByteArray()))
.setZ(ByteString.copyFrom(z.toByteArray()))

View File

@ -1,17 +1,24 @@
package verifier;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import meerkat.crypto.concrete.ECElGamalEncryption;
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier;
import meerkat.protobuf.ConcreteCrypto.ElGamalCiphertext;
import meerkat.protobuf.Crypto;
import meerkat.protobuf.Mixing;
import necessary.General;
import qilin.primitives.Group;
import org.bouncycastle.math.ec.ECPoint;
import prover.ProofOrganizer;
import qilin.primitives.RandomOracle;
import qilin.primitives.concrete.ECGroup;
import java.math.BigInteger;
import java.util.List;
public class Verifier implements Mix2ZeroKnowledgeVerifier {
/**
* Return true iff the proof is valid.
* @param in1
@ -21,38 +28,78 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier {
* @return
*/
Group group;
General general;
ECGroup group;
RandomOracle randomOracle;
ECElGamalEncryption encryptor;
ECPoint g,h;
public Verifier(Group group,General general) {
this.group = group;
this.general = general;
public Verifier(ECElGamalEncryption encryptor, RandomOracle randomOracle) {
this.encryptor = encryptor;
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,
Crypto.RerandomizableEncryptedMessage in2,
Crypto.RerandomizableEncryptedMessage out1,
Crypto.RerandomizableEncryptedMessage out2,
Mixing.ZeroKnowledgeProof proof)
{
Mixing.ZeroKnowledgeProof proof) throws InvalidProtocolBufferException {
ElGamalCiphertext e1ElGamal = general.calcRerandomizable2ElGamal(in1);
ElGamalCiphertext e2ElGamal = general.calcRerandomizable2ElGamal(in2);
ElGamalCiphertext e1TagElGamal = general.calcRerandomizable2ElGamal(out1);
ElGamalCiphertext e2TagElGamal = general.calcRerandomizable2ElGamal(out2);
ProofOrganizer organizer = new ProofOrganizer(in1,in2,out1,out2);
return verifyOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.first),
organizer.getE2(ProofOrganizer.OrProofOrder.first),
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()) &&
verifyElGamaOrProof(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,proof.getThird()) &&
verifyElGamaOrProof(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,proof.getFourth());
public boolean verifyOrProof(Crypto.RerandomizableEncryptedMessage e1,
Crypto.RerandomizableEncryptedMessage e2,
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,
ElGamalCiphertext e2,
ElGamalCiphertext e1New,
ElGamalCiphertext e2New,
Mixing.ZeroKnowledgeProof.OrProof orProof)
Mixing.ZeroKnowledgeProof.OrProof orProof, ProofOrganizer.OrProofOrder orProofOrder)
{
Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle =
@ -71,30 +118,107 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier {
.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());
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
orProof.getG1().equals(general.getG())&&
orProof.getH1().equals(group.add(e1New.getC1(), group.negate(e1.getC1())))&&
orProof.getG2().equals(general.getH())&&
orProof.getH2().equals(group.add(e1New.getC2(), group.negate(e1.getC2())))&&
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'
orProof.getG1Tag().equals(general.getG())&&
orProof.getH1Tag().equals(group.add(e2New.getC1(), group.negate(e2.getC1())))&&
orProof.getG2Tag().equals(general.getH())&&
orProof.getH2Tag().equals(group.add(e2New.getC2(), group.negate(e2.getC2()))) &&
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(general.hash(forRandomOracle).mod(group.orderUpperBound()).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(orProof.getG1(), new BigInteger(orProof.getZ().toByteArray()))
.equals(group.add(orProof.getU(), group.multiply(orProof.getH1(),new BigInteger(orProof.getC1().toByteArray())))) &&
group.multiply(orProof.getG2(), new BigInteger(orProof.getZ().toByteArray()))
.equals(group.add(orProof.getV(), group.multiply(orProof.getH2(),new BigInteger(orProof.getC1().toByteArray())))) &&
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()))));
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)));
}
}

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));
}
}