Search in sources :

Example 1 with BigIntEuclidean

use of com.github.zhenwei.core.pqc.math.ntru.euclid.BigIntEuclidean in project LinLong-Java by zhenwei1108.

the class ModularResultant method combineRho.

/**
 * Calculates a <code>rho</code> modulo <code>m1*m2</code> from two resultants whose
 * <code>rho</code>s are modulo <code>m1</code> and <code>m2</code>.<br/>
 * </code>res</code> is set to <code>null</code>.
 *
 * @param modRes1
 * @param modRes2
 * @return <code>rho</code> modulo <code>modRes1.modulus * modRes2.modulus</code>, and
 * <code>null</code> for </code>res</code>.
 */
static ModularResultant combineRho(ModularResultant modRes1, ModularResultant modRes2) {
    BigInteger mod1 = modRes1.modulus;
    BigInteger mod2 = modRes2.modulus;
    BigInteger prod = mod1.multiply(mod2);
    BigIntEuclidean er = BigIntEuclidean.calculate(mod2, mod1);
    BigIntPolynomial rho1 = (BigIntPolynomial) modRes1.rho.clone();
    rho1.mult(er.x.multiply(mod2));
    BigIntPolynomial rho2 = (BigIntPolynomial) modRes2.rho.clone();
    rho2.mult(er.y.multiply(mod1));
    rho1.add(rho2);
    rho1.mod(prod);
    return new ModularResultant(rho1, null, prod);
}
Also used : BigIntEuclidean(com.github.zhenwei.core.pqc.math.ntru.euclid.BigIntEuclidean) BigInteger(java.math.BigInteger)

Example 2 with BigIntEuclidean

use of com.github.zhenwei.core.pqc.math.ntru.euclid.BigIntEuclidean in project LinLong-Java by zhenwei1108.

the class NTRUSigningKeyPairGenerator method generateBasis.

/**
 * Creates a NTRUSigner basis consisting of polynomials <code>f, g, F, G, h</code>.<br/> If
 * <code>KeyGenAlg=FLOAT</code>, the basis may not be valid and this method must be rerun if that
 * is the case.<br/>
 *
 * @see #generateBoundedBasis()
 */
