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 ECElGamalEncryption encryptor;
|
||||||
private final ECPoint g,h;
|
private final ECPoint g,h;
|
||||||
private final BigInteger groupOrderUpperBound;
|
private final BigInteger groupOrderUpperBound;
|
||||||
private final ECElGamalMixProof organizer;
|
private final ECElGamalMixParams organizer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param rand
|
* @param rand
|
||||||
|
@ -41,7 +41,7 @@ public class Prover implements Mix2ZeroKnowledgeProver {
|
||||||
this.group = this.encryptor.getGroup();
|
this.group = this.encryptor.getGroup();
|
||||||
this.g = group.getGenerator();
|
this.g = group.getGenerator();
|
||||||
this.h = this.encryptor.getElGamalPK().getPK();
|
this.h = this.encryptor.getElGamalPK().getPK();
|
||||||
this.organizer = new ECElGamalMixProof(group,g,h);
|
this.organizer = new ECElGamalMixParams(group,g,h);
|
||||||
this.groupOrderUpperBound = group.orderUpperBound();
|
this.groupOrderUpperBound = group.orderUpperBound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,12 +68,12 @@ public class Prover implements Mix2ZeroKnowledgeProver {
|
||||||
Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException {
|
Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException {
|
||||||
Mixing.ZeroKnowledgeProof.OrProof first,second,third,fourth;
|
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());
|
first = createOrProofElGamal(statement.getOrStatement(0));
|
||||||
second = createOrProofElGamal(statement.getSecond());
|
second = createOrProofElGamal(statement.getOrStatement(1));
|
||||||
third = createOrProofElGamal(statement.getThird());
|
third = createOrProofElGamal(statement.getOrStatement(2));
|
||||||
fourth = createOrProofElGamal(statement.getFourth());
|
fourth = createOrProofElGamal(statement.getOrStatement(3));
|
||||||
|
|
||||||
Mixing.ZeroKnowledgeProof.Location location = Mixing.ZeroKnowledgeProof.Location.newBuilder()
|
Mixing.ZeroKnowledgeProof.Location location = Mixing.ZeroKnowledgeProof.Location.newBuilder()
|
||||||
.setI(i)
|
.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)
|
* @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
|
* 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 g1 = orStatement.g1;
|
||||||
ECPoint h1 = orStatement.h1;
|
ECPoint h1 = orStatement.h1;
|
||||||
|
|
|
@ -18,7 +18,7 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier {
|
||||||
private final ECGroup group;
|
private final ECGroup group;
|
||||||
private final RandomOracle randomOracle;
|
private final RandomOracle randomOracle;
|
||||||
private final ECPoint g,h;
|
private final ECPoint g,h;
|
||||||
private final ECElGamalMixProof organizer;
|
private final ECElGamalMixParams organizer;
|
||||||
private final ZeroKnowledgeOrProofParser parser;
|
private final ZeroKnowledgeOrProofParser parser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,7 +31,7 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier {
|
||||||
this.g = group.getGenerator();
|
this.g = group.getGenerator();
|
||||||
this.h = encryptor.getElGamalPK().getPK();
|
this.h = encryptor.getElGamalPK().getPK();
|
||||||
this.randomOracle = randomOracle;
|
this.randomOracle = randomOracle;
|
||||||
this.organizer = new ECElGamalMixProof(group,g,h);
|
this.organizer = new ECElGamalMixParams(group,g,h);
|
||||||
this.parser = new ZeroKnowledgeOrProofParser(group);
|
this.parser = new ZeroKnowledgeOrProofParser(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,11 +52,11 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier {
|
||||||
Crypto.RerandomizableEncryptedMessage out1,
|
Crypto.RerandomizableEncryptedMessage out1,
|
||||||
Crypto.RerandomizableEncryptedMessage out2,
|
Crypto.RerandomizableEncryptedMessage out2,
|
||||||
Mixing.ZeroKnowledgeProof proof) throws InvalidProtocolBufferException {
|
Mixing.ZeroKnowledgeProof proof) throws InvalidProtocolBufferException {
|
||||||
ECElGamalMixProof.Statement statement = organizer.createProofInput(in1,in2,out1,out2);
|
ECElGamalMixParams.Statement statement = organizer.createStatement(in1,in2,out1,out2);
|
||||||
return verifyElGamaOrProof(statement.getFirst(), proof.getFirst())&&
|
return verifyElGamaOrProof(statement.getOrStatement(0), proof.getFirst())&&
|
||||||
verifyElGamaOrProof(statement.getSecond(), proof.getSecond())&&
|
verifyElGamaOrProof(statement.getOrStatement(1), proof.getSecond())&&
|
||||||
verifyElGamaOrProof(statement.getThird(), proof.getThird())&&
|
verifyElGamaOrProof(statement.getOrStatement(2), proof.getThird())&&
|
||||||
verifyElGamaOrProof(statement.getFourth(), proof.getFourth());
|
verifyElGamaOrProof(statement.getOrStatement(3), proof.getFourth());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier {
|
||||||
* @param orProof
|
* @param orProof
|
||||||
* @return verify single or proof
|
* @return verify single or proof
|
||||||
*/
|
*/
|
||||||
private boolean verifyElGamaOrProof(ECElGamalMixProof.OrStatement orStatement,
|
private boolean verifyElGamaOrProof(ECElGamalMixParams.OrStatement orStatement,
|
||||||
Mixing.ZeroKnowledgeProof.OrProof orProof) {
|
Mixing.ZeroKnowledgeProof.OrProof orProof) {
|
||||||
ZeroKnowledgeOrProofParser.ZeroKnowledgeOrProofContainer container = parser.parseOrProof(orProof);
|
ZeroKnowledgeOrProofParser.ZeroKnowledgeOrProofContainer container = parser.parseOrProof(orProof);
|
||||||
return container.g1.equals(orStatement.g1) &&
|
return container.g1.equals(orStatement.g1) &&
|
||||||
|
|
Loading…
Reference in New Issue