Example #1
0
  /**
   * Generates a new key pair given the parameters in fheparams, stores the key locally and in the
   * keypair parameter
   *
   * @param fheparams the scheme parameters
   * @param keyPair holds the keypair
   */
  public GHKeyGen(FHEParams fheparams, GHKeyPair keyPair, IProgressMonitor monitor, int work) {
    t = fheparams.t;
    n = 1 << fheparams.logn;

    SubProgressMonitor sm = new SubProgressMonitor(monitor, work / 3);
    sm.beginTask("", work / 3);
    do { // try until HNF has the desired form, i.e. determinant is odd and lattice contains the
         // vector (-r,1,0,...,0)
      // generate random polynomial with coefficients uniformly random in [-2^t,2^t]
      v = Polynomial.randomPolynomial(n - 1, t);

      // verify whether the coefficient sum is odd, otherwise add 1
      int parity = 0;
      for (int i = 0; i < n; i++) {
        parity ^= (v.coeffs[i].testBit(0) ? 1 : 0);
      }
      if (parity == 0) v.coeffs[0].add(new BigInteger("1"));
      if (sm.isCanceled()) return;

    } while (!invModFx(v, fheparams.logn));
    sm.done();
    sm.beginTask("", work / 3);
    BigInteger sum = new BigInteger("0");
    BigInteger factor;
    // the public key blocks that squash the decryption scheme
    pkBlocksX = new BigInteger[fheparams.s];
    // the correct power such that \sum_pkBlocksX[i]*R^pkBlocksIdX[i] = w mod d
    int[] pkBlocksIdX = new int[fheparams.s];
    // make sure the sum is correct
    boolean sumtest = false;

    while (!sumtest) {
      sum = new BigInteger("0");
      // generate the first s-1 randomly
      for (int i = 0; i < fheparams.s - 1; i++) {
        byte[] temp = new byte[det.bitLength() / 8];
        r.nextBytes(temp);
        pkBlocksX[i] = (new BigInteger(temp)).abs().mod(det);
        pkBlocksIdX[i] = r.nextInt(fheparams.S);
        factor =
            (new BigInteger("2"))
                .modPow(
                    (new BigInteger(Integer.toString(pkBlocksIdX[i])))
                        .multiply(new BigInteger(Integer.toString(fheparams.logR))),
                    det);
        factor = (factor.multiply(pkBlocksX[i])).mod(det);
        sum = (sum.add(factor)).mod(det);
      }
      sum = w.subtract(sum).mod(det);
      // calculate the last x_i from the first s-1, try until the sum is invertible
      while (pkBlocksX[fheparams.s - 1] == null) {
        try {
          pkBlocksIdX[fheparams.s - 1] = r.nextInt(fheparams.S);
          factor =
              new BigInteger("2")
                  .modPow(
                      (new BigInteger(Integer.toString(pkBlocksIdX[fheparams.s - 1])))
                          .multiply(new BigInteger(Integer.toString(fheparams.logR))),
                      det);
          factor = factor.modInverse(det);
          pkBlocksX[fheparams.s - 1] = sum.multiply(factor).mod(det);
        } catch (ArithmeticException e) {

        }
        if (sm.isCanceled()) return;
      }
      // check whether \sum_pkBlocksX[i]*R^pkBlocksIdX[i] = w mod d
      sum = new BigInteger("0");
      for (int i = 0; i < fheparams.s; i++) {
        factor =
            new BigInteger("2")
                .modPow(
                    new BigInteger(Integer.toString(pkBlocksIdX[i]))
                        .multiply(new BigInteger(Integer.toString(fheparams.logR))),
                    det);
        factor = factor.multiply(pkBlocksX[i]).mod(det);
        sum = sum.add(factor).mod(det);
      }
      if (sum.compareTo(w) == 0) {
        sumtest = true;
      }
      if (sm.isCanceled()) return;
    }
    sm.done();
    // Compute the number of ciphertext for each progression,
    // i.e., an integer N such that N(N-1)/2 > S
    sm.beginTask("", work / 3);
    int nCtxts = (int) Math.ceil(2 * Math.sqrt(fheparams.S));
    int[] bits = new int[nCtxts * fheparams.s];
    for (int i = 0; i < fheparams.s; i++) {
      // let j1,j2 be the idx'th pair in {nCtxts choose 2}
      int j1, j2;
      int[] temp = encodeIndex(pkBlocksIdX[i], nCtxts);
      j1 = temp[0];
      j2 = temp[1];
      bits[i * nCtxts + j1] = bits[i * nCtxts + j2] = 1; // set these two bits to one
      if (sm.isCanceled()) return;
    }
    sm.done();
    ctxts = GHEncrypt.encrypt(fheparams, this, bits);
    keyPair.setKeyPair(det, root, w, ctxts, pkBlocksX);
  }