All Downloads are FREE. Search and download functionalities are using the official Maven repository.

paillier.com.unbound.common.crypto.Paillier Maven / Gradle / Ivy

Go to download

This is a collection of JAVA libraries that implement Unbound cryptographic classes for JAVA provider, PKCS11 wrapper, cryptoki, and advapi

There is a newer version: 42761
Show newest version
package com.unbound.common.crypto;

import com.unbound.common.Convertable;
import com.unbound.common.Converter;

import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Random;

public class Paillier implements Convertable
{

  private BigInteger N, NN, p, q, pp, qq, dpp, dqq, qqInv, phiN, invPhiN;

  public BigInteger getP() { return p; }
  public BigInteger getQ() { return q; }
  public BigInteger getPhiN() { return phiN; }
  public BigInteger getNN() { return NN; }
  public BigInteger getInvPhiN() { return invPhiN; }
  public BigInteger getPP() { return pp; }
  public BigInteger getQQ() { return qq; }

  public static Paillier generate(int bits)
  {
    Random random = new SecureRandom();
    BigInteger p = BigInteger.probablePrime(bits/2, random);
    BigInteger q = BigInteger.probablePrime(bits/2, random);
    BigInteger N = p.multiply(q);
    return new Paillier(N, p, q);
  }

  private void init()
  {
    NN = N.multiply(N);
    if (p==null) return;

    phiN = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE)); //phi(N) = (p-1)(q-1)
    invPhiN = phiN.modInverse(N);
    pp = p.multiply(p);
    qq = q.multiply(q);
    qqInv = qq.modInverse(pp);
    dpp = phiN.mod(pp.subtract(p));
    dqq = phiN.mod(qq.subtract(q));
  }

  public Paillier(BigInteger N)
  {
    this.N = N;
    init();
  }

  public BigInteger getPublic() {
    return N;
  }

  private void init(BigInteger N, BigInteger p, BigInteger q)
  {
    this.N = N;
    this.p = p;
    this.q = q;
    init();
  }

  public Paillier(BigInteger N, BigInteger p, BigInteger q)
  {
    this(N);
    this.p = p;
    this.q = q;
    phiN = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE)); //phi(N) = (p-1)(q-1)
    invPhiN = phiN.modInverse(N);
    pp = p.multiply(p);
    qq = q.multiply(q);
    qqInv = qq.modInverse(pp);
    dpp = phiN.mod(pp.subtract(p));
    dqq = phiN.mod(qq.subtract(q));
  }

  public BigInteger encrypt(BigInteger x)
  {
    return encrypt(x, CryptoRandom.generateBigInteger(N));
  }

  public BigInteger encrypt(BigInteger x, BigInteger r)
  {
    return x.multiply(N).mod(NN).add(BigInteger.ONE).multiply(r.modPow(N, NN)).mod(NN);
  }

  public BigInteger decrypt(BigInteger x)
  {
    BigInteger c1 = crtModPow(x, NN, pp, qq, dpp, dqq, qqInv);
    return c1.subtract(BigInteger.ONE).divide(N).multiply(invPhiN).mod(N);
  }

  private static BigInteger crtModPow(BigInteger x, BigInteger N, BigInteger p, BigInteger q, BigInteger dp, BigInteger dq, BigInteger qinv)
  {
    BigInteger m1 = x.modPow(dp, p);
    BigInteger m2 = x.modPow(dq, q);
    return m2.add(qinv.multiply(p.add(m1).subtract(m2)).mod(p).multiply(q));
  }

  @Override
  public void convert(Converter converter)
  {
    int struct = converter.beginStructVersion0();

    boolean hasPrivate = converter.convert(p!=null);
    N = converter.convert(N);

    if (hasPrivate)
    {
      p = converter.convert(p);
      q = converter.convert(q);
    }

    converter.endStruct(struct);

    if (!converter.isWrite())
    {
      if (!hasPrivate) p = q = null;
      init();
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy