More refactoring for mixer
parent
1baa567d8e
commit
5b268cd779
|
@ -0,0 +1,336 @@
|
|||
package meerkat.mixer.proofs;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||
import meerkat.protobuf.ConcreteCrypto;
|
||||
import meerkat.protobuf.Crypto;
|
||||
import org.bouncycastle.math.ec.ECPoint;
|
||||
import org.factcenter.qilin.primitives.concrete.ECGroup;
|
||||
|
||||
/**
|
||||
* use for organize the input for each ZKP
|
||||
*
|
||||
* both meerkat.mixer.proofs and meerkat.mixer.verifier implementation use it
|
||||
*/
|
||||
public class ECElGamalMixParams {
|
||||
|
||||
private final ECGroup group;
|
||||
private final ECPoint g;
|
||||
private final ECPoint h;
|
||||
private final byte[] gEncoded;
|
||||
private final byte[] hEncoded;
|
||||
|
||||
|
||||
/**
|
||||
* Decode from the serialized representation to an {@link ECPoint} object.
|
||||
* @param bs
|
||||
* @return
|
||||
*/
|
||||
private ECPoint decodeECPoint(ByteString bs){
|
||||
return group.decode(bs.toByteArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param group
|
||||
* @param g - generator of group
|
||||
* @param h - h = g ^ SecretKey
|
||||
*/
|
||||
public ECElGamalMixParams(ECGroup group, ECPoint g, ECPoint h){
|
||||
this.group = group;
|
||||
this.g = g;
|
||||
this.h = h;
|
||||
this.gEncoded = group.encode(g);
|
||||
this.hEncoded = group.encode(h);
|
||||
}
|
||||
|
||||
public enum TrueCouple {
|
||||
left, right, unknown
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* can be used by anyone, e.g meerkat.mixer.verifier
|
||||
*
|
||||
* call to the meerkat.mixer.main overload with flag = false
|
||||
*/
|
||||
public Statement createStatement(Crypto.RerandomizableEncryptedMessage in1, Crypto.RerandomizableEncryptedMessage in2
|
||||
, Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2) throws InvalidProtocolBufferException {
|
||||
|
||||
ConcreteCrypto.ElGamalCiphertext in1ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(in1);
|
||||
ConcreteCrypto.ElGamalCiphertext in2ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(in2);
|
||||
ConcreteCrypto.ElGamalCiphertext out1ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(out1);
|
||||
ConcreteCrypto.ElGamalCiphertext out2ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(out2);
|
||||
return new Statement(in1ElGamal, in2ElGamal, out1ElGamal, out2ElGamal);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
* convert each encrypted message to ElGamalCiphertext
|
||||
*
|
||||
* @throws InvalidProtocolBufferException - in case that at least one of the encrypted messages isn't
|
||||
* ElGamalCiphertext
|
||||
*/
|
||||
protected ProverStatement createProverStatement(Crypto.RerandomizableEncryptedMessage in1, Crypto.RerandomizableEncryptedMessage in2
|
||||
, Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2
|
||||
, Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2, boolean switched)
|
||||
throws InvalidProtocolBufferException {
|
||||
|
||||
//convert RerandomizableEncryptedMessage to ElGamalCiphertext
|
||||
ConcreteCrypto.ElGamalCiphertext in1ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(in1);
|
||||
ConcreteCrypto.ElGamalCiphertext in2ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(in2);
|
||||
ConcreteCrypto.ElGamalCiphertext out1ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(out1);
|
||||
ConcreteCrypto.ElGamalCiphertext out2ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(out2);
|
||||
|
||||
return new ProverStatement(in1ElGamal, in2ElGamal, out1ElGamal, out2ElGamal, r1, r2, switched);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Statement to be proved.
|
||||
*
|
||||
* The actual stored data is a cached representation for use in proofs and verification. This consists of the four substatements that are ORs of the DLOG equality.
|
||||
*
|
||||
* A Statement can be constructed only by calling the {@link #createStatement} factory method on an instance of ECElGamalMixParams (all constructors are private)
|
||||
*
|
||||
*/
|
||||
public class Statement {
|
||||
|
||||
/**
|
||||
* Denote the first ciphertext pair e1=(e1c1,e1c2), e2=(e2c1,e2c2) and the second
|
||||
* e1N=(e1Nc1, e1Nc2) and e2N=(e2Nc1,e2Nc2).
|
||||
* Then ci_ejNDivek = ejNci/ekci
|
||||
*/
|
||||
ECPoint c1_e1NDive1;
|
||||
/**
|
||||
* See {@link #c1_e1NDive1}
|
||||
*/
|
||||
ECPoint c1_e2NDive1;
|
||||
|
||||
/**
|
||||
* See {@link #c1_e1NDive1}
|
||||
*/
|
||||
ECPoint c1_e1NDive2;
|
||||
|
||||
/**
|
||||
* See {@link #c1_e1NDive1}
|
||||
*/
|
||||
ECPoint c1_e2NDive2;
|
||||
|
||||
/**
|
||||
* See {@link #c1_e1NDive1}
|
||||
*/
|
||||
ECPoint c2_e1NDive1;
|
||||
|
||||
/**
|
||||
* See {@link #c1_e1NDive1}
|
||||
*/
|
||||
ECPoint c2_e2NDive1;
|
||||
|
||||
/**
|
||||
* See {@link #c1_e1NDive1}
|
||||
*/
|
||||
ECPoint c2_e1NDive2;
|
||||
|
||||
/**
|
||||
* See {@link #c1_e1NDive1}
|
||||
*/
|
||||
ECPoint c2_e2NDive2;
|
||||
|
||||
|
||||
private final OrStatement orStatements[] = new OrStatement[4];
|
||||
|
||||
|
||||
public OrStatement getOrStatement(int num) {
|
||||
if (orStatements[0] == null)
|
||||
generateOrStatements();
|
||||
|
||||
return orStatements[num];
|
||||
}
|
||||
|
||||
public void setOrStatement(int num, OrStatement orStatement) {
|
||||
orStatements[num] = orStatement;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generate and set the four substatements.
|
||||
*/
|
||||
protected void generateOrStatements() {
|
||||
setOrStatement(0, new OrStatement(c1_e1NDive1,c2_e1NDive1,c1_e1NDive2,c2_e1NDive2));
|
||||
setOrStatement(1, new OrStatement(c1_e1NDive1,c2_e1NDive1,c1_e2NDive1,c2_e2NDive1));
|
||||
setOrStatement(2, new OrStatement(c1_e1NDive2,c2_e1NDive2,c1_e2NDive2,c2_e2NDive2));
|
||||
setOrStatement(3, new OrStatement(c1_e2NDive1,c2_e2NDive1,c1_e2NDive2,c2_e2NDive2));
|
||||
}
|
||||
|
||||
|
||||
private Statement(ConcreteCrypto.ElGamalCiphertext e1, ConcreteCrypto.ElGamalCiphertext e2
|
||||
, ConcreteCrypto.ElGamalCiphertext e1New, ConcreteCrypto.ElGamalCiphertext e2New){
|
||||
|
||||
ECPoint e1c1 = decodeECPoint(e1.getC1());
|
||||
ECPoint e1c2 = decodeECPoint(e1.getC2());
|
||||
ECPoint e2c1 = decodeECPoint(e2.getC1());
|
||||
ECPoint e2c2 = decodeECPoint(e2.getC2());
|
||||
ECPoint e1Nc1 = decodeECPoint(e1New.getC1());
|
||||
ECPoint e1Nc2 = decodeECPoint(e1New.getC2());
|
||||
ECPoint e2Nc1 = decodeECPoint(e2New.getC1());
|
||||
ECPoint e2Nc2 = decodeECPoint(e2New.getC2());
|
||||
|
||||
c1_e1NDive1 = group.add(e1Nc1, group.negate(e1c1));
|
||||
c1_e2NDive1 = group.add(e2Nc1, group.negate(e1c1));
|
||||
c1_e1NDive2 = group.add(e1Nc1, group.negate(e2c1));
|
||||
c1_e2NDive2 = group.add(e2Nc1, group.negate(e2c1));
|
||||
c2_e1NDive1 = group.add(e1Nc2, group.negate(e1c2));
|
||||
c2_e2NDive1 = group.add(e2Nc2, group.negate(e1c2));
|
||||
c2_e1NDive2 = group.add(e1Nc2, group.negate(e2c2));
|
||||
c2_e2NDive2 = group.add(e2Nc2, group.negate(e2c2));
|
||||
}
|
||||
}
|
||||
|
||||
public class ProverStatement extends Statement {
|
||||
/**
|
||||
* True iff the ciphertexts were switched (i.e., decrypt(e1N) == decrypt(e2) and decrypt(e2N) == decrypt(e1)
|
||||
*/
|
||||
boolean switched;
|
||||
|
||||
/**
|
||||
* Encryption randomness for e1 rerandomization
|
||||
*/
|
||||
Crypto.EncryptionRandomness r1;
|
||||
|
||||
/**
|
||||
* Encryption randomnesss for e2 rerandomization
|
||||
*/
|
||||
Crypto.EncryptionRandomness r2;
|
||||
|
||||
@Override
|
||||
protected void generateOrStatements() {
|
||||
byte[] c1_e1NDive1Encoded = group.encode(c1_e1NDive1);
|
||||
byte[] c1_e2NDive1Encoded = group.encode(c1_e2NDive1);
|
||||
byte[] c1_e1NDive2Encoded = group.encode(c1_e1NDive2);
|
||||
byte[] c1_e2NDive2Encoded = group.encode(c1_e2NDive2);
|
||||
byte[] c2_e1NDive1Encoded = group.encode(c2_e1NDive1);
|
||||
byte[] c2_e2NDive1Encoded = group.encode(c2_e2NDive1);
|
||||
byte[] c2_e1NDive2Encoded = group.encode(c2_e1NDive2);
|
||||
byte[] c2_e2NDive2Encoded = group.encode(c2_e2NDive2);
|
||||
|
||||
|
||||
if (!switched) {
|
||||
setOrStatement(0, new OrProverStatement(c1_e1NDive1, c2_e1NDive1, c1_e1NDive2, c2_e1NDive2
|
||||
, c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e1NDive2Encoded, c2_e1NDive2Encoded
|
||||
, r1, TrueCouple.left));
|
||||
setOrStatement(1, new OrProverStatement(c1_e1NDive1, c2_e1NDive1, c1_e2NDive1, c2_e2NDive1
|
||||
, c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e2NDive1Encoded, c2_e2NDive1Encoded
|
||||
, r1, TrueCouple.left));
|
||||
setOrStatement(2, new OrProverStatement(c1_e1NDive2, c2_e1NDive2, c1_e2NDive2, c2_e2NDive2
|
||||
, c1_e1NDive2Encoded, c2_e1NDive2Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded
|
||||
, r2, TrueCouple.right));
|
||||
setOrStatement(3, new OrProverStatement(c1_e2NDive1, c2_e2NDive1, c1_e2NDive2, c2_e2NDive2
|
||||
, c1_e2NDive1Encoded, c2_e2NDive1Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded
|
||||
, r2, TrueCouple.right));
|
||||
} else {
|
||||
setOrStatement(0, new OrProverStatement(c1_e1NDive1, c2_e1NDive1, c1_e1NDive2, c2_e1NDive2
|
||||
, c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e1NDive2Encoded, c2_e1NDive2Encoded
|
||||
, r2, TrueCouple.right));
|
||||
setOrStatement(1, new OrProverStatement(c1_e1NDive1, c2_e1NDive1, c1_e2NDive1, c2_e2NDive1
|
||||
, c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e2NDive1Encoded, c2_e2NDive1Encoded
|
||||
, r1, TrueCouple.right));
|
||||
setOrStatement(2, new OrProverStatement(c1_e1NDive2, c2_e1NDive2, c1_e2NDive2, c2_e2NDive2
|
||||
, c1_e1NDive2Encoded, c2_e1NDive2Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded
|
||||
, r2, TrueCouple.left));
|
||||
setOrStatement(3, new OrProverStatement(c1_e2NDive1, c2_e2NDive1, c1_e2NDive2, c2_e2NDive2
|
||||
, c1_e2NDive1Encoded, c2_e2NDive1Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded
|
||||
, r1, TrueCouple.left));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public OrProverStatement getOrStatement(int num) {
|
||||
OrStatement orStatement = super.getOrStatement(num);
|
||||
if (!(orStatement instanceof OrProverStatement))
|
||||
throw new RuntimeException("ProverStatement should always have OrProverStatement substatements!!");
|
||||
|
||||
return (OrProverStatement) orStatement;
|
||||
}
|
||||
|
||||
private ProverStatement(ConcreteCrypto.ElGamalCiphertext e1, ConcreteCrypto.ElGamalCiphertext e2,
|
||||
ConcreteCrypto.ElGamalCiphertext e1New, ConcreteCrypto.ElGamalCiphertext e2New,
|
||||
Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2, boolean switched) {
|
||||
super(e1, e2, e1New, e2New);
|
||||
this.r1 = r1;
|
||||
this.r2 = r2;
|
||||
this.switched = switched;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The statement of a single disjunction to be proved:
|
||||
* Either there exists x s.t (g1 ^ x == h1 and g2 ^ x == h2) or there exists x s.t. (g1' ^ x == h1 and g2' ^ x == h2)
|
||||
*
|
||||
* The statement can't be constructed externally (all constructors are private)
|
||||
*
|
||||
* 4 instances will be constructed for each new {@link ECElGamalMixParams.Statement}
|
||||
*
|
||||
*/
|
||||
public class OrStatement {
|
||||
public final ECPoint g1;
|
||||
public final ECPoint h1;
|
||||
public final ECPoint g2;
|
||||
public final ECPoint h2;
|
||||
public final ECPoint g1Tag;
|
||||
public final ECPoint h1Tag;
|
||||
public final ECPoint g2Tag;
|
||||
public final ECPoint h2Tag;
|
||||
|
||||
|
||||
/**
|
||||
* used by meerkat.mixer.proofs only
|
||||
*/
|
||||
private OrStatement(ECPoint h1, ECPoint h2, ECPoint h1Tag, ECPoint h2Tag) {
|
||||
this.g1 = g;
|
||||
this.h1 = h1;
|
||||
this.g2 = h;
|
||||
this.h2 = h2;
|
||||
this.g1Tag = g;
|
||||
this.h1Tag = h1Tag;
|
||||
this.g2Tag = h;
|
||||
this.h2Tag = h2Tag;
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class OrProverStatement extends OrStatement {
|
||||
protected final byte[] g1Encoded;
|
||||
protected final byte[] h1Encoded;
|
||||
protected final byte[] g2Encoded;
|
||||
protected final byte[] h2Encoded;
|
||||
protected final byte[] g1TagEncoded;
|
||||
protected final byte[] h1TagEncoded;
|
||||
protected final byte[] g2TagEncoded;
|
||||
protected final byte[] h2TagEncoded;
|
||||
protected final Crypto.EncryptionRandomness x;
|
||||
protected final TrueCouple flag;
|
||||
|
||||
private OrProverStatement(ECPoint h1, ECPoint h2, ECPoint h1Tag, ECPoint h2Tag,
|
||||
byte[] h1Encoded, byte[] h2Encoded, byte[] h1TagEncoded, byte[] h2TagEncoded,
|
||||
Crypto.EncryptionRandomness x, TrueCouple flag) {
|
||||
super(h1, h2, h1Tag, h2Tag);
|
||||
this.g1Encoded = gEncoded;
|
||||
this.h1Encoded = h1Encoded;
|
||||
this.g2Encoded = hEncoded;
|
||||
this.h2Encoded = h2Encoded;
|
||||
this.g1TagEncoded = gEncoded;
|
||||
this.h1TagEncoded = h1TagEncoded;
|
||||
this.g2TagEncoded = hEncoded;
|
||||
this.h2TagEncoded = h2TagEncoded;
|
||||
|
||||
this.x = x;
|
||||
this.flag = flag;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,301 +0,0 @@
|
|||
package meerkat.mixer.proofs;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||
import meerkat.protobuf.ConcreteCrypto;
|
||||
import meerkat.protobuf.Crypto;
|
||||
import org.bouncycastle.math.ec.ECPoint;
|
||||
import org.factcenter.qilin.primitives.concrete.ECGroup;
|
||||
|
||||
/**
|
||||
* use for organize the input for each ZKP
|
||||
*
|
||||
* both meerkat.mixer.proofs and meerkat.mixer.verifier implementation use it
|
||||
*/
|
||||
public class ECElGamalMixProof {
|
||||
|
||||
private final ECGroup group;
|
||||
private final ECPoint g;
|
||||
private final ECPoint h;
|
||||
private final byte[] gEncoded;
|
||||
private final byte[] hEncoded;
|
||||
|
||||
/**
|
||||
* @param group
|
||||
* @param g - generator of group
|
||||
* @param h - h = g ^ SecretKey
|
||||
*/
|
||||
public ECElGamalMixProof(ECGroup group, ECPoint g, ECPoint h){
|
||||
this.group = group;
|
||||
this.g = g;
|
||||
this.h = h;
|
||||
this.gEncoded = group.encode(g);
|
||||
this.hEncoded = group.encode(h);
|
||||
}
|
||||
|
||||
public enum TrueCouple {
|
||||
left, right, unknown
|
||||
}
|
||||
|
||||
/**
|
||||
* can be used by meerkat.mixer.proofs only
|
||||
*
|
||||
* call to the meerkat.mixer.main overload with flag = true
|
||||
*/
|
||||
protected Statement createProofInput(Crypto.RerandomizableEncryptedMessage in1, Crypto.RerandomizableEncryptedMessage in2
|
||||
, Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2
|
||||
, Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2, boolean switched) throws InvalidProtocolBufferException {
|
||||
|
||||
//boolean flag = true;
|
||||
return createProofInput(in1,in2,out1,out2,r1,r2,switched,true);
|
||||
}
|
||||
|
||||
/**
|
||||
* can be used by anyone, e.g meerkat.mixer.verifier
|
||||
*
|
||||
* call to the meerkat.mixer.main overload with flag = false
|
||||
*/
|
||||
public Statement createProofInput(Crypto.RerandomizableEncryptedMessage in1, Crypto.RerandomizableEncryptedMessage in2
|
||||
, Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2) throws InvalidProtocolBufferException {
|
||||
|
||||
// flag = false;
|
||||
return createProofInput(in1,in2,out1,out2,null,null,false,false);
|
||||
}
|
||||
|
||||
/**
|
||||
* inner method
|
||||
* convert each encrypted message to ElGamalCiphertext
|
||||
*
|
||||
* @param flag - true if called by meerkat.mixer.proofs ( r1,r2,switched are known)
|
||||
* @return ElGamalProofInput
|
||||
* @throws InvalidProtocolBufferException - in case that at least one of the encrypted messages isn't
|
||||
* ElGamalCiphertext
|
||||
*/
|
||||
private Statement createProofInput(Crypto.RerandomizableEncryptedMessage in1, Crypto.RerandomizableEncryptedMessage in2
|
||||
, Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2
|
||||
, Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2, boolean switched, boolean flag)
|
||||
throws InvalidProtocolBufferException {
|
||||
|
||||
//convert RerandomizableEncryptedMessage to ElGamalCiphertext
|
||||
ConcreteCrypto.ElGamalCiphertext in1ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(in1);
|
||||
ConcreteCrypto.ElGamalCiphertext in2ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(in2);
|
||||
ConcreteCrypto.ElGamalCiphertext out1ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(out1);
|
||||
ConcreteCrypto.ElGamalCiphertext out2ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(out2);
|
||||
|
||||
if(flag) {
|
||||
return new Statement(in1ElGamal, in2ElGamal, out1ElGamal, out2ElGamal, r1, r2, switched);
|
||||
}else {
|
||||
return new Statement(in1ElGamal, in2ElGamal, out1ElGamal, out2ElGamal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Statement to be proved. The statement consists of the four substatements that are ORs of the DLOG equality.
|
||||
*
|
||||
* This can be constructed only by calling createProofInput method on an instance of ECElGamalMixProof (all constructors are private)
|
||||
*
|
||||
* in construction it is used for preparing the input for proving, while avoiding double converting or calculations
|
||||
*
|
||||
* use as a container for 4 OrProofInput.
|
||||
*/
|
||||
public class Statement {
|
||||
private final OrStatement first;
|
||||
private final OrStatement second;
|
||||
private final OrStatement third;
|
||||
private final OrStatement fourth;
|
||||
|
||||
|
||||
public OrStatement getFirst() {
|
||||
return first;
|
||||
}
|
||||
|
||||
public OrStatement getSecond() {
|
||||
return second;
|
||||
}
|
||||
|
||||
public OrStatement getThird() {
|
||||
return third;
|
||||
}
|
||||
|
||||
public OrStatement getFourth() {
|
||||
return fourth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode from the serialized representation to an {@link ECPoint} object.
|
||||
* @param bs
|
||||
* @return
|
||||
*/
|
||||
private ECPoint decodeECPoint(ByteString bs){
|
||||
return group.decode(bs.toByteArray());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param proving - true if called by meerkat.mixer.proofs ( r1,r2,switched are known)
|
||||
*/
|
||||
private Statement(ConcreteCrypto.ElGamalCiphertext e1, ConcreteCrypto.ElGamalCiphertext e2
|
||||
, ConcreteCrypto.ElGamalCiphertext e1New, ConcreteCrypto.ElGamalCiphertext e2New
|
||||
, Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2, boolean switched, boolean proving){
|
||||
|
||||
ECPoint e1c1 = decodeECPoint(e1.getC1());
|
||||
ECPoint e1c2 = decodeECPoint(e1.getC2());
|
||||
ECPoint e2c1 = decodeECPoint(e2.getC1());
|
||||
ECPoint e2c2 = decodeECPoint(e2.getC2());
|
||||
ECPoint e1Nc1 = decodeECPoint(e1New.getC1());
|
||||
ECPoint e1Nc2 = decodeECPoint(e1New.getC2());
|
||||
ECPoint e2Nc1 = decodeECPoint(e2New.getC1());
|
||||
ECPoint e2Nc2 = decodeECPoint(e2New.getC2());
|
||||
|
||||
ECPoint c1_e1NDive1 = group.add(e1Nc1, group.negate(e1c1));
|
||||
ECPoint c1_e2NDive1 = group.add(e2Nc1, group.negate(e1c1));
|
||||
ECPoint c1_e1NDive2 = group.add(e1Nc1, group.negate(e2c1));
|
||||
ECPoint c1_e2NDive2 = group.add(e2Nc1, group.negate(e2c1));
|
||||
|
||||
ECPoint c2_e1NDive1 = group.add(e1Nc2, group.negate(e1c2));
|
||||
ECPoint c2_e2NDive1 = group.add(e2Nc2, group.negate(e1c2));
|
||||
ECPoint c2_e1NDive2 = group.add(e1Nc2, group.negate(e2c2));
|
||||
ECPoint c2_e2NDive2 = group.add(e2Nc2, group.negate(e2c2));
|
||||
|
||||
|
||||
if(!proving) {
|
||||
this.first = new OrStatement(c1_e1NDive1,c2_e1NDive1,c1_e1NDive2,c2_e1NDive2);
|
||||
this.second = new OrStatement(c1_e1NDive1,c2_e1NDive1,c1_e2NDive1,c2_e2NDive1);
|
||||
this.third = new OrStatement(c1_e1NDive2,c2_e1NDive2,c1_e2NDive2,c2_e2NDive2);
|
||||
this.fourth = new OrStatement(c1_e2NDive1,c2_e2NDive1,c1_e2NDive2,c2_e2NDive2);
|
||||
} else {
|
||||
|
||||
byte[] c1_e1NDive1Encoded = group.encode(c1_e1NDive1);
|
||||
byte[] c1_e2NDive1Encoded = group.encode(c1_e2NDive1);
|
||||
byte[] c1_e1NDive2Encoded = group.encode(c1_e1NDive2);
|
||||
byte[] c1_e2NDive2Encoded = group.encode(c1_e2NDive2);
|
||||
byte[] c2_e1NDive1Encoded = group.encode(c2_e1NDive1);
|
||||
byte[] c2_e2NDive1Encoded = group.encode(c2_e2NDive1);
|
||||
byte[] c2_e1NDive2Encoded = group.encode(c2_e1NDive2);
|
||||
byte[] c2_e2NDive2Encoded = group.encode(c2_e2NDive2);
|
||||
|
||||
|
||||
if (!switched) {
|
||||
this.first = new OrStatement(c1_e1NDive1, c2_e1NDive1, c1_e1NDive2, c2_e1NDive2
|
||||
, c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e1NDive2Encoded, c2_e1NDive2Encoded
|
||||
, r1, TrueCouple.left);
|
||||
this.second = new OrStatement(c1_e1NDive1, c2_e1NDive1, c1_e2NDive1, c2_e2NDive1
|
||||
, c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e2NDive1Encoded, c2_e2NDive1Encoded
|
||||
, r1, TrueCouple.left);
|
||||
this.third = new OrStatement(c1_e1NDive2, c2_e1NDive2, c1_e2NDive2, c2_e2NDive2
|
||||
, c1_e1NDive2Encoded, c2_e1NDive2Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded
|
||||
, r2, TrueCouple.right);
|
||||
this.fourth = new OrStatement(c1_e2NDive1, c2_e2NDive1, c1_e2NDive2, c2_e2NDive2
|
||||
, c1_e2NDive1Encoded, c2_e2NDive1Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded
|
||||
, r2, TrueCouple.right);
|
||||
} else {
|
||||
this.first = new OrStatement(c1_e1NDive1, c2_e1NDive1, c1_e1NDive2, c2_e1NDive2
|
||||
, c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e1NDive2Encoded, c2_e1NDive2Encoded
|
||||
, r2, TrueCouple.right);
|
||||
this.second = new OrStatement(c1_e1NDive1, c2_e1NDive1, c1_e2NDive1, c2_e2NDive1
|
||||
, c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e2NDive1Encoded, c2_e2NDive1Encoded
|
||||
, r1, TrueCouple.right);
|
||||
this.third = new OrStatement(c1_e1NDive2, c2_e1NDive2, c1_e2NDive2, c2_e2NDive2
|
||||
, c1_e1NDive2Encoded, c2_e1NDive2Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded
|
||||
, r2, TrueCouple.left);
|
||||
this.fourth = new OrStatement(c1_e2NDive1, c2_e2NDive1, c1_e2NDive2, c2_e2NDive2
|
||||
, c1_e2NDive1Encoded, c2_e2NDive1Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded
|
||||
, r1, TrueCouple.left);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* used by the meerkat.mixer.proofs
|
||||
* call to the meerkat.mixer.main constructor with proving = true
|
||||
*/
|
||||
private Statement(ConcreteCrypto.ElGamalCiphertext e1, ConcreteCrypto.ElGamalCiphertext e2
|
||||
, ConcreteCrypto.ElGamalCiphertext e1New, ConcreteCrypto.ElGamalCiphertext e2New
|
||||
, Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2, boolean switched){
|
||||
//proving = true;
|
||||
this(e1,e2,e1New,e2New,r1,r2,switched,true);
|
||||
}
|
||||
|
||||
/**
|
||||
* used by meerkat.mixer.proofs
|
||||
* call to the meerkat.mixer.main constructor with proving = false
|
||||
*/
|
||||
private Statement(ConcreteCrypto.ElGamalCiphertext e1, ConcreteCrypto.ElGamalCiphertext e2
|
||||
, ConcreteCrypto.ElGamalCiphertext e1New, ConcreteCrypto.ElGamalCiphertext e2New){
|
||||
//proving = false;
|
||||
this(e1,e2,e1New,e2New,null,null,false,false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The statement of a single disjunction to be proved:
|
||||
* Either there exists x s.t (g1 ^ x == h1 and g2 ^ x == h2) or there exists x s.t. (g1' ^ x == h1 and g2' ^ x == h2)
|
||||
*
|
||||
* The statement can't be constructed externally (all constructors are private)
|
||||
*
|
||||
* 4 instances will be constructed for each new {@link ECElGamalMixProof.Statement}
|
||||
*
|
||||
*/
|
||||
public class OrStatement {
|
||||
public final ECPoint g1;
|
||||
public final ECPoint h1;
|
||||
public final ECPoint g2;
|
||||
public final ECPoint h2;
|
||||
public final ECPoint g1Tag;
|
||||
public final ECPoint h1Tag;
|
||||
public final ECPoint g2Tag;
|
||||
public final ECPoint h2Tag;
|
||||
|
||||
// can be access by meerkat.mixer.proofs only
|
||||
protected final byte[] g1Encoded;
|
||||
protected final byte[] h1Encoded;
|
||||
protected final byte[] g2Encoded;
|
||||
protected final byte[] h2Encoded;
|
||||
protected final byte[] g1TagEncoded;
|
||||
protected final byte[] h1TagEncoded;
|
||||
protected final byte[] g2TagEncoded;
|
||||
protected final byte[] h2TagEncoded;
|
||||
protected final Crypto.EncryptionRandomness x;
|
||||
protected final TrueCouple flag;
|
||||
|
||||
/**
|
||||
* used by meerkat.mixer.proofs only
|
||||
*/
|
||||
private OrStatement(ECPoint h1, ECPoint h2, ECPoint h1Tag, ECPoint h2Tag
|
||||
, byte[] h1Encoded, byte[] h2Encoded, byte[] h1TagEncoded, byte[] h2TagEncoded
|
||||
, Crypto.EncryptionRandomness x, TrueCouple flag) {
|
||||
this.g1 = g;
|
||||
this.h1 = h1;
|
||||
this.g2 = h;
|
||||
this.h2 = h2;
|
||||
this.g1Tag = g;
|
||||
this.h1Tag = h1Tag;
|
||||
this.g2Tag = h;
|
||||
this.h2Tag = h2Tag;
|
||||
|
||||
this.g1Encoded = gEncoded;
|
||||
this.h1Encoded = h1Encoded;
|
||||
this.g2Encoded = hEncoded;
|
||||
this.h2Encoded = h2Encoded;
|
||||
this.g1TagEncoded = gEncoded;
|
||||
this.h1TagEncoded = h1TagEncoded;
|
||||
this.g2TagEncoded = hEncoded;
|
||||
this.h2TagEncoded = h2TagEncoded;
|
||||
|
||||
this.x = x;
|
||||
this.flag = flag;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* used by meerkat.mixer.verifier
|
||||
*/
|
||||
private OrStatement(ECPoint h1, ECPoint h2, ECPoint h1Tag, ECPoint h2Tag) {
|
||||
this(h1,h2,h1Tag,h2Tag,null,null,null,null,null,TrueCouple.unknown);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,7 +26,7 @@ public class Prover implements Mix2ZeroKnowledgeProver {
|
|||
private final ECElGamalEncryption encryptor;
|
||||
private final ECPoint g,h;
|
||||
private final BigInteger groupOrderUpperBound;
|
||||
private final ECElGamalMixProof organizer;
|
||||
private final ECElGamalMixParams organizer;
|
||||
|
||||
/**
|
||||
* @param rand
|
||||
|
@ -41,7 +41,7 @@ public class Prover implements Mix2ZeroKnowledgeProver {
|
|||
this.group = this.encryptor.getGroup();
|
||||
this.g = group.getGenerator();
|
||||
this.h = this.encryptor.getElGamalPK().getPK();
|
||||
this.organizer = new ECElGamalMixProof(group,g,h);
|
||||
this.organizer = new ECElGamalMixParams(group,g,h);
|
||||
this.groupOrderUpperBound = group.orderUpperBound();
|
||||
}
|
||||
|
||||
|
@ -68,12 +68,12 @@ public class Prover implements Mix2ZeroKnowledgeProver {
|
|||
Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException {
|
||||
Mixing.ZeroKnowledgeProof.OrProof first,second,third,fourth;
|
||||
|
||||
ECElGamalMixProof.Statement statement = organizer.createProofInput(in1,in2,out1,out2,r1,r2,sw);
|
||||
ECElGamalMixParams.ProverStatement statement = organizer.createProverStatement(in1,in2,out1,out2,r1,r2,sw);
|
||||
|
||||
first = createOrProofElGamal(statement.getFirst());
|
||||
second = createOrProofElGamal(statement.getSecond());
|
||||
third = createOrProofElGamal(statement.getThird());
|
||||
fourth = createOrProofElGamal(statement.getFourth());
|
||||
first = createOrProofElGamal(statement.getOrStatement(0));
|
||||
second = createOrProofElGamal(statement.getOrStatement(1));
|
||||
third = createOrProofElGamal(statement.getOrStatement(2));
|
||||
fourth = createOrProofElGamal(statement.getOrStatement(3));
|
||||
|
||||
Mixing.ZeroKnowledgeProof.Location location = Mixing.ZeroKnowledgeProof.Location.newBuilder()
|
||||
.setI(i)
|
||||
|
@ -109,7 +109,7 @@ public class Prover implements Mix2ZeroKnowledgeProver {
|
|||
* @return ZKP OrProof: there exists x s.t (g1 ^ x == h1 and g2 ^ x == h2) or (g1' ^ x == h1 and g2' ^ x == h2)
|
||||
* assuming DLog is hard in this.group then that proves x is known for the meerkat.mixer.proofs
|
||||
*/
|
||||
private Mixing.ZeroKnowledgeProof.OrProof createOrProofElGamal(ECElGamalMixProof.OrStatement orStatement) {
|
||||
private Mixing.ZeroKnowledgeProof.OrProof createOrProofElGamal(ECElGamalMixParams.OrProverStatement orStatement) {
|
||||
|
||||
ECPoint g1 = orStatement.g1;
|
||||
ECPoint h1 = orStatement.h1;
|
||||
|
|
|
@ -18,7 +18,7 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier {
|
|||
private final ECGroup group;
|
||||
private final RandomOracle randomOracle;
|
||||
private final ECPoint g,h;
|
||||
private final ECElGamalMixProof organizer;
|
||||
private final ECElGamalMixParams organizer;
|
||||
private final ZeroKnowledgeOrProofParser parser;
|
||||
|
||||
/**
|
||||
|
@ -31,7 +31,7 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier {
|
|||
this.g = group.getGenerator();
|
||||
this.h = encryptor.getElGamalPK().getPK();
|
||||
this.randomOracle = randomOracle;
|
||||
this.organizer = new ECElGamalMixProof(group,g,h);
|
||||
this.organizer = new ECElGamalMixParams(group,g,h);
|
||||
this.parser = new ZeroKnowledgeOrProofParser(group);
|
||||
}
|
||||
|
||||
|
@ -52,11 +52,11 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier {
|
|||
Crypto.RerandomizableEncryptedMessage out1,
|
||||
Crypto.RerandomizableEncryptedMessage out2,
|
||||
Mixing.ZeroKnowledgeProof proof) throws InvalidProtocolBufferException {
|
||||
ECElGamalMixProof.Statement statement = organizer.createProofInput(in1,in2,out1,out2);
|
||||
return verifyElGamaOrProof(statement.getFirst(), proof.getFirst())&&
|
||||
verifyElGamaOrProof(statement.getSecond(), proof.getSecond())&&
|
||||
verifyElGamaOrProof(statement.getThird(), proof.getThird())&&
|
||||
verifyElGamaOrProof(statement.getFourth(), proof.getFourth());
|
||||
ECElGamalMixParams.Statement statement = organizer.createStatement(in1,in2,out1,out2);
|
||||
return verifyElGamaOrProof(statement.getOrStatement(0), proof.getFirst())&&
|
||||
verifyElGamaOrProof(statement.getOrStatement(1), proof.getSecond())&&
|
||||
verifyElGamaOrProof(statement.getOrStatement(2), proof.getThird())&&
|
||||
verifyElGamaOrProof(statement.getOrStatement(3), proof.getFourth());
|
||||
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier {
|
|||
* @param orProof
|
||||
* @return verify single or proof
|
||||
*/
|
||||
private boolean verifyElGamaOrProof(ECElGamalMixProof.OrStatement orStatement,
|
||||
private boolean verifyElGamaOrProof(ECElGamalMixParams.OrStatement orStatement,
|
||||
Mixing.ZeroKnowledgeProof.OrProof orProof) {
|
||||
ZeroKnowledgeOrProofParser.ZeroKnowledgeOrProofContainer container = parser.parseOrProof(orProof);
|
||||
return container.g1.equals(orStatement.g1) &&
|
||||
|
|
Loading…
Reference in New Issue