private FGBasis generateBasis() {
    int N = params.N;
    int q = params.q;
    int d = params.d;
    int d1 = params.d1;
    int d2 = params.d2;
    int d3 = params.d3;
    int basisType = params.basisType;
    Polynomial f;
    IntegerPolynomial fInt;
    Polynomial g;
    IntegerPolynomial gInt;
    IntegerPolynomial fq;
    Resultant rf;
    Resultant rg;
    BigIntEuclidean r;
    int _2n1 = 2 * N + 1;
    boolean primeCheck = params.primeCheck;
    do {
        do {
            f = params.polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE ? DenseTernaryPolynomial.generateRandom(N, d + 1, d, CryptoServicesRegistrar.getSecureRandom()) : ProductFormPolynomial.generateRandom(N, d1, d2, d3 + 1, d3, CryptoServicesRegistrar.getSecureRandom());
            fInt = f.toIntegerPolynomial();
        } while (primeCheck && fInt.resultant(_2n1).res.equals(ZERO));
        fq = fInt.invertFq(q);
    } while (fq == null);
    rf = fInt.resultant();
    do {
        do {
            do {
                g = params.polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE ? DenseTernaryPolynomial.generateRandom(N, d + 1, d, CryptoServicesRegistrar.getSecureRandom()) : ProductFormPolynomial.generateRandom(N, d1, d2, d3 + 1, d3, CryptoServicesRegistrar.getSecureRandom());
                gInt = g.toIntegerPolynomial();
            } while (primeCheck && gInt.resultant(_2n1).res.equals(ZERO));
        } while (gInt.invertFq(q) == null);
        rg = gInt.resultant();
        r = BigIntEuclidean.calculate(rf.res, rg.res);
    } while (!r.gcd.equals(ONE));
    BigIntPolynomial A = (BigIntPolynomial) rf.rho.clone();
    A.mult(r.x.multiply(BigInteger.valueOf(q)));
    BigIntPolynomial B = (BigIntPolynomial) rg.rho.clone();
    B.mult(r.y.multiply(BigInteger.valueOf(-q)));
    BigIntPolynomial C;
    if (params.keyGenAlg == NTRUSigningKeyGenerationParameters.KEY_GEN_ALG_RESULTANT) {
        int[] fRevCoeffs = new int[N];
        int[] gRevCoeffs = new int[N];
        fRevCoeffs[0] = fInt.coeffs[0];
        gRevCoeffs[0] = gInt.coeffs[0];
        for (int i = 1; i < N; i++) {
            fRevCoeffs[i] = fInt.coeffs[N - i];
            gRevCoeffs[i] = gInt.coeffs[N - i];
        }
        IntegerPolynomial fRev = new IntegerPolynomial(fRevCoeffs);
        IntegerPolynomial gRev = new IntegerPolynomial(gRevCoeffs);
        IntegerPolynomial t = f.mult(fRev);
        t.add(g.mult(gRev));
        Resultant rt = t.resultant();
        C = fRev.mult(// fRev.mult(B) is actually faster than new SparseTernaryPolynomial(fRev).mult(B), possibly due to cache locality?
        B);
        C.add(gRev.mult(A));
        C = C.mult(rt.rho);
        C.div(rt.res);
    } else {
        // KeyGenAlg.FLOAT
        // calculate ceil(log10(N))
        int log10N = 0;
        for (int i = 1; i < N; i *= 10) {
            log10N++;
        }
        // * Cdec needs to be accurate to 1 decimal place so it can be correctly rounded;
        // * fInv loses up to (#digits of longest coeff of B) places in fInv.mult(B);
        // * multiplying fInv by B also multiplies the rounding error by a factor of N;
        // so make #decimal places of fInv the sum of the above.
        BigDecimalPolynomial fInv = rf.rho.div(new BigDecimal(rf.res), B.getMaxCoeffLength() + 1 + log10N);
        BigDecimalPolynomial gInv = rg.rho.div(new BigDecimal(rg.res), A.getMaxCoeffLength() + 1 + log10N);
        BigDecimalPolynomial Cdec = fInv.mult(B);
        Cdec.add(gInv.mult(A));
        Cdec.halve();
        C = Cdec.round();
    }
    BigIntPolynomial F = (BigIntPolynomial) B.clone();
    F.sub(f.mult(C));
    BigIntPolynomial G = (BigIntPolynomial) A.clone();
    G.sub(g.mult(C));
    IntegerPolynomial FInt = new IntegerPolynomial(F);
    IntegerPolynomial GInt = new IntegerPolynomial(G);
    minimizeFG(fInt, gInt, FInt, GInt, N);
    Polynomial fPrime;
    IntegerPolynomial h;
    if (basisType == NTRUSigningKeyGenerationParameters.BASIS_TYPE_STANDARD) {
        fPrime = FInt;
        h = g.mult(fq, q);
    } else {
        fPrime = g;
        h = FInt.mult(fq, q);
    }
    h.modPositive(q);
    return new FGBasis(f, fPrime, h, FInt, GInt, params);
}
Also used : BigDecimalPolynomial(com.github.zhenwei.core.pqc.math.ntru.polynomial.BigDecimalPolynomial) DenseTernaryPolynomial(com.github.zhenwei.core.pqc.math.ntru.polynomial.DenseTernaryPolynomial) ProductFormPolynomial(com.github.zhenwei.core.pqc.math.ntru.polynomial.ProductFormPolynomial) BigIntPolynomial(com.github.zhenwei.core.pqc.math.ntru.polynomial.BigIntPolynomial) IntegerPolynomial(com.github.zhenwei.core.pqc.math.ntru.polynomial.IntegerPolynomial) Polynomial(com.github.zhenwei.core.pqc.math.ntru.polynomial.Polynomial) BigDecimalPolynomial(com.github.zhenwei.core.pqc.math.ntru.polynomial.BigDecimalPolynomial) Resultant(com.github.zhenwei.core.pqc.math.ntru.polynomial.Resultant) BigIntEuclidean(com.github.zhenwei.core.pqc.math.ntru.euclid.BigIntEuclidean) IntegerPolynomial(com.github.zhenwei.core.pqc.math.ntru.polynomial.IntegerPolynomial) BigIntPolynomial(com.github.zhenwei.core.pqc.math.ntru.polynomial.BigIntPolynomial) BigDecimal(java.math.BigDecimal)

Example 3 with BigIntEuclidean

use of com.github.zhenwei.core.pqc.math.ntru.euclid.BigIntEuclidean in project LinLong-Java by zhenwei1108.

the class IntegerPolynomial method resultant.

