EC encryption code; compiles but not tested

crypto-primitives
Tal Moran 2015-11-22 03:16:35 +02:00
parent c3e651e34b
commit b8cc3feedb
9 changed files with 140 additions and 6 deletions

View File

@ -90,7 +90,6 @@ idea {
def srcDir = "${protobuf.generatedFilesBaseDir}/$sourceSet.name/java"
println "Adding $srcDir"
// add protobuf generated sources to generated source dir.
if ("test".equals(sourceSet.name)) {
testSourceDirs += file(srcDir)

View File

@ -46,6 +46,7 @@ dependencies {
compile 'com.google.protobuf:protobuf-java:3.+'
// Crypto
compile 'org.factcenter.qilin:qilin:1.+'
compile 'org.bouncycastle:bcprov-jdk15on:1.53'
compile 'org.bouncycastle:bcpkix-jdk15on:1.53'
@ -81,7 +82,6 @@ idea {
def srcDir = "${protobuf.generatedFilesBaseDir}/$sourceSet.name/java"
println "Adding $srcDir"
// add protobuf generated sources to generated source dir.
if ("test".equals(sourceSet.name)) {
testSourceDirs += file(srcDir)

View File

@ -1,5 +1,6 @@
package meerkat.crypto;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message;
import static meerkat.protobuf.Crypto.*;
@ -15,6 +16,6 @@ public interface Encryption {
*/
RerandomizableEncryptedMessage encrypt(Message plaintext, EncryptionRandomness rnd); // TODO: type of exception; throws
RerandomizableEncryptedMessage rerandomize(RerandomizableEncryptedMessage msg, EncryptionRandomness rnd);
RerandomizableEncryptedMessage rerandomize(RerandomizableEncryptedMessage msg, EncryptionRandomness rnd) throws InvalidProtocolBufferException;
}

View File

@ -0,0 +1,111 @@
package meerkat.crypto.concrete;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message;
import meerkat.crypto.Encryption;
import meerkat.protobuf.ConcreteCrypto;
import meerkat.protobuf.Crypto;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.util.PublicKeyFactory;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.BigIntegers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import qilin.primitives.concrete.ECElGamal;
import qilin.primitives.concrete.ECGroup;
import qilin.primitives.PseudorandomGenerator;
import qilin.util.PRGRandom;
import qilin.util.Pair;
import java.io.IOException;
import java.math.BigInteger;
import java.security.spec.*;
/**
* Created by talm on 17/11/15.
*/
public class ECElGamalEncryption implements Encryption {
final Logger logger = LoggerFactory.getLogger(getClass());
public final static String KEY_ALGORITHM = "ECDH";
/**
* The Qilin format El-Gamal public key
*/
ECElGamal.PK elGamalPK;
ECCurve curve;
ECGroup group;
public void init(ConcreteCrypto.ElGamalPublicKey serializedPk) throws InvalidKeySpecException {
AsymmetricKeyParameter keyParam;
try {
keyParam = PublicKeyFactory.createKey(serializedPk.getSubjectPublicKeyInfo().toByteArray());
} catch (IOException e) {
// Shouldn't every happen
logger.error("Invalid Public Key Encoding", e);
throw new InvalidKeySpecException("Invalid Public Key Encoding", e);
}
if (!(keyParam instanceof ECPublicKeyParameters)) {
logger.error("Public key is a {}, not a valid public EC Key!", keyParam.getClass());
throw new InvalidKeySpecException("Not a valid EC public key!");
}
ECDomainParameters params = ((ECKeyParameters) keyParam).getParameters();
ECParameterSpec ecParams = new ECParameterSpec(params.getCurve(), params.getG(), params.getN(), params.getH(),
params.getSeed());
curve = params.getCurve();
group = new ECGroup(ecParams);
elGamalPK = new ECElGamal.PK(group, ((ECPublicKeyParameters) keyParam).getQ());
}
@Override
public Crypto.RerandomizableEncryptedMessage encrypt(Message plaintext, Crypto.EncryptionRandomness rnd) {
byte[] msg = plaintext.toByteArray();
ECPoint encodedMsg = group.injectiveEncode(plaintext.toByteArray(), new PRGRandom(msg));
BigInteger rndInt = BigIntegers.fromUnsignedByteArray(rnd.getData().toByteArray());
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)))
.build();
return Crypto.RerandomizableEncryptedMessage.newBuilder()
.setData(encodedCipherText.toByteString())
.build();
}
@Override
public Crypto.RerandomizableEncryptedMessage rerandomize(Crypto.RerandomizableEncryptedMessage msg, Crypto.EncryptionRandomness rnd) throws InvalidProtocolBufferException {
BigInteger rndInt = BigIntegers.fromUnsignedByteArray(rnd.getData().toByteArray());
Pair<ECPoint,ECPoint> randomizer = elGamalPK.encrypt(curve.getInfinity(), rndInt);
ConcreteCrypto.ElGamalCiphertext originalEncodedCipher= ConcreteCrypto.ElGamalCiphertext.parseFrom(msg.getData());
Pair<ECPoint,ECPoint> originalCipher = new Pair<>(
curve.decodePoint(originalEncodedCipher.getC1().toByteArray()),
curve.decodePoint(originalEncodedCipher.getC2().toByteArray()));
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)))
.build().toByteString()
).build();
}
}

View File

@ -0,0 +1,22 @@
// Protobufs for specific crypto primitives
syntax = "proto3";
package meerkat;
import 'meerkat/crypto.proto';
option java_package = "meerkat.protobuf";
message ElGamalPublicKey {
// DER-encoded SubjectPublicKeyInfo as in RFC 3279
bytes subject_public_key_info = 1;
}
// An El-Gamal ciphertext
// Each group element should be an ASN.1 encoded curve point with compression.
message ElGamalCiphertext {
bytes c1 = 1; // First group element
bytes c2 = 2; // Second group element
}

View File

@ -9,6 +9,10 @@ enum SignatureType {
DSA = 1;
}
message BigInteger {
bytes data = 1;
}
// A digital signature
message Signature {
SignatureType type = 1;

View File

@ -73,7 +73,6 @@ idea {
def srcDir = "${protobuf.generatedFilesBaseDir}/$sourceSet.name/java"
println "Adding $srcDir"
// add protobuf generated sources to generated source dir.
if ("test".equals(sourceSet.name)) {
testSourceDirs += file(srcDir)

View File

@ -73,7 +73,6 @@ idea {
def srcDir = "${protobuf.generatedFilesBaseDir}/$sourceSet.name/java"
println "Adding $srcDir"
// add protobuf generated sources to generated source dir.
if ("test".equals(sourceSet.name)) {
testSourceDirs += file(srcDir)

View File

@ -72,7 +72,6 @@ idea {
def srcDir = "${protobuf.generatedFilesBaseDir}/$sourceSet.name/java"
println "Adding $srcDir"
// add protobuf generated sources to generated source dir.
if ("test".equals(sourceSet.name)) {
testSourceDirs += file(srcDir)