mixer + prover + verifier
parent
b502dc82d3
commit
23573666ec
|
@ -1,4 +1,4 @@
|
||||||
#Tue Dec 01 01:04:39 IST 2015
|
#Fri Dec 11 12:12:40 IST 2015
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|
|
@ -8,34 +8,27 @@ import 'meerkat/crypto.proto';
|
||||||
|
|
||||||
message ZeroKnowledgeProof {
|
message ZeroKnowledgeProof {
|
||||||
message OrProof {
|
message OrProof {
|
||||||
message GroupMember {
|
|
||||||
bytes data = 1;
|
|
||||||
}
|
|
||||||
message BigIntegerMsg {
|
|
||||||
bytes data = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//input : g1,h1, g2, h2, g1Tag, h1Tag, g2Tag, h2Tag;
|
//input : g1,h1, g2, h2, g1Tag, h1Tag, g2Tag, h2Tag;
|
||||||
GroupMember g1 = 1;
|
bytes g1 = 1;
|
||||||
GroupMember h1 = 2;
|
bytes h1 = 2;
|
||||||
GroupMember g2 = 3;
|
bytes g2 = 3;
|
||||||
GroupMember h2 = 4;
|
bytes h2 = 4;
|
||||||
GroupMember g1Tag = 5;
|
bytes g1Tag = 5;
|
||||||
GroupMember h1Tag = 6;
|
bytes h1Tag = 6;
|
||||||
GroupMember g2Tag = 7;
|
bytes g2Tag = 7;
|
||||||
GroupMember h2Tag = 8;
|
bytes h2Tag = 8;
|
||||||
|
|
||||||
//calc: u, v, uTag, vTag;
|
//calc: u, v, uTag, vTag;
|
||||||
GroupMember u = 9;
|
bytes u = 9;
|
||||||
GroupMember v = 10;
|
bytes v = 10;
|
||||||
GroupMember uTag = 11;
|
bytes uTag = 11;
|
||||||
GroupMember vTag = 12;
|
bytes vTag = 12;
|
||||||
|
|
||||||
//generated: c1,c2,z,zTag
|
//generated: c1,c2,z,zTag
|
||||||
BigIntegerMsg c1 = 13;
|
bytes c1 = 13;
|
||||||
BigIntegerMsg c2 = 14;
|
bytes c2 = 14;
|
||||||
BigIntegerMsg z = 15;
|
bytes z = 15;
|
||||||
BigIntegerMsg zTag = 16;
|
bytes zTag = 16;
|
||||||
}
|
}
|
||||||
OrProof first = 1;
|
OrProof first = 1;
|
||||||
OrProof second = 2;
|
OrProof second = 2;
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
package necessary;
|
||||||
|
|
||||||
|
import meerkat.protobuf.ConcreteCrypto;
|
||||||
|
import meerkat.protobuf.Crypto;
|
||||||
|
|
||||||
|
import com.google.protobuf.ByteString;
|
||||||
|
|
||||||
|
public interface General {
|
||||||
|
|
||||||
|
/*
|
||||||
|
given RerandomizableEncryptedMessage returns an equivalent ElGamalCiphertext
|
||||||
|
*/
|
||||||
|
ConcreteCrypto.ElGamalCiphertext calcRerandomizable2ElGamal(Crypto.RerandomizableEncryptedMessage enc);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
modulo operation over ByteString
|
||||||
|
*/
|
||||||
|
ByteString mod(ByteString dividend, ByteString divisor);
|
||||||
|
|
||||||
|
/*
|
||||||
|
addition operation over ByteString
|
||||||
|
*/
|
||||||
|
ByteString add(ByteString a, ByteString b);
|
||||||
|
|
||||||
|
/*
|
||||||
|
subtraction operation over ByteString
|
||||||
|
*/
|
||||||
|
ByteString sub(ByteString Subtraction, ByteString subtrahend);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
multiplication operation over ByteString
|
||||||
|
*/
|
||||||
|
ByteString mul(ByteString a, ByteString b);
|
||||||
|
|
||||||
|
/*
|
||||||
|
hash operation over ByteString
|
||||||
|
*/
|
||||||
|
ByteString hash(ByteString... arr);
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package necessary;
|
||||||
|
|
||||||
|
|
||||||
|
import com.google.protobuf.ByteString;
|
||||||
|
|
||||||
|
public interface Group {
|
||||||
|
|
||||||
|
ByteString getG();
|
||||||
|
ByteString getH();
|
||||||
|
ByteString div(ByteString dividend, ByteString divisor);
|
||||||
|
ByteString mul(ByteString a, ByteString b);
|
||||||
|
ByteString pow(ByteString bas, ByteString exp);
|
||||||
|
ByteString groupSize();
|
||||||
|
}
|
|
@ -0,0 +1,147 @@
|
||||||
|
package prover;
|
||||||
|
|
||||||
|
import com.google.protobuf.ByteString;
|
||||||
|
import meerkat.crypto.Encryption;
|
||||||
|
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver;
|
||||||
|
import meerkat.protobuf.ConcreteCrypto.ElGamalCiphertext;
|
||||||
|
import meerkat.protobuf.Crypto;
|
||||||
|
import meerkat.protobuf.Mixing;
|
||||||
|
import necessary.General;
|
||||||
|
import necessary.Group;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class Prover implements Mix2ZeroKnowledgeProver {
|
||||||
|
|
||||||
|
Group group;
|
||||||
|
General general;
|
||||||
|
Random rand;
|
||||||
|
Encryption encryptor;
|
||||||
|
|
||||||
|
public Prover(Group group,Random rand,Encryption encryptor,General general) {
|
||||||
|
this.group = group;
|
||||||
|
this.rand = rand;
|
||||||
|
this.encryptor = encryptor;
|
||||||
|
this.general = general;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mixing.ZeroKnowledgeProof prove(Crypto.RerandomizableEncryptedMessage in1,
|
||||||
|
Crypto.RerandomizableEncryptedMessage in2,
|
||||||
|
Crypto.RerandomizableEncryptedMessage out1,
|
||||||
|
Crypto.RerandomizableEncryptedMessage out2,
|
||||||
|
boolean switched,
|
||||||
|
Crypto.EncryptionRandomness r1,
|
||||||
|
Crypto.EncryptionRandomness r2) {
|
||||||
|
|
||||||
|
Mixing.ZeroKnowledgeProof.OrProof first,second,third,fourth;
|
||||||
|
if (!switched)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
return Mixing.ZeroKnowledgeProof.newBuilder()
|
||||||
|
.setFirst(first)
|
||||||
|
.setSecond(second)
|
||||||
|
.setThird(third)
|
||||||
|
.setFourth(fourth)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mixing.ZeroKnowledgeProof.OrProof createOrProof(Crypto.RerandomizableEncryptedMessage e1,
|
||||||
|
Crypto.RerandomizableEncryptedMessage e2,
|
||||||
|
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);
|
||||||
|
|
||||||
|
|
||||||
|
return createOrProofElGamal(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,x,flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mixing.ZeroKnowledgeProof.OrProof createOrProofElGamal(ElGamalCiphertext e1,
|
||||||
|
ElGamalCiphertext e2,
|
||||||
|
ElGamalCiphertext e1New,
|
||||||
|
ElGamalCiphertext e2New,
|
||||||
|
Crypto.EncryptionRandomness x,
|
||||||
|
boolean flag) {
|
||||||
|
ByteString g1 = group.getG();
|
||||||
|
ByteString h1 = group.div(e1New.getC1(),e1.getC1());
|
||||||
|
ByteString g2 = group.getH();
|
||||||
|
ByteString h2 = group.div(e1New.getC2(),e1.getC2());
|
||||||
|
|
||||||
|
ByteString g1Tag = group.getG();
|
||||||
|
ByteString h1Tag = group.div(e2New.getC1(),e2.getC1());
|
||||||
|
ByteString g2Tag = group.getH();
|
||||||
|
ByteString h2Tag = group.div(e2New.getC2(),e2.getC2());
|
||||||
|
|
||||||
|
ByteString r = general.mod(encryptor.generateRandomness(rand).getData(),group.groupSize());
|
||||||
|
ByteString u,v,uTag,vTag,c1,c2,z,zTag;
|
||||||
|
if (flag)
|
||||||
|
{
|
||||||
|
c2 = general.mod(encryptor.generateRandomness(rand).getData(),group.groupSize());
|
||||||
|
zTag = general.mod(encryptor.generateRandomness(rand).getData(),group.groupSize());
|
||||||
|
//step 1
|
||||||
|
u = group.pow(g1, r);
|
||||||
|
v = group.pow(g2, r);
|
||||||
|
uTag = group.div(group.pow(g1Tag, zTag), group.pow(h1Tag, c2));
|
||||||
|
vTag = group.div(group.pow(g2Tag, zTag), group.pow(h2Tag, c2));
|
||||||
|
//step 2
|
||||||
|
// c1 = (hash(input + step1) + group size - c2)% group size
|
||||||
|
c1 = general.mod(general.add(general.hash(g1, h1, g2, h2, g1Tag, h1Tag, g2Tag, h2Tag, u, v, uTag, vTag), general.sub(group.groupSize(), c2)),group.groupSize());
|
||||||
|
//step 3
|
||||||
|
//z = (r + c1 * x) % group size;
|
||||||
|
z = general.mod(general.add(r,general.mul(c1,x.getData())),group.groupSize());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c1 = general.mod(encryptor.generateRandomness(rand).getData(),group.groupSize());
|
||||||
|
z = general.mod(encryptor.generateRandomness(rand).getData(),group.groupSize());
|
||||||
|
//step 1
|
||||||
|
uTag = group.pow(g1Tag, r);
|
||||||
|
vTag = group.pow(g2Tag, r);
|
||||||
|
u = group.div(group.pow(g1, z), group.pow(h1, c1));
|
||||||
|
v = group.div(group.pow(g2, z), group.pow(h2, c1));
|
||||||
|
//step 2
|
||||||
|
// c1 = (hash(input + step1) + group size - c1)% group size
|
||||||
|
c2 = general.mod(general.add(general.hash(g1, h1, g2, h2, g1Tag, h1Tag, g2Tag, h2Tag, u, v, uTag, vTag), general.sub(group.groupSize(), c1)),group.groupSize());
|
||||||
|
//step 3
|
||||||
|
//zTag = (r + c2 * x) % group size;
|
||||||
|
zTag = general.mod(general.add(r,general.mul(c2,x.getData())),group.groupSize());
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
.setC1(c1)
|
||||||
|
.setC2(c2)
|
||||||
|
.setZ(z)
|
||||||
|
.setZTag(zTag)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
package verifier;
|
||||||
|
|
||||||
|
import meerkat.crypto.Encryption;
|
||||||
|
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier;
|
||||||
|
import meerkat.protobuf.ConcreteCrypto.ElGamalCiphertext;
|
||||||
|
import meerkat.protobuf.Crypto;
|
||||||
|
import meerkat.protobuf.Mixing;
|
||||||
|
import necessary.General;
|
||||||
|
import necessary.Group;
|
||||||
|
|
||||||
|
|
||||||
|
public class Verifier implements Mix2ZeroKnowledgeVerifier {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true iff the proof is valid.
|
||||||
|
* @param in1
|
||||||
|
* @param in2
|
||||||
|
* @param out1
|
||||||
|
* @param out2
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
|
||||||
|
Group group;
|
||||||
|
General general;
|
||||||
|
|
||||||
|
public Verifier(Group group,General general) {
|
||||||
|
this.group = group;
|
||||||
|
this.general = general;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean verify(Crypto.RerandomizableEncryptedMessage in1,
|
||||||
|
Crypto.RerandomizableEncryptedMessage in2,
|
||||||
|
Crypto.RerandomizableEncryptedMessage out1,
|
||||||
|
Crypto.RerandomizableEncryptedMessage out2,
|
||||||
|
Mixing.ZeroKnowledgeProof proof)
|
||||||
|
{
|
||||||
|
|
||||||
|
ElGamalCiphertext e1ElGamal = general.calcRerandomizable2ElGamal(in1);
|
||||||
|
ElGamalCiphertext e2ElGamal = general.calcRerandomizable2ElGamal(in2);
|
||||||
|
ElGamalCiphertext e1TagElGamal = general.calcRerandomizable2ElGamal(out1);
|
||||||
|
ElGamalCiphertext e2TagElGamal = general.calcRerandomizable2ElGamal(out2);
|
||||||
|
|
||||||
|
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 verifyElGamaOrProof(ElGamalCiphertext e1,
|
||||||
|
ElGamalCiphertext e2,
|
||||||
|
ElGamalCiphertext e1New,
|
||||||
|
ElGamalCiphertext e2New,
|
||||||
|
Mixing.ZeroKnowledgeProof.OrProof orProof)
|
||||||
|
{
|
||||||
|
|
||||||
|
return //input
|
||||||
|
orProof.getG1().equals(group.getG())&&
|
||||||
|
orProof.getH1().equals(group.div(e1New.getC1(), e1.getC1()))&&
|
||||||
|
orProof.getG2().equals(group.getH())&&
|
||||||
|
orProof.getH2().equals(group.div(e1New.getC2(), e1.getC2()))&&
|
||||||
|
// input'
|
||||||
|
orProof.getG1Tag().equals(group.getG())&&
|
||||||
|
orProof.getH1Tag().equals(group.div(e2New.getC1(), e2.getC1()))&&
|
||||||
|
orProof.getG2Tag().equals(group.getH())&&
|
||||||
|
orProof.getH2Tag().equals(group.div(e2New.getC2(), e2.getC2())) &&
|
||||||
|
// hash
|
||||||
|
// assert (c1 + c2 ) % group size == hash (imput + step1) % group size
|
||||||
|
general.mod((general.add(orProof.getC1(),orProof.getC2())),group.groupSize())
|
||||||
|
.equals(general.mod(general.hash(orProof.getG1(), orProof.getH1(), orProof.getG2(), orProof.getH2(),
|
||||||
|
orProof.getG1Tag(), orProof.getH1Tag(), orProof.getG2Tag(), orProof.getH2Tag(),
|
||||||
|
orProof.getV(),orProof.getU(),orProof.getVTag(),orProof.getUTag()) , group.groupSize()))&&
|
||||||
|
// proof
|
||||||
|
// g1 ^ z == u * ( h1 ^ c1 ) && g2 ^ z == v * ( h2 ^ c1 ) && the same for tag case
|
||||||
|
group.pow(orProof.getG1(), orProof.getZ()).equals(group.mul(orProof.getU(), group.pow(orProof.getH1(),orProof.getC1()))) &&
|
||||||
|
group.pow(orProof.getG2(), orProof.getZ()).equals(group.mul(orProof.getV(), group.pow(orProof.getH2(),orProof.getC1()))) &&
|
||||||
|
group.pow(orProof.getG1Tag(), orProof.getZTag()).equals(group.mul(orProof.getUTag(), group.pow(orProof.getH1Tag(),orProof.getC2()))) &&
|
||||||
|
group.pow(orProof.getG2Tag(), orProof.getZTag()).equals(group.mul(orProof.getVTag(), group.pow(orProof.getH2Tag(),orProof.getC2())));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue