Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BGN Implementation in Java

I am looking for opensource implementation of BGN homomorphic encryption algorithm in java.

I found following code online for BGN. I am trying to execute it but having issues.

More closely scheme is trying to implement following (page 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:

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;
    }
}

On executing, addition is working fine. But multiplication is not working with following error:

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)

I took above code from Here and removed Android part. Any clue on it please ? How can I solve below exception ?

like image 586
Umer Avatar asked Nov 07 '15 11:11

Umer


1 Answers

from the crypt document, the multi result is not the same Element type with P, Q in PublicKey and the decrypt method for multi is also not same with the one for addition. we need reimplement method mul and decryptMul like

public Element mul(PublicKey PK, Element C, Element D) {
    BigInteger t = BigIntegerUtils.getRandom(PK.getN());

    Element T = PK.doPairing(C, D);

    Element K = PK.doPairing(PK.getQ(), PK.getQ());
    K = K.pow(t);
    return T.mul(K);
}

public String decryptMul(PublicKey PK, BigInteger sk, Element C) {
    Element PSK = PK.doPairing(PK.getP(), PK.getP());
    PSK.pow(sk);

    Element CSK = C.duplicate();
    CSK.pow(sk);

    Element aux = PSK.duplicate();
    BigInteger m = new BigInteger("1");
    while (!aux.isEqual(CSK)) {
        aux = aux.mul(PSK);
        m = m.add(BigInteger.valueOf(1));
    }
    return m.toString();
}

then decrypt test code is like:

public static void main(String[] args) {
    BGNEncryption b = new BGNEncryption();
    PublicKey PK = b.gen(32);

    Element msg1 = b.encrypt(PK, 32);
    Element msg2 = b.encrypt(PK, 15);

    Element add = b.add(PK, msg1, msg2);
    System.out.println("Addition: " + b.decrypt(PK, b.q, add));

    Element mul = b.mul(PK, msg1, msg2);
    System.out.println("Mul: " + b.decryptMul(PK, b.q, mul));
} 

output is like

17578994648374341643  r4284550243 q4102879801
Hash is 32
Hash is 15
Addition: 47
Mul: 480
like image 108
andy Avatar answered Nov 12 '22 09:11

andy