/**
 * Resultant of this polynomial with <code>x^n-1</code> using a probabilistic algorithm.
 * <p>
 * Unlike EESS, this implementation does not compute all resultants modulo primes such that their
 * product exceeds the maximum possible resultant, but rather stops when
 * <code>NUM_EQUAL_RESULTANTS</code> consecutive modular resultants are equal.<br> This means the
 * return value may be incorrect. Experiments show this happens in about 1 out of 100 cases when
 * <code>N=439</code> and <code>NUM_EQUAL_RESULTANTS=2</code>, so the likelyhood of leaving the
 * loop too early is <code>(1/100)^(NUM_EQUAL_RESULTANTS-1)</code>.
 * <p>
 * Because of the above, callers must verify the output and try a different polynomial if
 * necessary.
 *
 * @return <code>(rho, res)</code> satisfying <code>res = rho*this + t*(x^n-1)</code> for some
 * integer <code>t</code>.
 */
public Resultant resultant() {
    int N = coeffs.length;
    // Compute resultants modulo prime numbers. Continue until NUM_EQUAL_RESULTANTS consecutive modular resultants are equal.
    LinkedList<ModularResultant> modResultants = new LinkedList<ModularResultant>();
    BigInteger pProd = Constants.BIGINT_ONE;
    BigInteger res = Constants.BIGINT_ONE;
    // number of consecutive modular resultants equal to each other
    int numEqual = 1;
    PrimeGenerator primes = new PrimeGenerator();
    while (true) {
        BigInteger prime = primes.nextPrime();
        ModularResultant crr = resultant(prime.intValue());
        modResultants.add(crr);
        BigInteger temp = pProd.multiply(prime);
        BigIntEuclidean er = BigIntEuclidean.calculate(prime, pProd);
        BigInteger resPrev = res;
        res = res.multiply(er.x.multiply(prime));
        BigInteger res2 = crr.res.multiply(er.y.multiply(pProd));
        res = res.add(res2).mod(temp);
        pProd = temp;
        BigInteger pProd2 = pProd.divide(BigInteger.valueOf(2));
        BigInteger pProd2n = pProd2.negate();
        if (res.compareTo(pProd2) > 0) {
            res = res.subtract(pProd);
        } else if (res.compareTo(pProd2n) < 0) {
            res = res.add(pProd);
        }
        if (res.equals(resPrev)) {
            numEqual++;
            if (numEqual >= NUM_EQUAL_RESULTANTS) {
                break;
            }
        } else {
            numEqual = 1;
        }
    }
    // then combine pairs of those, etc. until only one is left.
    while (modResultants.size() > 1) {
        ModularResultant modRes1 = modResultants.removeFirst();
        ModularResultant modRes2 = modResultants.removeFirst();
        ModularResultant modRes3 = ModularResultant.combineRho(modRes1, modRes2);
        modResultants.addLast(modRes3);
    }
    BigIntPolynomial rhoP = modResultants.getFirst().rho;
    BigInteger pProd2 = pProd.divide(BigInteger.valueOf(2));
    BigInteger pProd2n = pProd2.negate();
    if (res.compareTo(pProd2) > 0) {
        res = res.subtract(pProd);
    }
    if (res.compareTo(pProd2n) < 0) {
        res = res.add(pProd);
    }
    for (int i = 0; i < N; i++) {
        BigInteger c = rhoP.coeffs[i];
        if (c.compareTo(pProd2) > 0) {
            rhoP.coeffs[i] = c.subtract(pProd);
        }
        if (c.compareTo(pProd2n) < 0) {
            rhoP.coeffs[i] = c.add(pProd);
        }
    }
    return new Resultant(rhoP, res);
}
Also used : BigIntEuclidean(com.github.zhenwei.core.pqc.math.ntru.euclid.BigIntEuclidean) BigInteger(java.math.BigInteger) LinkedList(java.util.LinkedList)

Aggregations

BigIntEuclidean (com.github.zhenwei.core.pqc.math.ntru.euclid.BigIntEuclidean)3 BigInteger (java.math.BigInteger)2 BigDecimalPolynomial (com.github.zhenwei.core.pqc.math.ntru.polynomial.BigDecimalPolynomial)1 BigIntPolynomial (com.github.zhenwei.core.pqc.math.ntru.polynomial.BigIntPolynomial)1 DenseTernaryPolynomial (com.github.zhenwei.core.pqc.math.ntru.polynomial.DenseTernaryPolynomial)1 IntegerPolynomial (com.github.zhenwei.core.pqc.math.ntru.polynomial.IntegerPolynomial)1 Polynomial (com.github.zhenwei.core.pqc.math.ntru.polynomial.Polynomial)1 ProductFormPolynomial (com.github.zhenwei.core.pqc.math.ntru.polynomial.ProductFormPolynomial)1 Resultant (com.github.zhenwei.core.pqc.math.ntru.polynomial.Resultant)1 BigDecimal (java.math.BigDecimal)1 LinkedList (java.util.LinkedList)1