Bug fixes; Encryption/Rerandomization tests pass
							parent
							
								
									46de34fbfb
								
							
						
					
					
						commit
						984d7457c6
					
				|  | @ -152,6 +152,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 {  | ||||||
|  |  | ||||||
|  | @ -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() |  | ||||||
|                     .addAnswer(2) |  | ||||||
|                     .addAnswer(3) |  | ||||||
|                     .addAnswer(0) |  | ||||||
|                 ) |  | ||||||
|                 .addAnswers( Voting.BallotAnswer.newBuilder() |  | ||||||
|                         .addAnswer(5) |  | ||||||
|                         .addAnswer(6) |  | ||||||
|                         .addAnswer(7) |  | ||||||
|                 ) |  | ||||||
|                 .build(); |  | ||||||
| 
 | 
 | ||||||
|         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); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | @ -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