Bug fixes; Encryption/Rerandomization tests pass
parent
46de34fbfb
commit
984d7457c6
|
@ -153,6 +153,8 @@ task fatCapsule(type: FatCapsule){
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
|
||||||
|
mavenLocal();
|
||||||
|
|
||||||
// Prefer the local nexus repository (it may have 3rd party artifacts not found in mavenCentral)
|
// Prefer the local nexus repository (it may have 3rd party artifacts not found in mavenCentral)
|
||||||
maven {
|
maven {
|
||||||
url nexusRepository
|
url nexusRepository
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.slf4j.LoggerFactory;
|
||||||
import qilin.primitives.concrete.ECElGamal;
|
import qilin.primitives.concrete.ECElGamal;
|
||||||
import qilin.primitives.concrete.ECGroup;
|
import qilin.primitives.concrete.ECGroup;
|
||||||
import qilin.primitives.PseudorandomGenerator;
|
import qilin.primitives.PseudorandomGenerator;
|
||||||
|
import qilin.primitives.generic.ElGamal;
|
||||||
import qilin.util.PRGRandom;
|
import qilin.util.PRGRandom;
|
||||||
import qilin.util.Pair;
|
import qilin.util.Pair;
|
||||||
|
|
||||||
|
@ -49,6 +50,12 @@ public class ECElGamalEncryption extends GlobalCryptoSetup implements Encryption
|
||||||
|
|
||||||
ECGroup group;
|
ECGroup group;
|
||||||
|
|
||||||
|
public ECGroup getGroup() { return group; }
|
||||||
|
|
||||||
|
public ECElGamal.PK getElGamalPK() {
|
||||||
|
return elGamalPK;
|
||||||
|
}
|
||||||
|
|
||||||
public void init(ConcreteCrypto.ElGamalPublicKey serializedPk) throws InvalidKeySpecException {
|
public void init(ConcreteCrypto.ElGamalPublicKey serializedPk) throws InvalidKeySpecException {
|
||||||
AsymmetricKeyParameter keyParam;
|
AsymmetricKeyParameter keyParam;
|
||||||
|
|
||||||
|
|
|
@ -4,18 +4,32 @@ import meerkat.protobuf.BulletinBoardAPI;
|
||||||
import meerkat.protobuf.ConcreteCrypto;
|
import meerkat.protobuf.ConcreteCrypto;
|
||||||
import meerkat.protobuf.Crypto;
|
import meerkat.protobuf.Crypto;
|
||||||
import meerkat.protobuf.Voting;
|
import meerkat.protobuf.Voting;
|
||||||
|
import org.bouncycastle.math.ec.ECPoint;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import qilin.primitives.concrete.ECElGamal;
|
import qilin.primitives.concrete.ECElGamal;
|
||||||
import qilin.primitives.concrete.ECGroup;
|
import qilin.primitives.concrete.ECGroup;
|
||||||
|
import qilin.primitives.generic.ElGamal;
|
||||||
|
import qilin.util.Pair;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test class for {@link ECElGamalEncryption}
|
* Test class for {@link ECElGamalEncryption}
|
||||||
*/
|
*/
|
||||||
public class ECElGamalEncryptionTest {
|
public class ECElGamalEncryptionTest {
|
||||||
|
final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
/**
|
||||||
|
* Number of times to repeat probabilistic tests.
|
||||||
|
*/
|
||||||
|
public final static int CONFIDENCE = 10;
|
||||||
|
|
||||||
Random rand = new Random(0); // Insecure deterministic random for testing.
|
Random rand = new Random(0); // Insecure deterministic random for testing.
|
||||||
|
|
||||||
ECElGamal.SK key;
|
ECElGamal.SK key;
|
||||||
|
@ -37,25 +51,75 @@ public class ECElGamalEncryptionTest {
|
||||||
enc.init(serializedPk);
|
enc.init(serializedPk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Voting.PlaintextBallot genRandomBallot(int numQuestions, int numAnswers, int maxAnswer) {
|
||||||
|
Voting.PlaintextBallot.Builder ballot = Voting.PlaintextBallot.newBuilder();
|
||||||
|
ballot.setSerialNumber(rand.nextInt(1000000));
|
||||||
|
for (int i = 0; i < numQuestions; ++i) {
|
||||||
|
Voting.BallotAnswer.Builder answers = ballot.addAnswersBuilder();
|
||||||
|
for (int j = 0; j < numAnswers; ++j) {
|
||||||
|
answers.addAnswer(rand.nextInt(maxAnswer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ballot.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Testing just the key management
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testEncrypt() throws Exception {
|
public void testPkSerialization() throws Exception {
|
||||||
Voting.PlaintextBallot msg = Voting.PlaintextBallot.newBuilder()
|
ECElGamal.PK pk = enc.getElGamalPK();
|
||||||
.setSerialNumber(1)
|
|
||||||
.addAnswers( Voting.BallotAnswer.newBuilder()
|
ECPoint point = enc.getGroup().sample(rand);
|
||||||
.addAnswer(2)
|
Pair<ECPoint, ECPoint> cipher = pk.encrypt(point, pk.getRandom(rand));
|
||||||
.addAnswer(3)
|
|
||||||
.addAnswer(0)
|
ECPoint decrypted = key.decrypt(cipher);
|
||||||
)
|
|
||||||
.addAnswers( Voting.BallotAnswer.newBuilder()
|
assertEquals("Decrypted value not equal to encrypted value!", point, decrypted);
|
||||||
.addAnswer(5)
|
}
|
||||||
.addAnswer(6)
|
|
||||||
.addAnswer(7)
|
@Test
|
||||||
)
|
public void testEncryption() throws Exception {
|
||||||
.build();
|
for (int i = 0; i < CONFIDENCE; ++i) {
|
||||||
|
Voting.PlaintextBallot msg = genRandomBallot(2,3,16); // 2 questions with 3 answers each, in range 0-15.
|
||||||
|
if (msg.getSerializedSize() > enc.getGroup().getInjectiveEncodeMsgLength()) {
|
||||||
|
logger.error("Test Message too big (|msg|={} > max={}), expect failure.",
|
||||||
|
msg.getSerializedSize(), enc.getGroup().getInjectiveEncodeMsgLength());
|
||||||
|
}
|
||||||
|
|
||||||
Crypto.RerandomizableEncryptedMessage cipherText = enc.encrypt(msg, enc.generateRandomness(rand));
|
Crypto.RerandomizableEncryptedMessage cipherText = enc.encrypt(msg, enc.generateRandomness(rand));
|
||||||
|
|
||||||
Voting.PlaintextBallot decrypted = ECElGamalUtils.decrypt(Voting.PlaintextBallot.class, key, group, cipherText);
|
Voting.PlaintextBallot decrypted = ECElGamalUtils.decrypt(Voting.PlaintextBallot.class, key, group, cipherText);
|
||||||
|
|
||||||
|
assertEquals("Decrypted value differs from encrypted value (i="+i+")!", msg, decrypted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRerandomizeModifiesCiphertext() throws Exception {
|
||||||
|
Voting.PlaintextBallot msg = genRandomBallot(2,3,16); // 2 questions with 3 answers each, in range 0-15.
|
||||||
|
Crypto.RerandomizableEncryptedMessage cipher1 = enc.encrypt(msg, enc.generateRandomness(rand));
|
||||||
|
Crypto.RerandomizableEncryptedMessage cipher2 = enc.rerandomize(cipher1, enc.generateRandomness(rand));
|
||||||
|
assertNotEquals("Rerandomized cipher identical to original!", cipher1, cipher2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRerandomizePreservesPlaintext() throws Exception {
|
||||||
|
for (int i = 0; i < CONFIDENCE; ++i) {
|
||||||
|
Voting.PlaintextBallot msg = genRandomBallot(2,3,16); // 2 questions with 3 answers each, in range 0-15.
|
||||||
|
|
||||||
|
Crypto.RerandomizableEncryptedMessage cipher = enc.encrypt(msg, enc.generateRandomness(rand));
|
||||||
|
Crypto.RerandomizableEncryptedMessage cipher2 = cipher;
|
||||||
|
for (int j = 0; j < CONFIDENCE; ++j)
|
||||||
|
cipher2 = enc.rerandomize(cipher2, enc.generateRandomness(rand));
|
||||||
|
|
||||||
|
Voting.PlaintextBallot decrypted = ECElGamalUtils.decrypt(Voting.PlaintextBallot.class, key, group,
|
||||||
|
cipher2);
|
||||||
|
|
||||||
|
assertEquals("Decrypted value differs from original encrypted value (i="+i+")!", msg, decrypted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
package meerkat.crypto.concrete;
|
package meerkat.crypto.concrete;
|
||||||
|
|
||||||
import com.google.protobuf.*;
|
import com.google.protobuf.ByteString;
|
||||||
|
import com.google.protobuf.GeneratedMessage;
|
||||||
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
|
import com.google.protobuf.Message;
|
||||||
import meerkat.protobuf.ConcreteCrypto;
|
import meerkat.protobuf.ConcreteCrypto;
|
||||||
import meerkat.protobuf.Crypto;
|
import meerkat.protobuf.Crypto;
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
|
||||||
import org.bouncycastle.jce.spec.ECParameterSpec;
|
import org.bouncycastle.jce.spec.ECParameterSpec;
|
||||||
import org.bouncycastle.jce.spec.ECPublicKeySpec;
|
import org.bouncycastle.jce.spec.ECPublicKeySpec;
|
||||||
import org.bouncycastle.math.ec.ECPoint;
|
import org.bouncycastle.math.ec.ECPoint;
|
||||||
|
@ -14,13 +16,11 @@ import qilin.primitives.concrete.ECGroup;
|
||||||
import qilin.primitives.generic.ElGamal;
|
import qilin.primitives.generic.ElGamal;
|
||||||
import qilin.util.Pair;
|
import qilin.util.Pair;
|
||||||
|
|
||||||
import java.lang.reflect.*;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.security.KeyFactory;
|
import java.security.KeyFactory;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.NoSuchProviderException;
|
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.security.spec.InvalidKeySpecException;
|
import java.security.spec.InvalidKeySpecException;
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* utilities for ECElgamal
|
* utilities for ECElgamal
|
||||||
|
@ -73,12 +73,13 @@ public class ECElGamalUtils {
|
||||||
|
|
||||||
byte[] plaintext = group.injectiveDecode(plaintextEncoded);
|
byte[] plaintext = group.injectiveDecode(plaintextEncoded);
|
||||||
|
|
||||||
CodedInputStream ci = CodedInputStream.newInstance(plaintext);
|
ByteArrayInputStream in = new ByteArrayInputStream(plaintext);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
java.lang.reflect.Method newBuilder = plaintextMessageType.getMethod("newBuilder");
|
java.lang.reflect.Method newBuilder = plaintextMessageType.getMethod("newBuilder");
|
||||||
GeneratedMessage.Builder builder = (GeneratedMessage.Builder) newBuilder.invoke(plaintextMessageType);
|
GeneratedMessage.Builder builder = (GeneratedMessage.Builder) newBuilder.invoke(plaintextMessageType);
|
||||||
return (T) builder.mergeFrom(ci).build();
|
builder.mergeDelimitedFrom(in);
|
||||||
|
return plaintextMessageType.cast(builder.build());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("Error parsing incoming message", e);
|
logger.error("Error parsing incoming message", e);
|
||||||
throw new InvalidProtocolBufferException("Plaintext protobuf error");
|
throw new InvalidProtocolBufferException("Plaintext protobuf error");
|
||||||
|
|
Loading…
Reference in New Issue