Can't encrypt/decrypt big data array with pailler cryptosystem with java

210 views Asked by At

I have a project to test various algorithms about their running time for big byte arrays (>10MB) and i can't find a way to encrypt/decrypt those data with the paillier algorithm. This is my code which obviously doesn't work for data bigger than the key size

public class PaillierKeyPair implements Serializable{

public PaillierPublicKey PublicKey;
public PaillierPrivateKey PrivateKey;

public PaillierKeyPair(int bitLengthVal) {
    // TODO Auto-generated constructor stub
    KeyGeneration(bitLengthVal, 100);
}

public PaillierKeyPair() {
    //null constructor
}

private void KeyGeneration(int bitLengthVal, int certainty) {
    int bitLength = bitLengthVal;
    /*Constructs two randomly generated positive BigIntegers that are probably prime, with the specified bitLength and certainty.*/
    BigInteger p = new BigInteger(bitLength / 2, certainty, new SecureRandom());
    BigInteger q = new BigInteger(bitLength / 2, certainty, new SecureRandom());

    BigInteger n = p.multiply(q);
    BigInteger nsquare = n.multiply(n);
    BigInteger g, lambda;
    while(true){
        g = new BigInteger(bitLength, new SecureRandom());
        lambda = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE)).divide(
                p.subtract(BigInteger.ONE).gcd(q.subtract(BigInteger.ONE)));
        /* check whether g is good.*/
        if (g.modPow(lambda, nsquare).subtract(BigInteger.ONE).divide(n).gcd(n).intValue() != 1) {
            System.out.println("g is not good. Choose g again.");
            //System.exit(1);
        }else{
            break;
        }
    }
    PublicKey = new PaillierPublicKey();
    PublicKey.bitLength = bitLength;
    PublicKey.n = n;
    PublicKey.nsquare = nsquare;
    PublicKey.g = g;

    PrivateKey = new PaillierPrivateKey();
    PrivateKey.bitLength = bitLength;
    PrivateKey.n = n;
    PrivateKey.nsquare = nsquare;
    PrivateKey.lambda = lambda;
    PrivateKey.u = g.modPow(lambda, nsquare).subtract(BigInteger.ONE).divide(n).modInverse(n);
}

//public static void main() throws IOException {
public static void main(String[] str) throws IOException, IllegalBlockSizeException, BadPaddingException {
    PaillierKeyPair pkp = new PaillierKeyPair(1024);

    int data_size = 256; //256*8(bits)>1024(bits)
    byte[] data = new byte[data_size];
    new Random().nextBytes(data);

    /* instantiating two plaintext msgs*/
    BigInteger  m1 = new BigInteger(data);
    BigInteger m2 = BigInteger.valueOf(1);


    /* encryption*/
    System.out.println("start paillier encryption ");


    long enc_time = System.nanoTime();


    BigInteger em1 = pkp.PublicKey.Encryption(m1);
    byte[] encrypted = blockCipher(data, 0, pkp); 

    long endTime_encr = System.nanoTime();


    System.out.println("Encryption : "+(endTime_encr - enc_time)/1000 + " us"); 


    BigInteger em2 = pkp.PublicKey.Encryption(m2);





    System.out.println("start paillier decryption ");



    long decr_time = System.nanoTime();

    BigInteger dm1 = pkp.PrivateKey.Decryption(em1);
    byte[] decrypted = blockCipher(encrypted, 1, pkp); 

    long endTime_decr = System.nanoTime();

    System.out.println("Decryption : "+(endTime_decr - decr_time)/1000 + " us"); 

    byte[] array_d = dm1.toByteArray();



    /* test homomorphic properties -> D(E(m1)*E(m2) mod n^2) = (m1 + m2) mod n */
    BigInteger product_em1em2 = em1.multiply(em2).mod(pkp.PublicKey.nsquare);


}
public class PaillierPrivateKey implements Serializable {

/**
 * number of bits of modulus
 */
public int bitLength;
/**
 * n = p*q, where p and q are two large primes.
 */
public BigInteger n;
/**
 * nsquare = n*n
 */
public BigInteger nsquare;
/**
 * p and q are two large primes.
 * lambda = lcm(p-1, q-1) = (p-1)*(q-1)/gcd(p-1, q-1).
 */
public BigInteger lambda;
/**
 * u = (L(g^lambda mod n^2))^(-1) mod n
 */
public BigInteger u;


public PaillierPrivateKey() {
    // TODO Auto-generated constructor stub
}

/**
 * Decrypts ciphertext c. plaintext m = L(c^lambda mod n^2) * u mod n, where u = (L(g^lambda mod n^2))^(-1) mod n.
 * @param c ciphertext as a BigInteger
 * @return plaintext as a BigInteger
 */
public BigInteger Decryption(BigInteger c) {
    return c.modPow(lambda, nsquare).subtract(BigInteger.ONE).divide(n).multiply(u).mod(n);
}
public class PaillierPublicKey implements Serializable {

/**
 * number of bits of modulus
 */
public int bitLength;
/**
 * n = p*q, where p and q are two large primes.
 */
public BigInteger n;
/**
 * nsquare = n*n
 */
public BigInteger nsquare;
/**
 * a random integer in Z*_{n^2} where gcd (L(g^lambda mod n^2), n) = 1.
 */
public BigInteger g;

public PaillierPublicKey() {
    // TODO Auto-generated constructor stub
}

/**
 * Encrypts plaintext m. ciphertext c = g^m * r^n mod n^2. This function automatically generates random input r (to help with encryption).
 * @param m plaintext as a BigInteger
 * @return ciphertext as a BigInteger
 */
public BigInteger Encryption(BigInteger m) {
    BigInteger r = new BigInteger(bitLength, new SecureRandom());
    return g.modPow(m, nsquare).multiply(r.modPow(n, nsquare)).mod(nsquare);
}

public boolean equals(Object arg0){
    PaillierPublicKey pk = (PaillierPublicKey)arg0;
    if(this.bitLength == pk.bitLength && this.n.equals(pk.n) && this.nsquare.equals(pk.nsquare) && this.g.equals(pk.g)) return true;
    else return false;
}

I tried to make smaller data blocks of the byte array (data), then made those smaller arrays BigInteger and then encrypt them but it didn't work at all. Is there a way to make that possible ?

0

There are 0 answers