zkp verification fails from time to time
parent
75c411a5e7
commit
026a879de3
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,10 @@ option java_package = "meerkat.protobuf";
|
|||
|
||||
import 'meerkat/crypto.proto';
|
||||
|
||||
message Plaintext{
|
||||
bytes data = 1;
|
||||
}
|
||||
|
||||
message ZeroKnowledgeProof {
|
||||
message OrProof {
|
||||
message ForRandomOracle{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -206,8 +206,7 @@ public class MainMixing {
|
|||
|
||||
}
|
||||
|
||||
private boolean verifyTable()
|
||||
{
|
||||
private boolean verifyTable() throws InvalidProtocolBufferException {
|
||||
int index1,index2,layer;
|
||||
|
||||
//initialize locationChecksum table
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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()))
|
||||
|
|
|
@ -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)));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue