예제 #1
0
        public override void PerformTest()
        {
            BigIntEuclidean r = BigIntEuclidean.Calculate(BigInteger.ValueOf(120), BigInteger.ValueOf(23));

            Assert.AreEqual(BigInteger.ValueOf(-9), r.x);
            Assert.AreEqual(BigInteger.ValueOf(47), r.y);
            Assert.AreEqual(BigInteger.ValueOf(1), r.gcd);

            r = BigIntEuclidean.Calculate(BigInteger.ValueOf(126), BigInteger.ValueOf(231));
            Assert.AreEqual(BigInteger.ValueOf(2), r.x);
            Assert.AreEqual(BigInteger.ValueOf(-1), r.y);
            Assert.AreEqual(BigInteger.ValueOf(21), r.gcd);
        }
예제 #2
0
        /// <summary>
        /// Calculates a <c>rho</c> modulo <c>m1*m2</c> from two resultants whose
        /// <c>rho</c>s are modulo <c>m1</c> and <c>m2</c>.
        /// <para><c>res</c> is set to <c>null</c>.</para>
        /// </summary>
        ///
        /// <param name="ModRes1">M1 resultant</param>
        /// <param name="ModRes2">M2 resultant</param>
        ///
        /// <returns><c>Rho</c> modulo <c>modRes1.modulus * modRes2.modulus</c>, and <c>null</c> for <c>res</c></returns>
        public static ModularResultant CombineRho(ModularResultant ModRes1, ModularResultant ModRes2)
        {
            BigInteger      mod1 = ModRes1.m_modulus;
            BigInteger      mod2 = ModRes2.m_modulus;
            BigInteger      prod = mod1.Multiply(mod2);
            BigIntEuclidean er   = BigIntEuclidean.Calculate(mod2, mod1);

            BigIntPolynomial rho1 = ModRes1.Rho.Clone();

            rho1.Multiply(er.X.Multiply(mod2));
            BigIntPolynomial rho2 = ModRes2.Rho.Clone();

            rho2.Multiply(er.Y.Multiply(mod1));
            rho1.Add(rho2);
            rho1.Mod(prod);

            return(new ModularResultant(rho1, null, prod));
        }
예제 #3
0
        /// <summary>
        /// BigIntEuclidean tests
        /// </summary>
        ///
        /// <returns>State</returns>
        public string Test()
        {
            try
            {
                BigIntEuclidean r = BigIntEuclidean.Calculate(BigInteger.ValueOf(120), BigInteger.ValueOf(23));
                if (!BigInteger.ValueOf(-9).Equals(r.X))
                {
                    throw new Exception("BigIntEuclidean failed r.X!");
                }
                if (!BigInteger.ValueOf(47).Equals(r.Y))
                {
                    throw new Exception("BigIntEuclidean failed r.Y!");
                }
                if (!BigInteger.ValueOf(1).Equals(r.GCD))
                {
                    throw new Exception("BigIntEuclidean failed r.GCD!");
                }
                OnProgress(new TestEventArgs("Passed round 1 X, Y and GCD value comparisons"));

                r = BigIntEuclidean.Calculate(BigInteger.ValueOf(126), BigInteger.ValueOf(231));
                if (!BigInteger.ValueOf(2).Equals(r.X))
                {
                    throw new Exception("BigIntEuclidean failed r.X!");
                }
                if (!BigInteger.ValueOf(-1).Equals(r.Y))
                {
                    throw new Exception("BigIntEuclidean failed r.Y!");
                }
                if (!BigInteger.ValueOf(21).Equals(r.GCD))
                {
                    throw new Exception("BigIntEuclidean failed r.GCD!");
                }
                OnProgress(new TestEventArgs("Passed round 2 X, Y and GCD value comparisons"));

                return(SUCCESS);
            }
            catch (Exception Ex)
            {
                string message = Ex.Message == null ? "" : Ex.Message;
                throw new Exception(FAILURE + message);
            }
        }
