ch.ge.ve.protopoc.service.algorithm.PolynomialAlgorithms.java Source code

Java tutorial

Introduction

Here is the source code for ch.ge.ve.protopoc.service.algorithm.PolynomialAlgorithms.java

Source

/*-------------------------------------------------------------------------------------------------
 - #%L                                                                                            -
 - chvote-protocol-poc                                                                            -
 - %%                                                                                             -
 - Copyright (C) 2016 - 2017 Rpublique et Canton de Genve                                       -
 - %%                                                                                             -
 - This program is free software: you can redistribute it and/or modify                           -
 - it under the terms of the GNU Affero General Public License as published by                    -
 - the Free Software Foundation, either version 3 of the License, or                              -
 - (at your option) any later version.                                                            -
 -                                                                                                -
 - This program is distributed in the hope that it will be useful,                                -
 - but WITHOUT ANY WARRANTY; without even the implied warranty of                                 -
 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                                   -
 - GNU General Public License for more details.                                                   -
 -                                                                                                -
 - You should have received a copy of the GNU Affero General Public License                       -
 - along with this program. If not, see <http://www.gnu.org/licenses/>.                           -
 - #L%                                                                                            -
 -------------------------------------------------------------------------------------------------*/

package ch.ge.ve.protopoc.service.algorithm;

import ch.ge.ve.protopoc.service.model.PrimeField;
import ch.ge.ve.protopoc.service.model.polynomial.Point;
import ch.ge.ve.protopoc.service.model.polynomial.PointsAndZeroImages;
import ch.ge.ve.protopoc.service.support.RandomGenerator;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * This class holds the parameters and the methods / algorithms applicable to polynomials
 */
public class PolynomialAlgorithms {
    private static final Logger log = LoggerFactory.getLogger(PolynomialAlgorithms.class);
    private final RandomGenerator randomGenerator;
    private final PrimeField primeField;

    public PolynomialAlgorithms(RandomGenerator randomGenerator, PrimeField primeField) {
        this.randomGenerator = randomGenerator;
        this.primeField = primeField;
    }

    /**
     * Algorithm 7.7: GenPoints
     *
     * @param bold_n the vector containing the number of candidates per election
     * @param bold_k the vector containing the number of allowed selections per election
     * @return a list of <i>bold_n</i> random points picked from <i>t</i> different polynomials, along with the image of 0 for each polynomial
     */
    public PointsAndZeroImages genPoints(List<Integer> bold_n, List<Integer> bold_k) {
        Preconditions.checkArgument(bold_n.size() == bold_k.size(),
                String.format("|bold_n| [%d] != |bold_k| [%d]", bold_n.size(), bold_k.size()));
        for (int i = 0; i < bold_n.size(); i++) {
            Preconditions.checkArgument(bold_n.get(i) > bold_k.get(i),
                    String.format("n_%1$d [%2$d] <= k_%1$d [%3$d]", i, bold_n.get(i), bold_k.get(i)));
        }
        List<Point> bold_p = new ArrayList<>();
        List<BigInteger> bold_y = new ArrayList<>();
        int i = 0; // (used as subscript for x_i, y_i)
        // loop on election: index j (hence the a_j symbol)
        for (int j = 0; j < bold_n.size(); j++) {
            Set<BigInteger> upper_x = new HashSet<>();
            List<BigInteger> bold_a_j = genPolynomial(bold_k.get(j) - 1);
            for (int l = 0; l < bold_n.get(j); l++) {
                BigInteger x;
                do {
                    x = randomGenerator.randomInZq(primeField.getP_prime());
                } while (x.compareTo(BigInteger.ZERO) == 0 || upper_x.contains(x));
                upper_x.add(x);
                BigInteger y = getYValue(x, bold_a_j);
                Point p_i = new Point(x, y);
                bold_p.add(p_i);
                log.debug(String.format("Created point %d: %s", i, p_i));
                i++;
            }
            bold_y.add(getYValue(BigInteger.ZERO, bold_a_j));
        }
        return new PointsAndZeroImages(bold_p, bold_y);
    }

    /**
     * Algorithm 7.8: GenPolynomial
     *
     * @param d the degree of the polynomial (-1 means a 0 constant)
     * @return the list of coefficients of a random polynomial p(X) = \sum(i=1,d){a_i*X^i mod p'}
     */
    public List<BigInteger> genPolynomial(int d) {
        Preconditions.checkArgument(d >= -1,
                String.format("Value of d should be greater or equal to -1 (it is [%d]", d));
        List<BigInteger> bold_a = new ArrayList<>();
        if (d == -1) {
            bold_a.add(BigInteger.ZERO);
        } else {
            for (int i = 0; i <= d - 1; i++) {
                bold_a.add(randomGenerator.randomInZq(primeField.getP_prime()));
            }
            // a_d \isin Z_p_prime \ {0}
            bold_a.add(randomGenerator.
            // random in range 0 - p'-2
                    randomInZq(primeField.getP_prime().subtract(BigInteger.ONE))
                    // --> random in range 1 - p'-1
                    .add(BigInteger.ONE));
        }
        return bold_a;
    }

    /**
     * Algorithm 7.9: GetYValue
     * <p>Generates the coefficients a_0, ..., a_d of a random polynomial</p>
     *
     * @param x value in Z_p_prime
     * @param bold_a the coefficients of the polynomial
     * @return the computed value y
     */
    public BigInteger getYValue(BigInteger x, List<BigInteger> bold_a) {
        Preconditions.checkArgument(bold_a.size() >= 1, String
                .format("The size of bold_a should always be larger or equal to 1 (it is [%d]", bold_a.size()));
        if (x.equals(BigInteger.ZERO)) {
            return bold_a.get(0);
        } else {
            BigInteger y = BigInteger.ZERO;
            for (BigInteger a_i : Lists.reverse(bold_a)) {
                y = a_i.add(x.multiply(y).mod(primeField.getP_prime())).mod(primeField.getP_prime());
            }
            return y;
        }
    }

}