Bug fixes; Encryption/Rerandomization tests pass

crypto-primitives
Tal Moran 2015-11-22 23:24:27 +02:00
parent 46de34fbfb
commit 984d7457c6
4 changed files with 97 additions and 23 deletions

View File

@ -152,6 +152,8 @@ task fatCapsule(type: FatCapsule){
*===================================*/
repositories {
mavenLocal();
// Prefer the local nexus repository (it may have 3rd party artifacts not found in mavenCentral)
maven {

View File

@ -22,6 +22,7 @@ import org.slf4j.LoggerFactory;
import qilin.primitives.concrete.ECElGamal;
import qilin.primitives.concrete.ECGroup;
import qilin.primitives.PseudorandomGenerator;
import qilin.primitives.generic.ElGamal;
import qilin.util.PRGRandom;
import qilin.util.Pair;
@ -49,6 +50,12 @@ public class ECElGamalEncryption extends GlobalCryptoSetup implements Encryption
ECGroup group;
public ECGroup getGroup() { return group; }
public ECElGamal.PK getElGamalPK() {
return elGamalPK;
}
public void init(ConcreteCrypto.ElGamalPublicKey serializedPk) throws InvalidKeySpecException {
AsymmetricKeyParameter keyParam;

View File

@ -4,18 +4,32 @@ import meerkat.protobuf.BulletinBoardAPI;
import meerkat.protobuf.ConcreteCrypto;
import meerkat.protobuf.Crypto;
import meerkat.protobuf.Voting;
import org.bouncycastle.math.ec.ECPoint;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import qilin.primitives.concrete.ECElGamal;
import qilin.primitives.concrete.ECGroup;
import qilin.primitives.generic.ElGamal;
import qilin.util.Pair;
import java.math.BigInteger;
import java.util.Random;
import static org.junit.Assert.*;
/**
* Test class for {@link ECElGamalEncryption}
*/
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.
ECElGamal.SK key;
@ -37,25 +51,75 @@ public class ECElGamalEncryptionTest {
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
public void testEncrypt() throws Exception {
Voting.PlaintextBallot msg = Voting.PlaintextBallot.newBuilder()
.setSerialNumber(1)
.addAnswers( Voting.BallotAnswer.newBuilder()
.addAnswer(2)
.addAnswer(3)
.addAnswer(0)
)
.addAnswers( Voting.BallotAnswer.newBuilder()
.addAnswer(5)
.addAnswer(6)
.addAnswer(7)
)
.build();
public void testPkSerialization() throws Exception {
ECElGamal.PK pk = enc.getElGamalPK();
Crypto.RerandomizableEncryptedMessage cipherText = enc.encrypt(msg, enc.generateRandomness(rand));
ECPoint point = enc.getGroup().sample(rand);
Pair<ECPoint, ECPoint> cipher = pk.encrypt(point, pk.getRandom(rand));
Voting.PlaintextBallot decrypted = ECElGamalUtils.decrypt(Voting.PlaintextBallot.class, key, group, cipherText);
ECPoint decrypted = key.decrypt(cipher);
assertEquals("Decrypted value not equal to encrypted value!", point, decrypted);
}
@Test
public void testEncryption() 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.
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));
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);
}
}
}

View File

@ -1,9 +1,11 @@
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.Crypto;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.math.ec.ECPoint;
@ -14,13 +16,11 @@ import qilin.primitives.concrete.ECGroup;
import qilin.primitives.generic.ElGamal;
import qilin.util.Pair;
import java.lang.reflect.*;
import java.io.ByteArrayInputStream;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.util.Random;
/**
* utilities for ECElgamal
@ -73,12 +73,13 @@ public class ECElGamalUtils {
byte[] plaintext = group.injectiveDecode(plaintextEncoded);
CodedInputStream ci = CodedInputStream.newInstance(plaintext);
ByteArrayInputStream in = new ByteArrayInputStream(plaintext);
try {
java.lang.reflect.Method newBuilder = plaintextMessageType.getMethod("newBuilder");
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) {
logger.error("Error parsing incoming message", e);
throw new InvalidProtocolBufferException("Plaintext protobuf error");