예제 #4
0
        /**
         * Creates a NtruSign 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         = param.N;
            int       q         = param.q;
            int       d         = param.d;
            int       d1        = param.d1;
            int       d2        = param.d2;
            int       d3        = param.d3;
            BasisType basisType = param.basisType;

            IPolynomial       f;
            IntegerPolynomial fInt;
            IPolynomial       g;
            IntegerPolynomial gInt;
            IntegerPolynomial fq;
            Resultant         rf;
            Resultant         rg;
            BigIntEuclidean   r;

            int  _2n1       = 2 * N + 1;
            bool primeCheck = param.primeCheck;

            Random rng = new Random();

            do
            {
                do
                {
                    if (param.polyType == TernaryPolynomialType.SIMPLE)
                    {
                        f = DenseTernaryPolynomial.GenerateRandom(N, d + 1, d);
                    }
                    else
                    {
                        f = ProductFormPolynomial.GenerateRandom(N, d1, d2, d3 + 1, d3);
                    }
                    fInt = f.ToIntegerPolynomial();
                } while (primeCheck && fInt.Resultant(_2n1).Res.Equals(BigInteger.Zero));
                fq = fInt.InvertFq(q);
            } while (fq == null);
            rf = fInt.Resultant();

            do
            {
                do
                {
                    do
                    {
                        if (param.polyType == TernaryPolynomialType.SIMPLE)
                        {
                            g = DenseTernaryPolynomial.GenerateRandom(N, d + 1, d);
                        }
                        else
                        {
                            g = ProductFormPolynomial.GenerateRandom(N, d1, d2, d3 + 1, d3);
                        }
                        gInt = g.ToIntegerPolynomial();
                    } while (primeCheck && gInt.Resultant(_2n1).Res.Equals(BigInteger.Zero));
                } while (!gInt.IsInvertiblePow2());
                rg = gInt.Resultant();
                r  = BigIntEuclidean.Calculate(rf.Res, rg.Res);
            } while (!r.GCD.Equals(BigInteger.One));

            BigIntPolynomial A = rf.Rho.Clone();

            A.Multiply(r.X.Multiply(BigInteger.ValueOf(q)));
            BigIntPolynomial B = rg.Rho.Clone();

            B.Multiply(r.Y.Multiply(BigInteger.ValueOf(-q)));

            BigIntPolynomial C;

            if (param.keyGenAlg == KeyGenAlg.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.Multiply(fRev);
                t.Add(g.Multiply(gRev));
                Resultant rt = t.Resultant();
                C = fRev.Multiply(B); // fRev.mult(B) is actually faster than new SparseTernaryPolynomial(fRev).mult(B), possibly due to cache locality?
                C.Add(gRev.Multiply(A));
                C = C.MultBig(rt.Rho);
                C.Divide(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.Divide(new BigDecimal(rf.Res), B.GetMaxCoeffLength() + 1 + log10N);
                BigDecimalPolynomial gInv = rg.Rho.Divide(new BigDecimal(rg.Res), A.GetMaxCoeffLength() + 1 + log10N);

                BigDecimalPolynomial Cdec = fInv.Multiply(B);
                Cdec.Add(gInv.Multiply(A));
                Cdec.Halve();
                C = Cdec.Round();
            }

            BigIntPolynomial F = B.Clone();

            F.Subtract(f.Multiply(C));
            BigIntPolynomial G = A.Clone();

            G.Subtract(g.Multiply(C));

            IntegerPolynomial FInt = new IntegerPolynomial(F);
            IntegerPolynomial GInt = new IntegerPolynomial(G);

            minimizeFG(fInt, gInt, FInt, GInt, N);

            IPolynomial       fPrime;
            IntegerPolynomial h;

            if (basisType == BasisType.STANDARD)
            {
                fPrime = FInt;
                h      = g.Multiply(fq, q);
            }
            else
            {
                fPrime = g;
                h      = FInt.Multiply(fq, q);
            }
            h.ModPositive(q);

            return(new FGBasis(f, fPrime, h, FInt, GInt, param.q, param.polyType, param.basisType, param.keyNormBoundSq));
        }
예제 #5
0
        /**
         * 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;
            int        numEqual = 1;        // number of consecutive modular resultants equal to each other

            PrimeGenerator primes = new PrimeGenerator();
            BigInteger     pProd2;
            BigInteger     pProd2n;

            while (true)
            {
                BigInteger       prime = primes.nextPrime();
                ModularResultant crr   = Resultant(prime.IntValue);
                modResultants.AddLast(crr);                 //Was just add in Java

                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;

                pProd2  = pProd.Divide(BigInteger.ValueOf(2));
                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;
                }
            }

            // Combine modular rho's to obtain the final rho.
            // For efficiency, first combine all pairs of small resultants to bigger resultants,
            // then combine pairs of those, etc. until only one is left.
            while (modResultants.Count > 1)
            {
                ModularResultant modRes1 = modResultants.First.Value;
                modResultants.RemoveFirst();
                ModularResultant modRes2 = modResultants.First.Value;
                modResultants.RemoveFirst();
                ModularResultant modRes3 = ModularResultant.CombineRho(modRes1, modRes2);
                modResultants.AddLast(modRes3);
            }
            BigIntPolynomial rhoP = modResultants.First.Value.Rho;

            pProd2  = pProd.Divide(BigInteger.ValueOf(2));
            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));
        }