Page MenuHomec4science

ECElGamal.java
No OneTemporary

File Metadata

Created
Tue, Jan 7, 00:23

ECElGamal.java

package crypto.elgamal;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.HashMap;
import org.bouncycastle.asn1.nist.NISTNamedCurves;
import org.bouncycastle.asn1.x9.X962NamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.math.ec.ECPoint;
public class ECElGamal {
public static final int PART_SPU = 1;
public static final int PART_MU = 2;
//FIXME: fix number of bits (q)?
private static final int PRIV_KEY_BITLENGTH = 128;
//FIXME: depends on the result space
private static final int DOMAIN_RANGE = 10000;
private X9ECParameters ecParams;
private BigInteger privKey;
private ECPoint pPubKey;
private int partNumber;
private SecureRandom randomGen;
private HashMap<ECPoint, BigInteger> reverseTable;
public ECElGamal() {
this(NISTNamedCurves.getByName("P-521"));
}
public ECElGamal(X9ECParameters ecParams) {
this.ecParams = ecParams;
randomGen = new SecureRandom();
this.privKey = new BigInteger(PRIV_KEY_BITLENGTH, randomGen);
this.pPubKey = ecParams.getG().multiply(privKey);
}
public ECElGamal(X9ECParameters ecParams, BigInteger privKey) {
this.ecParams = ecParams;
randomGen = new SecureRandom();
this.privKey = privKey;
this.pPubKey = ecParams.getG().multiply(privKey);
}
public ECElGamal(X9ECParameters ecParams, ECPoint pPubKey) {
this.ecParams = ecParams;
randomGen = new SecureRandom();
this.pPubKey = pPubKey;
}
public void initReverseDLTable() {
initReverseDLTable(BigInteger.valueOf(DOMAIN_RANGE));
}
private void initReverseDLTable(BigInteger size) {
if (reverseTable != null) {
System.out.println("Reverse Discrete Logarithm table exists already!");
return;
}
else {
reverseTable = new HashMap<>(size.intValue()); // XXX: beware of this
BigInteger i = BigInteger.ZERO;
while(i.compareTo(size) < 0) { // counter < size
ECPoint p = ecParams.getG().multiply(i);
reverseTable.put(p, i);
i = i.add(BigInteger.ONE);
}
}
}
public boolean canDecrypt() {
//FIXME need modification with threshold encryption
// FIXME obselete now. need canDecrypt and canReverse
return (privKey != null) && (reverseTable != null);
}
public FragmentEncrypted encrypt(BigInteger msg) {
ECPoint pMsg = map(msg);
BigInteger random = new BigInteger(PRIV_KEY_BITLENGTH, randomGen);
ECPoint R = ecParams.getG().multiply(random);
ECPoint S = pMsg.add(pPubKey.multiply(random));
return new FragmentEncrypted(R, S);
}
public BigInteger decrypt(FragmentEncrypted frag) {
if (!canDecrypt()) {
throw new UnsupportedOperationException("Private key undefined");
}
ECPoint M = frag.getS().subtract(frag.getR().multiply(privKey));
return rmap(M);
}
public FragmentPartial partialDecrypt(FragmentEncrypted frag) {
if (!canDecrypt()) {
throw new UnsupportedOperationException("Private key undefined");
}
if (partNumber == 0) {
throw new IllegalStateException("No part number set: unable to partially decrypt");
}
ECPoint T = frag.getR().multiply(privKey);
return new FragmentPartial(partNumber, frag, T);
}
public BigInteger fullDecrypt(FragmentPartial fragmentMU, FragmentPartial fragmentSPU) {
if ( !fragmentMU.equalsFragmentEncrypted(fragmentSPU) ) {
throw new IllegalArgumentException("fragments do not have same source encrypted data");
} else if (fragmentMU.getPartNumber() != PART_MU) {
throw new IllegalArgumentException("MU fragment does not have matching type");
} else if (fragmentSPU.getPartNumber() != PART_SPU) {
throw new IllegalArgumentException("SPU fragment does not have matching type");
}
ECPoint tMU = fragmentMU.getT().multiply(BigInteger.valueOf(2));
ECPoint tSPU = fragmentSPU.getT();
ECPoint F = tMU.subtract(tSPU);
ECPoint M = fragmentMU.getS().subtract(F);
return rmap(M);
}
private ECPoint map(BigInteger msg) {
if (msg.compareTo(BigInteger.valueOf(DOMAIN_RANGE)) > 0) {
throw new IllegalArgumentException("msg should be less than " + DOMAIN_RANGE);
}
return ecParams.getG().multiply(msg);
}
private BigInteger rmap(ECPoint p) {
BigInteger m = reverseTable.get(p);
if (m == null) {
// mapping not indexed. Out of Domain Range.
throw new ArrayIndexOutOfBoundsException("Could not find mapping for EC point");
}
return m;
}
public X9ECParameters getECParams() {
return ecParams;
}
public void setPartNumber(int partNumber) {
this.partNumber = partNumber;
}
public static void main(String[] args) {
ECElGamal eccegScheme = new ECElGamal(NISTNamedCurves.getByName("P-384"));
System.out.print("Generating table lookup...");
eccegScheme.initReverseDLTable();
System.out.println("[OK]");
}
public static void test() {
// X9ECParameters params = NISTNamedCurves.getByName("P-384");
X9ECParameters params = NISTNamedCurves.getByName("P-521");
X9ECParameters params2 = X962NamedCurves.getByName("c2pnb163v1");
System.out.println("Field size :" + params.getCurve().getFieldSize());
System.out.println("n=" + params.getN());
}
}

Event Timeline