Yet more mixer refactoring
parent
5b268cd779
commit
aac7a50a94
|
@ -80,6 +80,45 @@ public class ECElGamalEncryption implements Encryption {
|
|||
elGamalPK = new ECElGamal.PK(group, ((ECPublicKeyParameters) keyParam).getQ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a group element into a protobuf.
|
||||
* @param p
|
||||
* @return
|
||||
*/
|
||||
public ConcreteCrypto.GroupElement encodeElement(ECPoint p) {
|
||||
return encodeElement(group, p);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encode a group element into a protobuf.
|
||||
*
|
||||
* @param group group to use for encoding
|
||||
* @param p element to encode.
|
||||
* @return
|
||||
*/
|
||||
public static ConcreteCrypto.GroupElement encodeElement(ECGroup group, ECPoint p) {
|
||||
return ConcreteCrypto.GroupElement.newBuilder().setData(ByteString.copyFrom(p.getEncoded(true))).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode from the serialized representation to an {@link ECPoint} object.
|
||||
* @param bs
|
||||
* @return
|
||||
*/
|
||||
public ECPoint decodeElement(ConcreteCrypto.GroupElement bs) {
|
||||
return decodeElement(group, bs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode from the serialized representation to an {@link ECPoint} object.
|
||||
* @param group group to use for decoding.
|
||||
* @param bs
|
||||
* @return
|
||||
*/
|
||||
public static ECPoint decodeElement(ECGroup group, ConcreteCrypto.GroupElement bs) {
|
||||
return group.decode(bs.getData().toByteArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Crypto.RerandomizableEncryptedMessage encrypt(Message plaintext, Crypto.EncryptionRandomness rnd) {
|
||||
|
@ -95,11 +134,11 @@ public class ECElGamalEncryption implements Encryption {
|
|||
byte[] msg = out.toByteArray();
|
||||
ECPoint encodedMsg = group.injectiveEncode(msg, new PRGRandom(msg));
|
||||
|
||||
BigInteger rndInt = BigIntegers.fromUnsignedByteArray(rnd.getData().toByteArray());
|
||||
BigInteger rndInt = extractRandomness(rnd);
|
||||
Pair<ECPoint,ECPoint> cipherText = elGamalPK.encrypt(encodedMsg, rndInt);
|
||||
ConcreteCrypto.ElGamalCiphertext encodedCipherText = ConcreteCrypto.ElGamalCiphertext.newBuilder()
|
||||
.setC1(ByteString.copyFrom(cipherText.a.getEncoded(true)))
|
||||
.setC2(ByteString.copyFrom(cipherText.b.getEncoded(true)))
|
||||
.setC1(encodeElement(cipherText.a))
|
||||
.setC2(encodeElement(cipherText.b))
|
||||
.build();
|
||||
|
||||
return Crypto.RerandomizableEncryptedMessage.newBuilder()
|
||||
|
@ -118,34 +157,49 @@ public class ECElGamalEncryption implements Encryption {
|
|||
|
||||
@Override
|
||||
public Crypto.RerandomizableEncryptedMessage rerandomize(Crypto.RerandomizableEncryptedMessage msg, Crypto.EncryptionRandomness rnd) throws InvalidProtocolBufferException {
|
||||
BigInteger rndInt = BigIntegers.fromUnsignedByteArray(rnd.getData().toByteArray());
|
||||
BigInteger rndInt = extractRandomness(rnd);
|
||||
Pair<ECPoint,ECPoint> randomizer = elGamalPK.encrypt(curve.getInfinity(), rndInt);
|
||||
ConcreteCrypto.ElGamalCiphertext originalEncodedCipher= ConcreteCrypto.ElGamalCiphertext.parseFrom(msg.getData());
|
||||
|
||||
Pair<ECPoint,ECPoint> originalCipher = new Pair<ECPoint, ECPoint>(
|
||||
curve.decodePoint(originalEncodedCipher.getC1().toByteArray()),
|
||||
curve.decodePoint(originalEncodedCipher.getC2().toByteArray()));
|
||||
decodeElement(originalEncodedCipher.getC1()),
|
||||
decodeElement(originalEncodedCipher.getC2()));
|
||||
Pair<ECPoint,ECPoint> newCipher = elGamalPK.add(originalCipher, randomizer);
|
||||
|
||||
return Crypto.RerandomizableEncryptedMessage.newBuilder()
|
||||
.setData(
|
||||
ConcreteCrypto.ElGamalCiphertext.newBuilder()
|
||||
.setC1(ByteString.copyFrom(newCipher.a.getEncoded(true)))
|
||||
.setC2(ByteString.copyFrom(newCipher.b.getEncoded(true)))
|
||||
.setC1(encodeElement(newCipher.a))
|
||||
.setC2(encodeElement(newCipher.b))
|
||||
.build().toByteString()
|
||||
).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Crypto.EncryptionRandomness generateRandomness(Random rand) {
|
||||
BigInteger randomInt = new BigInteger(group.getCurveParams().getN().bitLength() - 1, rand);
|
||||
BigInteger randomInt = generateRandomExponent(rand);
|
||||
Crypto.EncryptionRandomness retval = Crypto.EncryptionRandomness.newBuilder()
|
||||
.setData(ByteString.copyFrom(BigIntegers.asUnsignedByteArray(randomInt))).build();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the discrete log of a random element in the group (i.e., a random value in Z_{groupOrder})
|
||||
* @param rand
|
||||
* @return
|
||||
*/
|
||||
public BigInteger generateRandomExponent(Random rand) {
|
||||
return new BigInteger(group.getCurveParams().getN().bitLength() - 1, rand);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract (deserialize) the random exponent from a {@link Crypto.EncryptionRandomness} protobuf.
|
||||
*
|
||||
* @param encryptionRandomness
|
||||
* @return
|
||||
*/
|
||||
public BigInteger extractRandomness(Crypto.EncryptionRandomness encryptionRandomness){
|
||||
return new BigInteger(1,encryptionRandomness.getData().toByteArray());
|
||||
return BigIntegers.fromUnsignedByteArray(encryptionRandomness.getData().toByteArray());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package meerkat.crypto.concrete;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import meerkat.protobuf.Crypto;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Created by talm on 02/11/16.
|
||||
*/
|
||||
public class Util {
|
||||
/**
|
||||
* Decode a BigInteger from a protobuf
|
||||
* @param i
|
||||
* @return
|
||||
*/
|
||||
public static BigInteger decodeBigInteger(Crypto.BigInteger i) {
|
||||
return new BigInteger(i.getData().toByteArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a BigInteger in a protobuf.
|
||||
* @param i
|
||||
* @return
|
||||
*/
|
||||
public static Crypto.BigInteger encodeBigInteger(BigInteger i) {
|
||||
return Crypto.BigInteger.newBuilder().setData(ByteString.copyFrom(i.toByteArray())).build();
|
||||
}
|
||||
}
|
|
@ -14,9 +14,13 @@ message ElGamalPublicKey {
|
|||
bytes subject_public_key_info = 1;
|
||||
}
|
||||
|
||||
// An El-Gamal ciphertext
|
||||
// Each group element should be an ASN.1 encoded curve point with compression.
|
||||
message GroupElement {
|
||||
bytes data = 1;
|
||||
}
|
||||
|
||||
// An El-Gamal ciphertext
|
||||
message ElGamalCiphertext {
|
||||
bytes c1 = 1; // First group element
|
||||
bytes c2 = 2; // Second group element
|
||||
GroupElement c1 = 1; // First group element
|
||||
GroupElement c2 = 2; // Second group element
|
||||
}
|
|
@ -5,49 +5,51 @@ package meerkat;
|
|||
option java_package = "meerkat.protobuf";
|
||||
|
||||
import 'meerkat/crypto.proto';
|
||||
import 'meerkat/concrete_crypto.proto';
|
||||
|
||||
message Plaintext{
|
||||
message Plaintext {
|
||||
bytes data = 1;
|
||||
}
|
||||
|
||||
message ZeroKnowledgeProof {
|
||||
message OrProof {
|
||||
message ForRandomOracle{
|
||||
bytes g1 = 1;
|
||||
bytes h1 = 2;
|
||||
bytes g2 = 3;
|
||||
bytes h2 = 4;
|
||||
bytes g1Tag = 5;
|
||||
bytes h1Tag = 6;
|
||||
bytes g2Tag = 7;
|
||||
bytes h2Tag = 8;
|
||||
bytes u = 9;
|
||||
bytes v = 10;
|
||||
bytes uTag = 11;
|
||||
bytes vTag = 12;
|
||||
message FirstMessage {
|
||||
GroupElement g1 = 1;
|
||||
GroupElement h1 = 2;
|
||||
GroupElement g2 = 3;
|
||||
GroupElement h2 = 4;
|
||||
GroupElement g1Tag = 5;
|
||||
GroupElement h1Tag = 6;
|
||||
GroupElement g2Tag = 7;
|
||||
GroupElement h2Tag = 8;
|
||||
GroupElement u = 9;
|
||||
GroupElement v = 10;
|
||||
GroupElement uTag = 11;
|
||||
GroupElement vTag = 12;
|
||||
}
|
||||
//input : g1,h1, g2, h2, g1Tag, h1Tag, g2Tag, h2Tag;
|
||||
bytes g1 = 1;
|
||||
bytes h1 = 2;
|
||||
bytes g2 = 3;
|
||||
bytes h2 = 4;
|
||||
bytes g1Tag = 5;
|
||||
bytes h1Tag = 6;
|
||||
bytes g2Tag = 7;
|
||||
bytes h2Tag = 8;
|
||||
//statement parameters : g1,h1, g2, h2, g1Tag, h1Tag, g2Tag, h2Tag;
|
||||
GroupElement g1 = 1;
|
||||
GroupElement h1 = 2;
|
||||
GroupElement g2 = 3;
|
||||
GroupElement h2 = 4;
|
||||
GroupElement g1Tag = 5;
|
||||
GroupElement h1Tag = 6;
|
||||
GroupElement g2Tag = 7;
|
||||
GroupElement h2Tag = 8;
|
||||
|
||||
//calc: u, v, uTag, vTag;
|
||||
bytes u = 9;
|
||||
bytes v = 10;
|
||||
bytes uTag = 11;
|
||||
bytes vTag = 12;
|
||||
GroupElement u = 9;
|
||||
GroupElement v = 10;
|
||||
GroupElement uTag = 11;
|
||||
GroupElement vTag = 12;
|
||||
|
||||
//generated: c1,c2,z,zTag
|
||||
bytes c1 = 13;
|
||||
bytes c2 = 14;
|
||||
bytes z = 15;
|
||||
bytes zTag = 16;
|
||||
BigInteger c1 = 13;
|
||||
BigInteger c2 = 14;
|
||||
BigInteger z = 15;
|
||||
BigInteger zTag = 16;
|
||||
}
|
||||
|
||||
message Location{
|
||||
int32 i = 1;
|
||||
int32 j = 2;
|
||||
|
|
|
@ -15,33 +15,26 @@ import org.factcenter.qilin.primitives.concrete.ECGroup;
|
|||
*/
|
||||
public class ECElGamalMixParams {
|
||||
|
||||
private final ECElGamalEncryption encryptor;
|
||||
private final ECGroup group;
|
||||
private final ECPoint g;
|
||||
private final ECPoint h;
|
||||
private final byte[] gEncoded;
|
||||
private final byte[] hEncoded;
|
||||
|
||||
// Cache encoded formats to save multiple re-encodings
|
||||
private final ConcreteCrypto.GroupElement gEncoded;
|
||||
private final ConcreteCrypto.GroupElement hEncoded;
|
||||
|
||||
/**
|
||||
* Decode from the serialized representation to an {@link ECPoint} object.
|
||||
* @param bs
|
||||
* @return
|
||||
* @param encryptor encryptor used for encoding/decoding serialized ciphertexts. The group, default generator and
|
||||
* second base (h) are taken from the encryptor (second base is the public key)
|
||||
*/
|
||||
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 ECElGamalMixParams(ECElGamalEncryption encryptor){
|
||||
this.encryptor = encryptor;
|
||||
this.group = encryptor.getGroup();
|
||||
this.g = group.getGenerator();
|
||||
this.h = encryptor.getElGamalPK().getPK();
|
||||
this.gEncoded = encryptor.encodeElement(g);
|
||||
this.hEncoded = encryptor.encodeElement(h);
|
||||
}
|
||||
|
||||
public enum TrueCouple {
|
||||
|
@ -165,17 +158,17 @@ public class ECElGamalMixParams {
|
|||
}
|
||||
|
||||
|
||||
private Statement(ConcreteCrypto.ElGamalCiphertext e1, ConcreteCrypto.ElGamalCiphertext e2
|
||||
, ConcreteCrypto.ElGamalCiphertext e1New, ConcreteCrypto.ElGamalCiphertext e2New){
|
||||
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());
|
||||
ECPoint e1c1 = encryptor.decodeElement(e1.getC1());
|
||||
ECPoint e1c2 = encryptor.decodeElement(e1.getC2());
|
||||
ECPoint e2c1 = encryptor.decodeElement(e2.getC1());
|
||||
ECPoint e2c2 = encryptor.decodeElement(e2.getC2());
|
||||
ECPoint e1Nc1 = encryptor.decodeElement(e1New.getC1());
|
||||
ECPoint e1Nc2 = encryptor.decodeElement(e1New.getC2());
|
||||
ECPoint e2Nc1 = encryptor.decodeElement(e2New.getC1());
|
||||
ECPoint e2Nc2 = encryptor.decodeElement(e2New.getC2());
|
||||
|
||||
c1_e1NDive1 = group.add(e1Nc1, group.negate(e1c1));
|
||||
c1_e2NDive1 = group.add(e2Nc1, group.negate(e1c1));
|
||||
|
@ -188,6 +181,9 @@ public class ECElGamalMixParams {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A statement with additional witness information that enables us to generate a ZK proof.
|
||||
*/
|
||||
public class ProverStatement extends Statement {
|
||||
/**
|
||||
* True iff the ciphertexts were switched (i.e., decrypt(e1N) == decrypt(e2) and decrypt(e2N) == decrypt(e1)
|
||||
|
@ -206,14 +202,14 @@ public class ECElGamalMixParams {
|
|||
|
||||
@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);
|
||||
ConcreteCrypto.GroupElement c1_e1NDive1Encoded = encryptor.encodeElement(c1_e1NDive1);
|
||||
ConcreteCrypto.GroupElement c1_e2NDive1Encoded = encryptor.encodeElement(c1_e2NDive1);
|
||||
ConcreteCrypto.GroupElement c1_e1NDive2Encoded = encryptor.encodeElement(c1_e1NDive2);
|
||||
ConcreteCrypto.GroupElement c1_e2NDive2Encoded = encryptor.encodeElement(c1_e2NDive2);
|
||||
ConcreteCrypto.GroupElement c2_e1NDive1Encoded = encryptor.encodeElement(c2_e1NDive1);
|
||||
ConcreteCrypto.GroupElement c2_e2NDive1Encoded = encryptor.encodeElement(c2_e2NDive1);
|
||||
ConcreteCrypto.GroupElement c2_e1NDive2Encoded = encryptor.encodeElement(c2_e1NDive2);
|
||||
ConcreteCrypto.GroupElement c2_e2NDive2Encoded = encryptor.encodeElement(c2_e2NDive2);
|
||||
|
||||
|
||||
if (!switched) {
|
||||
|
@ -304,20 +300,29 @@ public class ECElGamalMixParams {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An {@link OrStatement} with additional info needed to generate a ZK proof.
|
||||
*/
|
||||
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;
|
||||
|
||||
// We cache the encoded versions since we need them as input to the random oracle
|
||||
// when using the Fiat-Shamir heuristic.
|
||||
|
||||
protected final ConcreteCrypto.GroupElement g1Encoded;
|
||||
protected final ConcreteCrypto.GroupElement h1Encoded;
|
||||
protected final ConcreteCrypto.GroupElement g2Encoded;
|
||||
protected final ConcreteCrypto.GroupElement h2Encoded;
|
||||
|
||||
protected final ConcreteCrypto.GroupElement g1TagEncoded;
|
||||
protected final ConcreteCrypto.GroupElement h1TagEncoded;
|
||||
protected final ConcreteCrypto.GroupElement g2TagEncoded;
|
||||
protected final ConcreteCrypto.GroupElement h2TagEncoded;
|
||||
|
||||
private OrProverStatement(ECPoint h1, ECPoint h2, ECPoint h1Tag, ECPoint h2Tag,
|
||||
byte[] h1Encoded, byte[] h2Encoded, byte[] h1TagEncoded, byte[] h2TagEncoded,
|
||||
ConcreteCrypto.GroupElement h1Encoded, ConcreteCrypto.GroupElement h2Encoded, ConcreteCrypto.GroupElement h1TagEncoded, ConcreteCrypto.GroupElement h2TagEncoded,
|
||||
Crypto.EncryptionRandomness x, TrueCouple flag) {
|
||||
super(h1, h2, h1Tag, h2Tag);
|
||||
this.g1Encoded = gEncoded;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package meerkat.mixer.proofs;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||
import meerkat.crypto.concrete.Util;
|
||||
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver;
|
||||
import meerkat.protobuf.Crypto;
|
||||
import meerkat.protobuf.Mixing;
|
||||
|
@ -26,14 +26,14 @@ public class Prover implements Mix2ZeroKnowledgeProver {
|
|||
private final ECElGamalEncryption encryptor;
|
||||
private final ECPoint g,h;
|
||||
private final BigInteger groupOrderUpperBound;
|
||||
private final ECElGamalMixParams organizer;
|
||||
private final ECElGamalMixParams mixParams;
|
||||
|
||||
/**
|
||||
* @param rand
|
||||
* @param encryptor
|
||||
* @param randomOracle - use for Fiat–Shamir heuristic
|
||||
*/
|
||||
public Prover(Random rand,ECElGamalEncryption encryptor,RandomOracle randomOracle) {
|
||||
public Prover(Random rand, ECElGamalEncryption encryptor, RandomOracle randomOracle) {
|
||||
|
||||
this.rand = rand;
|
||||
this.encryptor = encryptor;
|
||||
|
@ -41,16 +41,16 @@ public class Prover implements Mix2ZeroKnowledgeProver {
|
|||
this.group = this.encryptor.getGroup();
|
||||
this.g = group.getGenerator();
|
||||
this.h = this.encryptor.getElGamalPK().getPK();
|
||||
this.organizer = new ECElGamalMixParams(group,g,h);
|
||||
this.mixParams = new ECElGamalMixParams(encryptor);
|
||||
this.groupOrderUpperBound = group.orderUpperBound();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param in1
|
||||
* @param in2
|
||||
* @param out1 - if sw then out1 = rerandomize(in2,r2) else out1 = rerandomize(in1,r1)
|
||||
* @param out2 - if sw then out2 = rerandomize(in1,r1) else out1 = rerandomize(in2,r2)
|
||||
* @param sw - flag
|
||||
* @param out1 - if switched then out1 = rerandomize(in2,r2) else out1 = rerandomize(in1,r1)
|
||||
* @param out2 - if switched then out2 = rerandomize(in1,r1) else out1 = rerandomize(in2,r2)
|
||||
* @param switched - flag
|
||||
* @param i - column of in1 and out1 in encryption table
|
||||
* @param j - column of in2 and out2 in encryption table
|
||||
* @param layer - row of in1,in2 in encryption table
|
||||
|
@ -63,17 +63,17 @@ public class Prover implements Mix2ZeroKnowledgeProver {
|
|||
Crypto.RerandomizableEncryptedMessage in2,
|
||||
Crypto.RerandomizableEncryptedMessage out1,
|
||||
Crypto.RerandomizableEncryptedMessage out2,
|
||||
boolean sw,int i,int j, int layer,
|
||||
boolean switched,int i,int j, int layer,
|
||||
Crypto.EncryptionRandomness r1,
|
||||
Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException {
|
||||
Mixing.ZeroKnowledgeProof.OrProof first,second,third,fourth;
|
||||
|
||||
ECElGamalMixParams.ProverStatement statement = organizer.createProverStatement(in1,in2,out1,out2,r1,r2,sw);
|
||||
ECElGamalMixParams.ProverStatement statement = mixParams.createProverStatement(in1,in2,out1,out2,r1,r2,switched);
|
||||
|
||||
first = createOrProofElGamal(statement.getOrStatement(0));
|
||||
second = createOrProofElGamal(statement.getOrStatement(1));
|
||||
third = createOrProofElGamal(statement.getOrStatement(2));
|
||||
fourth = createOrProofElGamal(statement.getOrStatement(3));
|
||||
first = createOrProof(statement.getOrStatement(0));
|
||||
second = createOrProof(statement.getOrStatement(1));
|
||||
third = createOrProof(statement.getOrStatement(2));
|
||||
fourth = createOrProof(statement.getOrStatement(3));
|
||||
|
||||
Mixing.ZeroKnowledgeProof.Location location = Mixing.ZeroKnowledgeProof.Location.newBuilder()
|
||||
.setI(i)
|
||||
|
@ -98,18 +98,28 @@ public class Prover implements Mix2ZeroKnowledgeProver {
|
|||
* @param randomOracle
|
||||
* @return randomOracle.hash(input)
|
||||
*/
|
||||
public static BigInteger hash(Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle input, RandomOracle randomOracle) {
|
||||
public static BigInteger hash(Mixing.ZeroKnowledgeProof.OrProof.FirstMessage input, RandomOracle randomOracle) {
|
||||
byte[] arr = input.toByteArray();
|
||||
return new BigInteger(1,randomOracle.hash(arr,arr.length));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate a ZK proof that there exists x s.t (g1 ^ x == h1 and g2 ^ x == h2) or (g1' ^ x == h1 and g2' ^ x == h2).
|
||||
*
|
||||
* For each clause of the disjunction, we use the following sigma-protocol for DLOG equality (i.e. log_{g1}(h1)==log_{g1}(h2)):
|
||||
* <ol>
|
||||
* <li>Prover chooses a random r, and sends g1^r, g2^r </li>
|
||||
* <li>Verifier chooses a random c and sends c</li>
|
||||
* <li>Prover computes </li>
|
||||
* </ol>
|
||||
*
|
||||
*
|
||||
* @param orStatement
|
||||
* @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:
|
||||
* assuming DLog is hard in this.group then that proves x is known for the meerkat.mixer.proofs
|
||||
*/
|
||||
private Mixing.ZeroKnowledgeProof.OrProof createOrProofElGamal(ECElGamalMixParams.OrProverStatement orStatement) {
|
||||
private Mixing.ZeroKnowledgeProof.OrProof createOrProof(ECElGamalMixParams.OrProverStatement orStatement) {
|
||||
|
||||
ECPoint g1 = orStatement.g1;
|
||||
ECPoint h1 = orStatement.h1;
|
||||
|
@ -121,16 +131,19 @@ public class Prover implements Mix2ZeroKnowledgeProver {
|
|||
ECPoint g2Tag = orStatement.g2Tag;
|
||||
ECPoint h2Tag = orStatement.h2Tag;
|
||||
|
||||
BigInteger r = encryptor.extractRandomness(encryptor.generateRandomness(rand)).mod(groupOrderUpperBound);
|
||||
// Randomness for the ZK proof
|
||||
BigInteger r = encryptor.generateRandomExponent(rand);
|
||||
|
||||
|
||||
BigInteger c1,c2,z,zTag;
|
||||
ECPoint u,v,uTag,vTag;
|
||||
Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle;
|
||||
Mixing.ZeroKnowledgeProof.OrProof.FirstMessage firstMessage;
|
||||
|
||||
|
||||
switch (orStatement.flag) {
|
||||
case left:
|
||||
c2 = encryptor.extractRandomness(encryptor.generateRandomness(rand)).mod(groupOrderUpperBound);
|
||||
zTag = encryptor.extractRandomness(encryptor.generateRandomness(rand)).mod(groupOrderUpperBound);
|
||||
c2 = encryptor.generateRandomExponent(rand);
|
||||
zTag = encryptor.generateRandomExponent(rand);
|
||||
//step 1
|
||||
u = group.multiply(g1, r);
|
||||
v = group.multiply(g2, r);
|
||||
|
@ -138,29 +151,29 @@ public class Prover implements Mix2ZeroKnowledgeProver {
|
|||
vTag = group.add(group.multiply(g2Tag, zTag), group.negate(group.multiply(h2Tag, c2)));
|
||||
//step 2
|
||||
// c1 = (hash(input + step1) + group size - c2)% group size
|
||||
forRandomOracle =
|
||||
Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle.newBuilder()
|
||||
.setG1(ByteString.copyFrom(orStatement.g1Encoded))
|
||||
.setH1(ByteString.copyFrom(orStatement.h1Encoded))
|
||||
.setG2(ByteString.copyFrom(orStatement.g2Encoded))
|
||||
.setH2(ByteString.copyFrom(orStatement.h2Encoded))
|
||||
.setG1Tag(ByteString.copyFrom(orStatement.g1TagEncoded))
|
||||
.setH1Tag(ByteString.copyFrom(orStatement.h1TagEncoded))
|
||||
.setG2Tag(ByteString.copyFrom(orStatement.g2TagEncoded))
|
||||
.setH2Tag(ByteString.copyFrom(orStatement.h2TagEncoded))
|
||||
.setU(ByteString.copyFrom(group.encode(u)))
|
||||
.setV(ByteString.copyFrom(group.encode(v)))
|
||||
.setUTag(ByteString.copyFrom(group.encode(uTag)))
|
||||
.setVTag(ByteString.copyFrom(group.encode(vTag)))
|
||||
firstMessage =
|
||||
Mixing.ZeroKnowledgeProof.OrProof.FirstMessage.newBuilder()
|
||||
.setG1(orStatement.g1Encoded)
|
||||
.setH1(orStatement.h1Encoded)
|
||||
.setG2(orStatement.g2Encoded)
|
||||
.setH2(orStatement.h2Encoded)
|
||||
.setG1Tag(orStatement.g1TagEncoded)
|
||||
.setH1Tag(orStatement.h1TagEncoded)
|
||||
.setG2Tag(orStatement.g2TagEncoded)
|
||||
.setH2Tag(orStatement.h2TagEncoded)
|
||||
.setU(encryptor.encodeElement(u))
|
||||
.setV(encryptor.encodeElement(v))
|
||||
.setUTag(encryptor.encodeElement(uTag))
|
||||
.setVTag(encryptor.encodeElement(vTag))
|
||||
.build();
|
||||
c1 = hash(forRandomOracle,randomOracle).add(group.orderUpperBound().subtract(c2)).mod(groupOrderUpperBound);
|
||||
c1 = hash(firstMessage,randomOracle).add(group.orderUpperBound().subtract(c2)).mod(groupOrderUpperBound);
|
||||
//step 3
|
||||
//z = (r + c1 * x) % group size;
|
||||
z = r.add(c1.multiply(encryptor.extractRandomness(orStatement.x))).mod(groupOrderUpperBound);
|
||||
break;
|
||||
case right:
|
||||
c1 = encryptor.extractRandomness(encryptor.generateRandomness(rand)).mod(groupOrderUpperBound);
|
||||
z = encryptor.extractRandomness(encryptor.generateRandomness(rand)).mod(groupOrderUpperBound);
|
||||
c1 = encryptor.generateRandomExponent(rand);
|
||||
z = encryptor.generateRandomExponent(rand);
|
||||
//step 1
|
||||
uTag = group.multiply(g1Tag, r);
|
||||
vTag = group.multiply(g2Tag, r);
|
||||
|
@ -168,22 +181,22 @@ public class Prover implements Mix2ZeroKnowledgeProver {
|
|||
v = group.add(group.multiply(g2, z), group.negate(group.multiply(h2, c1)));
|
||||
//step 2
|
||||
// c1 = (hash(input + step1) + group size - c1)% group size
|
||||
forRandomOracle =
|
||||
Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle.newBuilder()
|
||||
.setG1(ByteString.copyFrom(orStatement.g1Encoded))
|
||||
.setH1(ByteString.copyFrom(orStatement.h1Encoded))
|
||||
.setG2(ByteString.copyFrom(orStatement.g2Encoded))
|
||||
.setH2(ByteString.copyFrom(orStatement.h2Encoded))
|
||||
.setG1Tag(ByteString.copyFrom(orStatement.g1TagEncoded))
|
||||
.setH1Tag(ByteString.copyFrom(orStatement.h1TagEncoded))
|
||||
.setG2Tag(ByteString.copyFrom(orStatement.g2TagEncoded))
|
||||
.setH2Tag(ByteString.copyFrom(orStatement.h2TagEncoded))
|
||||
.setU(ByteString.copyFrom(group.encode(u)))
|
||||
.setV(ByteString.copyFrom(group.encode(v)))
|
||||
.setUTag(ByteString.copyFrom(group.encode(uTag)))
|
||||
.setVTag(ByteString.copyFrom(group.encode(vTag)))
|
||||
firstMessage =
|
||||
Mixing.ZeroKnowledgeProof.OrProof.FirstMessage.newBuilder()
|
||||
.setG1(orStatement.g1Encoded)
|
||||
.setH1(orStatement.h1Encoded)
|
||||
.setG2(orStatement.g2Encoded)
|
||||
.setH2(orStatement.h2Encoded)
|
||||
.setG1Tag(orStatement.g1TagEncoded)
|
||||
.setH1Tag(orStatement.h1TagEncoded)
|
||||
.setG2Tag(orStatement.g2TagEncoded)
|
||||
.setH2Tag(orStatement.h2TagEncoded)
|
||||
.setU(encryptor.encodeElement(u))
|
||||
.setV(encryptor.encodeElement(v))
|
||||
.setUTag(encryptor.encodeElement(uTag))
|
||||
.setVTag(encryptor.encodeElement(vTag))
|
||||
.build();
|
||||
c2 = hash(forRandomOracle,randomOracle).add(group.orderUpperBound().subtract(c1)).mod(groupOrderUpperBound);
|
||||
c2 = hash(firstMessage,randomOracle).add(group.orderUpperBound().subtract(c1)).mod(groupOrderUpperBound);
|
||||
//step 3
|
||||
//zTag = (r + c2 * x) % group size;
|
||||
zTag = r.add(c2.multiply(encryptor.extractRandomness(orStatement.x))).mod(groupOrderUpperBound);
|
||||
|
@ -194,22 +207,22 @@ public class Prover implements Mix2ZeroKnowledgeProver {
|
|||
|
||||
|
||||
return Mixing.ZeroKnowledgeProof.OrProof.newBuilder()
|
||||
.setG1(forRandomOracle.getG1())
|
||||
.setH1(forRandomOracle.getH1())
|
||||
.setG2(forRandomOracle.getG2())
|
||||
.setH2(forRandomOracle.getH2())
|
||||
.setG1Tag(forRandomOracle.getG1())
|
||||
.setH1Tag(forRandomOracle.getH1Tag())
|
||||
.setG2Tag(forRandomOracle.getG2Tag())
|
||||
.setH2Tag(forRandomOracle.getH2Tag())
|
||||
.setU(forRandomOracle.getU())
|
||||
.setV(forRandomOracle.getV())
|
||||
.setUTag(forRandomOracle.getUTag())
|
||||
.setVTag(forRandomOracle.getVTag())
|
||||
.setC1(ByteString.copyFrom(c1.toByteArray()))
|
||||
.setC2(ByteString.copyFrom(c2.toByteArray()))
|
||||
.setZ(ByteString.copyFrom(z.toByteArray()))
|
||||
.setZTag(ByteString.copyFrom(zTag.toByteArray()))
|
||||
.setG1(firstMessage.getG1())
|
||||
.setH1(firstMessage.getH1())
|
||||
.setG2(firstMessage.getG2())
|
||||
.setH2(firstMessage.getH2())
|
||||
.setG1Tag(firstMessage.getG1())
|
||||
.setH1Tag(firstMessage.getH1Tag())
|
||||
.setG2Tag(firstMessage.getG2Tag())
|
||||
.setH2Tag(firstMessage.getH2Tag())
|
||||
.setU(firstMessage.getU())
|
||||
.setV(firstMessage.getV())
|
||||
.setUTag(firstMessage.getUTag())
|
||||
.setVTag(firstMessage.getVTag())
|
||||
.setC1(Util.encodeBigInteger(c1))
|
||||
.setC2(Util.encodeBigInteger(c2))
|
||||
.setZ(Util.encodeBigInteger(z))
|
||||
.setZTag(Util.encodeBigInteger(zTag))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier {
|
|||
private final ECGroup group;
|
||||
private final RandomOracle randomOracle;
|
||||
private final ECPoint g,h;
|
||||
private final ECElGamalMixParams organizer;
|
||||
private final ECElGamalMixParams mixParams;
|
||||
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 ECElGamalMixParams(group,g,h);
|
||||
this.mixParams = new ECElGamalMixParams(encryptor);
|
||||
this.parser = new ZeroKnowledgeOrProofParser(group);
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier {
|
|||
Crypto.RerandomizableEncryptedMessage out1,
|
||||
Crypto.RerandomizableEncryptedMessage out2,
|
||||
Mixing.ZeroKnowledgeProof proof) throws InvalidProtocolBufferException {
|
||||
ECElGamalMixParams.Statement statement = organizer.createStatement(in1,in2,out1,out2);
|
||||
ECElGamalMixParams.Statement statement = mixParams.createStatement(in1,in2,out1,out2);
|
||||
return verifyElGamaOrProof(statement.getOrStatement(0), proof.getFirst())&&
|
||||
verifyElGamaOrProof(statement.getOrStatement(1), proof.getSecond())&&
|
||||
verifyElGamaOrProof(statement.getOrStatement(2), proof.getThird())&&
|
||||
|
@ -79,7 +79,7 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier {
|
|||
container.g2Tag.equals(orStatement.g2Tag) &&
|
||||
container.h2Tag.equals(orStatement.h2Tag) &&
|
||||
container.c1.add(container.c2).mod(group.orderUpperBound())
|
||||
.equals(Prover.hash(container.forRandomOracle,randomOracle).mod(group.orderUpperBound())) &&
|
||||
.equals(Prover.hash(container.firstMessage,randomOracle).mod(group.orderUpperBound())) &&
|
||||
group.multiply(container.g1, container.z)
|
||||
.equals(group.add(container.u, group.multiply(container.h1,container.c1))) &&
|
||||
group.multiply(container.g2, container.z)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package meerkat.mixer.proofs;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||
import meerkat.crypto.concrete.Util;
|
||||
import meerkat.protobuf.Mixing;
|
||||
import org.bouncycastle.math.ec.ECPoint;
|
||||
import org.factcenter.qilin.primitives.concrete.ECGroup;
|
||||
|
@ -32,15 +33,6 @@ public class ZeroKnowledgeOrProofParser {
|
|||
this.group = group;
|
||||
}
|
||||
|
||||
/**
|
||||
* convert ByteString to ECPoint
|
||||
* @param bs
|
||||
* @return
|
||||
*/
|
||||
public ECPoint convert2ECPoint(ByteString bs){
|
||||
return group.decode(bs.toByteArray());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* inner class
|
||||
|
@ -52,15 +44,15 @@ public class ZeroKnowledgeOrProofParser {
|
|||
public final ECPoint g1Tag,g2Tag,h1Tag,h2Tag;
|
||||
public final ECPoint u,v,uTag,vTag;
|
||||
public final BigInteger c1,c2,z,zTag;
|
||||
public final Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle;
|
||||
public final Mixing.ZeroKnowledgeProof.OrProof.FirstMessage firstMessage;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
* @param orProof
|
||||
*/
|
||||
private ZeroKnowledgeOrProofContainer(Mixing.ZeroKnowledgeProof.OrProof orProof){
|
||||
this.forRandomOracle =
|
||||
Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle.newBuilder()
|
||||
this.firstMessage =
|
||||
Mixing.ZeroKnowledgeProof.OrProof.FirstMessage.newBuilder()
|
||||
.setG1(orProof.getG1())
|
||||
.setH1(orProof.getH1())
|
||||
.setG2(orProof.getG2())
|
||||
|
@ -74,22 +66,22 @@ public class ZeroKnowledgeOrProofParser {
|
|||
.setUTag(orProof.getUTag())
|
||||
.setVTag(orProof.getVTag())
|
||||
.build();
|
||||
this.g1 = convert2ECPoint(orProof.getG1());
|
||||
this.g2 = convert2ECPoint(orProof.getG2());
|
||||
this.h1 = convert2ECPoint(orProof.getH1());
|
||||
this.h2 = convert2ECPoint(orProof.getH2());
|
||||
this.g1Tag = convert2ECPoint(orProof.getG1Tag());
|
||||
this.g2Tag = convert2ECPoint(orProof.getG2Tag());
|
||||
this.h1Tag = convert2ECPoint(orProof.getH1Tag());
|
||||
this.h2Tag = convert2ECPoint(orProof.getH2Tag());
|
||||
this.u = convert2ECPoint(orProof.getU());
|
||||
this.v = convert2ECPoint(orProof.getV());
|
||||
this.uTag = convert2ECPoint(orProof.getUTag());
|
||||
this.vTag = convert2ECPoint(orProof.getVTag());
|
||||
this.c1 = new BigInteger(orProof.getC1().toByteArray());
|
||||
this.c2 = new BigInteger(orProof.getC2().toByteArray());
|
||||
this.z = new BigInteger(orProof.getZ().toByteArray());
|
||||
this.zTag = new BigInteger(orProof.getZTag().toByteArray());
|
||||
this.g1 = ECElGamalEncryption.decodeElement(group, orProof.getG1());
|
||||
this.g2 = ECElGamalEncryption.decodeElement(group, orProof.getG2());
|
||||
this.h1 = ECElGamalEncryption.decodeElement(group, orProof.getH1());
|
||||
this.h2 = ECElGamalEncryption.decodeElement(group, orProof.getH2());
|
||||
this.g1Tag = ECElGamalEncryption.decodeElement(group, orProof.getG1Tag());
|
||||
this.g2Tag = ECElGamalEncryption.decodeElement(group, orProof.getG2Tag());
|
||||
this.h1Tag = ECElGamalEncryption.decodeElement(group, orProof.getH1Tag());
|
||||
this.h2Tag = ECElGamalEncryption.decodeElement(group, orProof.getH2Tag());
|
||||
this.u = ECElGamalEncryption.decodeElement(group, orProof.getU());
|
||||
this.v = ECElGamalEncryption.decodeElement(group, orProof.getV());
|
||||
this.uTag = ECElGamalEncryption.decodeElement(group, orProof.getUTag());
|
||||
this.vTag = ECElGamalEncryption.decodeElement(group, orProof.getVTag());
|
||||
this.c1 = Util.decodeBigInteger(orProof.getC1());
|
||||
this.c2 = Util.decodeBigInteger(orProof.getC2());
|
||||
this.z = Util.decodeBigInteger(orProof.getZ());
|
||||
this.zTag = Util.decodeBigInteger(orProof.getZTag());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,8 +43,8 @@ public class RerandomizeTest {
|
|||
h = enc.getElGamalPK().getPK();
|
||||
}
|
||||
|
||||
private ECPoint convert2ECPoint(ByteString bs){
|
||||
return group.decode(bs.toByteArray());
|
||||
private ECPoint convert2ECPoint(ConcreteCrypto.GroupElement bs){
|
||||
return enc.decodeElement(bs);
|
||||
}
|
||||
|
||||
public void oneRerandomizeTest() throws InvalidProtocolBufferException {
|
||||
|
|
|
@ -62,11 +62,11 @@ public class Utils {
|
|||
public static <T extends Message> T decrypt(Class<T> plaintextMessageType, ECElGamal.SK secretKey, ECGroup group, Crypto.RerandomizableEncryptedMessage opaqueCipher)
|
||||
throws InvalidProtocolBufferException {
|
||||
ConcreteCrypto.ElGamalCiphertext cipherText = ConcreteCrypto.ElGamalCiphertext.parseFrom(opaqueCipher.getData());
|
||||
ByteString c1encoded = cipherText.getC1();
|
||||
ByteString c2encoded = cipherText.getC2();
|
||||
ConcreteCrypto.GroupElement c1encoded = cipherText.getC1();
|
||||
ConcreteCrypto.GroupElement c2encoded = cipherText.getC2();
|
||||
|
||||
ECPoint c1 = group.decode(c1encoded.toByteArray());
|
||||
ECPoint c2 = group.decode(c2encoded.toByteArray());
|
||||
ECPoint c1 = ECElGamalEncryption.decodeElement(group, c1encoded);
|
||||
ECPoint c2 = ECElGamalEncryption.decodeElement(group, c2encoded);
|
||||
|
||||
assert (group.contains(c1));
|
||||
assert (group.contains(c2));
|
||||
|
@ -87,7 +87,7 @@ public class Utils {
|
|||
}
|
||||
}
|
||||
|
||||
static Random random = new Random();
|
||||
static Random random = new Random(0);
|
||||
|
||||
public static Voting.PlaintextBallot genRandomBallot(int numQuestions, int numAnswers, int maxAnswer) {
|
||||
Voting.PlaintextBallot.Builder ballot = Voting.PlaintextBallot.newBuilder();
|
||||
|
|
|
@ -9,6 +9,7 @@ import meerkat.mixer.proofs.Prover;
|
|||
import meerkat.mixer.proofs.Verifier;
|
||||
import meerkat.protobuf.ConcreteCrypto;
|
||||
import meerkat.protobuf.Crypto;
|
||||
import meerkat.protobuf.Mixing;
|
||||
import meerkat.protobuf.Voting;
|
||||
//import meerkat.protobuf.Voting.PlaintextBallot;
|
||||
import org.bouncycastle.math.ec.ECPoint;
|
||||
|
@ -51,8 +52,8 @@ public class ZeroKnowledgeProofTest {
|
|||
prover = new Prover(new Random(),enc,randomOracle);
|
||||
}
|
||||
|
||||
private ECPoint convert2ECPoint(ByteString bs){
|
||||
return group.decode(bs.toByteArray());
|
||||
private ECPoint convert2ECPoint(ConcreteCrypto.GroupElement bs){
|
||||
return enc.decodeElement(bs);
|
||||
}
|
||||
|
||||
public void oneZKPTest() throws InvalidProtocolBufferException {
|
||||
|
@ -89,7 +90,10 @@ public class ZeroKnowledgeProofTest {
|
|||
assertEquals (h.multiply(enc.extractRandomness(r2)),
|
||||
group.add(convert2ECPoint(e2TagElGamal.getC2()),group.negate(convert2ECPoint(e2ElGamal.getC2()))));
|
||||
|
||||
assertTrue (verifier.verify(e1,e2,e1New,e2New,prover.prove(e1,e2,e1New,e2New,false,0,0,0,r1,r2)));
|
||||
|
||||
Mixing.ZeroKnowledgeProof proof = prover.prove(e1,e2,e1New,e2New,false,0,0,0,r1,r2);
|
||||
|
||||
assertTrue (verifier.verify(e1,e2,e1New,e2New, proof));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -45,8 +45,8 @@ public class ByteString2ECPoint {
|
|||
(enc.encrypt(msg, enc.generateRandomness(rand)));
|
||||
}
|
||||
}
|
||||
private ECPoint convert2ECPoint(ByteString bs){
|
||||
return group.decode(bs.toByteArray());
|
||||
private ECPoint convert2ECPoint(ConcreteCrypto.GroupElement bs){
|
||||
return enc.decodeElement(bs);
|
||||
}
|
||||
|
||||
public void ByteString2ECPointProfiling() throws InvalidProtocolBufferException {
|
||||
|
|
Loading…
Reference in New Issue