Poszukuję opensource implementacji homomorficznego algorytmu szyfrowania BGN w java.Implementacja BGN w Javie
Znalazłem następujący kod online dla BGN. Próbuję go wykonać, ale mam problemy.
dokładniej schemat próbuje wdrożyć following (strona 3, 4):
Add(pk;C1;C2): Choose t0 R [1, n] and output C0 = C1 + C2 + [t0]Q E G. Mult(pk;C1;C2): Choose u R [1, n] and output D = ^e(C1;C2).e(Q;Q)u E n.
package bgn;
import it.unisa.dia.gas.jpbc.Element;
import it.unisa.dia.gas.jpbc.Field;
import it.unisa.dia.gas.jpbc.PairingParameters;
import it.unisa.dia.gas.plaf.jpbc.pairing.a1.TypeA1CurveGenerator;
import it.unisa.dia.gas.plaf.jpbc.pairing.a1.TypeA1Pairing;
import it.unisa.dia.gas.plaf.jpbc.util.math.BigIntegerUtils;
import java.math.BigInteger;
import java.security.SecureRandom;
public class BGNEncryption {
public BGNEncryption()
{
}
private PairingParameters param;
private BigInteger r;
private BigInteger q; //This is the private key.
private BigInteger order;
private SecureRandom rng;
public PublicKey gen(int bits) {
rng = new SecureRandom();
TypeA1CurveGenerator a1 = new TypeA1CurveGenerator(rng, 2, bits); //Requires 2 prime numbers.
param = a1.generate();
TypeA1Pairing pairing = new TypeA1Pairing(param);
order = param.getBigInteger("n"); //Must extract the prime numbers for both keys.
r = param.getBigInteger("n0");
q = param.getBigInteger("n1");
System.out.println(order + " " + " r"+ r + " q"+ q + "");
Field<?> f = pairing.getG1();
Element P = f.newRandomElement();
P = P.mul(param.getBigInteger("l"));
Element Q = f.newElement();
Q = Q.set(P);
Q = Q.mul(r);
return new PublicKey(pairing, P, Q,
order);
}
public Element encrypt(PublicKey PK, int msg)
{
BigInteger t = BigIntegerUtils.getRandom(PK.getN());
int m = msg;
System.out.println("Hash is " + m);
Field<?> f = PK.getField();
Element A = f.newElement();
Element B = f.newElement();
Element C = f.newElement();
A = A.set(PK.getP());
A = A.mul(BigInteger.valueOf(m));
B = B.set(PK.getQ());
B = B.mul(t);
C = C.set(A);
C = C.add(B);
return C;
}
public Element add(PublicKey PK, Element A, Element B){
BigInteger t = BigIntegerUtils.getRandom(PK.getN());
Field<?> f = PK.getField();
Element output = f.newElement();
Element aux = f.newElement();
aux.set(PK.getQ());
aux.mul(t);
output.set(A);
output.add(B);
output.add(aux);
return output;
}
public Element mul(PublicKey PK, Element C, Element D){
BigInteger t = BigIntegerUtils.getRandom(PK.getN()); //Make sure product is NOT infinite.
Field<?> f = PK.getField();
Element Q = PK.getQ();
Element output = f.newElement();
Element aux = f.newElement();
aux.set(PK.doPairing(C, D));
output.set(PK.doPairing(Q,Q));
output.pow(t);
output.mul(aux);
return output;
}
public String decrypt(PublicKey PK, BigInteger sk, Element C) {
Field<?> f = PK.getField();
Element T = f.newElement();
Element K = f.newElement();
Element aux = f.newElement();
T = T.set(PK.getP());
T = T.mul(sk);
K = K.set(C);
K = K.mul(sk);
aux = aux.set(T);
BigInteger m = new BigInteger("1");
while (!aux.isEqual(K)) {
//This is a brute force implementation of finding the discrete logarithm.
//Performance may be improved using algorithms such as Pollard's Kangaroo.
aux = aux.add(T);
m = m.add(BigInteger.valueOf(1));
}
return m.toString();
}
public static void main(String[] args)
{
BGNEncryption b = new BGNEncryption();
PublicKey PK = b.gen(32);
Element msg = b.encrypt(PK, 1);
Element msg2 = b.encrypt(PK, 1);
Element add = b.add(PK, msg, msg2);
Element mul = b.mul(PK, msg, msg2);
System.out.println("Addition: "+ b.decrypt(PK, b.q, add));
// System.out.println("Mul: "+ b.decrypt(PK, b.q, mul));
long t = System.currentTimeMillis();
System.out.println(b.decrypt(PK, b.q, msg2));
System.out.println("Decryption took "
+ (System.currentTimeMillis() - t) + " ms");
}
}
PublicKey.Java Class: Drobny
package bgn;
import it.unisa.dia.gas.jpbc.Element;
import it.unisa.dia.gas.jpbc.Field;
import it.unisa.dia.gas.plaf.jpbc.pairing.a1.TypeA1Pairing;
import java.math.BigInteger;
public class PublicKey {
private TypeA1Pairing map;
private Element P, Q;
private BigInteger n;
private Field<?> f;
public PublicKey(TypeA1Pairing pairing, Element gen, Element point,
BigInteger order) {
map = pairing;
P = gen.set(gen);
Q = point.set(point);
n = order;
f = pairing.getG1();
}
public Element doPairing(Element A, Element B) {
return map.pairing(A, B);
}
public Element getP() {
return this.P;
}
public Element getQ() {
return this.Q;
}
public BigInteger getN() {
return this.n;
}
public Field<?> getField() {
return this.f;
}
}
Na wykonanie, dodatek działa. Ale mnożenie nie działa z następującym błędem:
Exception in thread "main" java.lang.ClassCastException: it.unisa.dia.gas.plaf.jpbc.field.gt.GTFiniteElement cannot be cast to it.unisa.dia.gas.plaf.jpbc.field.curve.CurveElement
at it.unisa.dia.gas.plaf.jpbc.field.curve.CurveElement.set(CurveElement.java:55)
at it.unisa.dia.gas.plaf.jpbc.field.curve.CurveElement.set(CurveElement.java:12)
at bgn.BGNEncryption.mul(BGNEncryption.java:82)
at bgn.BGNEncryption.main(BGNEncryption.java:118)
Wziąłem wyżej kod z Here i usunięte Android część. Czy jest na to jakaś wskazówka? Jak mogę rozwiązać poniżej wyjątek?
Weź schemat, że kod ten ma na celu wdrożenie i sprawdź, czy każde pole zawiera elementy typu, który ma zawierać. Błąd mówi, że nie można umieścić elementu grupy GT w zmiennej elementu grupy G1. –
@ArtjomB. ** GT ** nie został nigdzie utworzony w kodzie. Utworzono i dodano G1. – Azam
Wynik parowania jest zawsze w GT. Problem polega na tym, że jest to prawdopodobnie napisane dla starszej wersji jPBC. Użyj 'Element x = element.duplicate();' zamiast 'Element x = f.newElement(); x.set (element); ', ale to nie rozwiąże problemu, ponieważ' aux' jest elementem krzywej G1 podczas odszyfrowywania, ale 'K' jest elementem krzywej. –