Beispiel #1
0
        public void testMult()
        {
            BigDecimalPolynomial a = new BigDecimalPolynomial(new BigIntPolynomial(new IntegerPolynomial(new int[] { 4, -1, 9, 2, 1, -5, 12, -7, 0, -9, 5 })));
            BigDecimalPolynomial b = new BigDecimalPolynomial(new BigIntPolynomial(new IntegerPolynomial(new int[] { -6, 0, 0, 13, 3, -2, -4, 10, 11, 2, -1 })));
            BigDecimalPolynomial c = a.Multiply(b);

            decimal[] expectedCoeffs = new BigDecimalPolynomial(new BigIntPolynomial(new IntegerPolynomial(new int[] { 2, -189, 77, 124, -29, 0, -75, 124, -49, 267, 34 }))).getCoeffs();

            decimal[] cCoeffs = c.getCoeffs();

            Assert.AreEqual(expectedCoeffs.Length, cCoeffs.Length);
            for (int i = 0; i != cCoeffs.Length; i++)
            {
                Assert.AreEqual(expectedCoeffs[i], cCoeffs[i]);
            }

            // multiply a polynomial by its inverse modulo 2048 and check that the result is 1
            SecureRandom      random = new SecureRandom();
            IntegerPolynomial d, dInv;

            do
            {
                d    = DenseTernaryPolynomial.GenerateRandom(1001, 333, 334, random);
                dInv = d.InvertFq(2048);
            }while (dInv == null);

            d.Mod(2048);
            BigDecimalPolynomial e = new BigDecimalPolynomial(new BigIntPolynomial(d));
            BigIntPolynomial     f = new BigIntPolynomial(dInv);
            IntegerPolynomial    g = new IntegerPolynomial(e.Multiply(f).round());

            g.ModPositive(2048);
            Assert.True(g.EqualsOne());
        }
Beispiel #2
0
        /// <summary>
        /// Deterministically generates a blinding polynomial from a seed and a message representative
        /// </summary>
        ///
        /// <param name="Seed">The seed value</param>
        ///
        /// <returns>A blinding polynomial</returns>
        private IPolynomial GenerateBlindingPoly(byte[] Seed)
        {
            int            N  = _encParams.N;
            IndexGenerator ig = new IndexGenerator(Seed, _encParams);

            if (_encParams.PolyType == TernaryPolynomialType.PRODUCT) //.8, .6
            {
                SparseTernaryPolynomial r1 = SparseTernaryPolynomial.GenerateBlindingPoly(ig, N, _encParams.DR1);
                SparseTernaryPolynomial r2 = SparseTernaryPolynomial.GenerateBlindingPoly(ig, N, _encParams.DR2);
                SparseTernaryPolynomial r3 = SparseTernaryPolynomial.GenerateBlindingPoly(ig, N, _encParams.DR3);

                return(new ProductFormPolynomial(r1, r2, r3));
            }
            else
            {
                if (_encParams.Sparse)
                {
                    return(SparseTernaryPolynomial.GenerateBlindingPoly(ig, N, _encParams.DR));
                }
                else
                {
                    return(DenseTernaryPolynomial.GenerateBlindingPoly(ig, N, _encParams.DR));
                }
            }
        }
Beispiel #3
0
        public void testInvertFq()
        {
            SecureRandom random = new SecureRandom();
            // Verify an example from the NTRU tutorial
            IntegerPolynomial a = new IntegerPolynomial(new int[] { -1, 1, 1, 0, -1, 0, 1, 0, 0, 1, -1 });
            IntegerPolynomial b = a.InvertFq(32);

            assertEqualsMod(new int[] { 5, 9, 6, 16, 4, 15, 16, 22, 20, 18, 30 }, b.coeffs, 32);
            verifyInverse(a, b, 32);

            // test 3 random polynomials
            int numInvertible = 0;

            while (numInvertible < 3)
            {
                a = DenseTernaryPolynomial.GenerateRandom(853, random);
                b = a.InvertFq(2048);
                if (b != null)
                {
                    numInvertible++;
                    verifyInverse(a, b, 2048);
                }
            }

            // test a non-invertible polynomial
            a = new IntegerPolynomial(new int[] { -1, 0, 1, 1, 0, 0, -1, 0, -1, 0, 1 });
            b = a.InvertFq(32);
            Assert.IsNull(b);
        }
 private void CheckTernarity(DenseTernaryPolynomial poly)
 {
     if (!poly.IsTernary())
     {
         throw new Exception("DenseTernaryPolynomial CheckTernarity test failed!");
     }
 }
Beispiel #5
0
        public void testResultant()
        {
            SecureRandom random = new SecureRandom();
            NTRUSigningKeyGenerationParameters parameters = NTRUSigningKeyGenerationParameters.APR2011_439;
            IntegerPolynomial a = DenseTernaryPolynomial.GenerateRandom(parameters.N, parameters.d, parameters.d, random);
            Resultant         r = a.Resultant();

            if (r.Rho.GetCoeffs().Length > parameters.N)
            {
                BigInteger[] trimmedArray = new BigInteger[parameters.N];
                Array.Copy(r.Rho.GetCoeffs(), trimmedArray, parameters.N);
                r.Rho.coeffs = trimmedArray;
            }
            verifyResultant(a, r);

            a = new IntegerPolynomial(new int[] { 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 1, -1, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, -1, -1, 0, -1, 1, -1, 0, -1, 0, -1, -1, -1, 0, 0, 0, 1, 1, -1, -1, -1, 0, -1, -1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 1, 1, -1, 0, 1, -1, 0, 1, 0, 1, 0, -1, -1, 0, 1, 0, -1, 1, 1, 1, 1, 0, 0, -1, -1, 1, 0, 0, -1, -1, 0, -1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 1, 0, 1, -1, 0, 0, 1, 1, 1, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0, -1, -1, 0, -1, -1, -1, 0, -1, -1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, -1, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, -1, -1, 0, -1, -1, 1, 1, 0, 0, -1, 1, 0, 0, 0, -1, 1, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 1, 1, 0, 0, -1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, -1, 0, 1, 0, -1, -1, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 1, -1, 1, -1, -1, 1, -1, 0, 1, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, -1, 0, 1, -1, 0, 0, 1, 1, 0, 0, 1, 1, 0, -1, 0, -1, 1, -1, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 1, -1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, -1, -1, 0, 0, -1, 0, 1, 1, -1, 1, -1, 0, 0, 0, 1 });

            r = a.Resultant();
            if (r.Rho.GetCoeffs().Length > a.coeffs.Length)
            {
                BigInteger[] trimmedArray = new BigInteger[a.coeffs.Length];
                Array.Copy(r.Rho.GetCoeffs(), trimmedArray, a.coeffs.Length);
                r.Rho.coeffs = trimmedArray;
            }
            verifyResultant(a, r);
        }
Beispiel #6
0
        public void testFromToBinary3Tight()
        {
            int[]             c     = new int[] { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 1, 0, 1, 0, -1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0 };
            IntegerPolynomial poly1 = new IntegerPolynomial(c);
            IntegerPolynomial poly2 = IntegerPolynomial.FromBinary3Tight(poly1.ToBinary3Tight(), c.Length);

            Assert.True(poly1.coeffs.SequenceEqual(poly2.coeffs));

            IntegerPolynomial poly3 = new IntegerPolynomial(new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, -1, -1, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 });

            byte[]            arr   = poly3.ToBinary3Tight();
            IntegerPolynomial poly4 = IntegerPolynomial.FromBinary3Tight(arr, 1499);

            Assert.True(poly3.coeffs.SequenceEqual(poly4.coeffs));

            IntegerPolynomial poly5 = new IntegerPolynomial(new int[] { 0, 0, 0, 1, -1, -1, -1 });

            arr = poly5.ToBinary3Tight();
            IntegerPolynomial poly6 = IntegerPolynomial.FromBinary3Tight(arr, 7);

            Assert.True(poly5.coeffs.SequenceEqual(poly6.coeffs));

            SecureRandom random = new SecureRandom();

            for (int i = 0; i < 100; i++)
            {
                IntegerPolynomial poly7 = DenseTernaryPolynomial.GenerateRandom(157, random);
                arr = poly7.ToBinary3Tight();
                IntegerPolynomial poly8 = IntegerPolynomial.FromBinary3Tight(arr, 157);
                Assert.True(poly7.coeffs.SequenceEqual(poly8.coeffs));
            }
        }
        public void testEncodeDecodeMod3Tight()
        {
            SecureRandom random = new SecureRandom();

            int[]  coeffs  = DenseTernaryPolynomial.GenerateRandom(1000, random).coeffs;
            byte[] data    = ArrayEncoder.EncodeMod3Tight(coeffs);
            int[]  coeffs2 = ArrayEncoder.DecodeMod3Tight(data, 1000);
            Assert.True(coeffs.SequenceEqual(coeffs2));
        }
Beispiel #8
0
        /// <summary>
        /// Read a Private key from a stream
        /// </summary>
        ///
        /// <param name="KeyStream">The stream containing the key</param>
        ///
        /// <returns>An initialized NTRUPrivateKey class</returns>
        ///
        /// <exception cref="NTRUException">Thrown if the stream can not be read</exception>
        public static NTRUPrivateKey From(MemoryStream KeyStream)
        {
            BinaryReader dataStream = new BinaryReader(KeyStream);

            try
            {
                // ins.Position = 0; wrong here, ins pos is wrong
                int         n      = IntUtils.ReadShort(KeyStream);
                int         q      = IntUtils.ReadShort(KeyStream);
                byte        flags  = dataStream.ReadByte();
                bool        sparse = (flags & 1) != 0;
                bool        fastFp = (flags & 2) != 0;
                IPolynomial t;

                TernaryPolynomialType polyType = (flags & 4) == 0 ?
                                                 TernaryPolynomialType.SIMPLE :
                                                 TernaryPolynomialType.PRODUCT;

                if (polyType == TernaryPolynomialType.PRODUCT)
                {
                    t = ProductFormPolynomial.FromBinary(KeyStream, n);
                }
                else
                {
                    IntegerPolynomial fInt = IntegerPolynomial.FromBinary3Tight(KeyStream, n);

                    if (sparse)
                    {
                        t = new SparseTernaryPolynomial(fInt);
                    }
                    else
                    {
                        t = new DenseTernaryPolynomial(fInt);
                    }
                }

                // Initializes fp from t
                IntegerPolynomial fp;
                if (fastFp)
                {
                    fp           = new IntegerPolynomial(n);
                    fp.Coeffs[0] = 1;
                }
                else
                {
                    fp = t.ToIntegerPolynomial().InvertF3();
                }

                return(new NTRUPrivateKey(t, fp, n, q, sparse, fastFp, polyType));
            }
            catch (IOException ex)
            {
                throw new NTRUException("NTRUPrivateKey:From", ex.Message, ex);
            }
        }
Beispiel #9
0
 /**
  * Generates a "sparse" or "dense" polynomial containing numOnes ints equal to 1,
  * numNegOnes int equal to -1, and the rest equal to 0.
  *
  * @param N
  * @param numOnes
  * @param numNegOnes
  * @param sparse     whether to create a {@link SparseTernaryPolynomial} or {@link DenseTernaryPolynomial}
  * @return a ternary polynomial
  */
 public static ITernaryPolynomial GenerateRandomTernary(int N, int numOnes, int numNegOnes, bool sparse, SecureRandom random)
 {
     if (sparse)
     {
         return(SparseTernaryPolynomial.GenerateRandom(N, numOnes, numNegOnes, random));
     }
     else
     {
         return(DenseTernaryPolynomial.GenerateRandom(N, numOnes, numNegOnes, random));
     }
 }
        private void testMult(int[] coeffs1, int[] coeffs2)
        {
            IntegerPolynomial i1 = new IntegerPolynomial(coeffs1);
            IntegerPolynomial i2 = new IntegerPolynomial(coeffs2);

            LongPolynomial5        a  = new LongPolynomial5(i1);
            DenseTernaryPolynomial b  = new DenseTernaryPolynomial(i2);
            IntegerPolynomial      c1 = i1.Multiply(i2, 2048);
            IntegerPolynomial      c2 = a.Multiply(b).ToIntegerPolynomial();

            assertEqualsMod(c1.coeffs, c2.coeffs, 2048);
        }
Beispiel #11
0
        private void MultTest(int[] coeffs1, int[] coeffs2)
        {
            IntegerPolynomial      i1 = new IntegerPolynomial(coeffs1);
            IntegerPolynomial      i2 = new IntegerPolynomial(coeffs2);
            LongPolynomial5        a  = new LongPolynomial5(i1);
            DenseTernaryPolynomial b  = new DenseTernaryPolynomial(i2);
            IntegerPolynomial      c1 = i1.Multiply(i2, 2048);
            IntegerPolynomial      c2 = a.Multiply(b).ToIntegerPolynomial();

            if (!EqualsMod(c1.Coeffs, c2.Coeffs, 2048))
            {
                throw new Exception("LongPolynomial5 multiply test failed!");
            }
        }
        /// <remarks>
        /// Generates the ephemeral secret polynomial 'g'.
        /// </remarks>
        private IntegerPolynomial GenerateG(IRandom Rng)
        {
            int N  = _encParams.N;
            int dg = _encParams.Dg;

            while (true)
            {
                DenseTernaryPolynomial g = DenseTernaryPolynomial.GenerateRandom(N, dg, dg - 1, Rng);

                if (g.IsInvertiblePow2())
                {
                    return(g);
                }
            }
        }
Beispiel #13
0
        /// <remarks>
        /// Generates the ephemeral secret polynomial 'g'.
        /// </remarks>
        private IntegerPolynomial GenerateG(IRandom RngEngine)
        {
            var N  = this.m_ntruParams.N;
            var dg = this.m_ntruParams.Dg;

            while (true)
            {
                var g = DenseTernaryPolynomial.GenerateRandom(N, dg, dg - 1, RngEngine);

                if (g.IsInvertiblePow2())
                {
                    return(g);
                }
            }
        }
Beispiel #14
0
        public void testResultantMod()
        {
            int p = 46337;               // prime; must be less than sqrt(2^31) or integer overflows will occur

            IntegerPolynomial a = new IntegerPolynomial(new int[] { 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 1, -1, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, -1, -1, 0, -1, 1, -1, 0, -1, 0, -1, -1, -1, 0, 0, 0, 1, 1, -1, -1, -1, 0, -1, -1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 1, 1, -1, 0, 1, -1, 0, 1, 0, 1, 0, -1, -1, 0, 1, 0, -1, 1, 1, 1, 1, 0, 0, -1, -1, 1, 0, 0, -1, -1, 0, -1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 1, 0, 1, -1, 0, 0, 1, 1, 1, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0, -1, -1, 0, -1, -1, -1, 0, -1, -1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, -1, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, -1, -1, 0, -1, -1, 1, 1, 0, 0, -1, 1, 0, 0, 0, -1, 1, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 1, 1, 0, 0, -1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, -1, 0, 1, 0, -1, -1, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 1, -1, 1, -1, -1, 1, -1, 0, 1, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, -1, 0, 1, -1, 0, 0, 1, 1, 0, 0, 1, 1, 0, -1, 0, -1, 1, -1, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 1, -1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, -1, -1, 0, 0, -1, 0, 1, 1, -1, 1, -1, 0, 0, 0, 1 });

            verifyResultant(a, a.Resultant(p), p);

            SecureRandom random = new SecureRandom();

            for (int i = 0; i < 10; i++)
            {
                a = DenseTernaryPolynomial.GenerateRandom(853, random);
                verifyResultant(a, a.Resultant(p), p);
            }
        }
        /**
         * tests mult(IntegerPolynomial) and mult(BigIntPolynomial)
         */
        public void testMult()
        {
            SecureRandom            random = new SecureRandom();
            SparseTernaryPolynomial p1     = SparseTernaryPolynomial.GenerateRandom(1000, 500, 500, random);
            IntegerPolynomial       p2     = DenseTernaryPolynomial.GenerateRandom(1000, random);

            IntegerPolynomial prod1 = p1.Multiply(p2);
            IntegerPolynomial prod2 = p1.Multiply(p2);

            Assert.AreEqual(prod1.coeffs, prod2.coeffs);

            BigIntPolynomial p3    = new BigIntPolynomial(p2);
            BigIntPolynomial prod3 = p1.Multiply(p3);

            Assert.AreEqual((new BigIntPolynomial(prod1)).coeffs, prod3.coeffs);
        }
        /// <summary>
        /// Test the validity of the BigDecimalPolynomial implementation
        /// </summary>
        ///
        /// <returns>State</returns>
        public string Test()
        {
            try
            {
                BigDecimalPolynomial a = CreateBigDecimalPolynomial(new int[] { 4, -1, 9, 2, 1, -5, 12, -7, 0, -9, 5 });
                BigIntPolynomial     b = new BigIntPolynomial(new IntegerPolynomial(new int[] { -6, 0, 0, 13, 3, -2, -4, 10, 11, 2, -1 }));
                BigDecimalPolynomial c = a.Multiply(b);
                if (!Compare.AreEqual(c.Coeffs, CreateBigDecimalPolynomial(new int[] { 2, -189, 77, 124, -29, 0, -75, 124, -49, 267, 34 }).Coeffs))
                {
                    throw new Exception("The BigDecimalPolynomial test failed!");
                }
                // multiply a polynomial by its inverse modulo 2048 and check that the result is 1
                IntegerPolynomial d, dInv;
                CSPRng            rng = new CSPRng();

                do
                {
                    d    = DenseTernaryPolynomial.GenerateRandom(1001, 333, 334, rng);
                    dInv = d.InvertFq(2048);
                } while (dInv == null);

                d.Mod(2048);
                BigDecimalPolynomial e = CreateBigDecimalPolynomial(d.Coeffs);
                BigIntPolynomial     f = new BigIntPolynomial(dInv);
                IntegerPolynomial    g = new IntegerPolynomial(e.Multiply(f).Round());
                g.ModPositive(2048);

                if (!g.EqualsOne())
                {
                    throw new Exception("The BigDecimalPolynomial test failed!");
                }
                OnProgress(new TestEventArgs("Passed BigDecimalPolynomial tests"));

                return(SUCCESS);
            }
            catch (Exception Ex)
            {
                string message = Ex.Message == null ? "" : Ex.Message;
                throw new Exception(FAILURE + message);
            }
        }
        public void testMult()
        {
            testMult(new int[] { 2 }, new int[] { -1 });
            testMult(new int[] { 2, 0 }, new int[] { -1, 0 });
            testMult(new int[] { 2, 0, 3 }, new int[] { -1, 0, 1 });
            testMult(new int[] { 2, 0, 3, 1 }, new int[] { -1, 0, 1, 1 });
            testMult(new int[] { 2, 0, 3, 1, 2 }, new int[] { -1, 0, 1, 1, 0 });
            testMult(new int[] { 2, 0, 3, 1, 1, 5 }, new int[] { 1, -1, 1, 1, 0, 1 });
            testMult(new int[] { 2, 0, 3, 1, 1, 5, 1, 4 }, new int[] { 1, 0, 1, 1, -1, 1, 0, -1 });
            testMult(new int[] { 1368, 2047, 672, 871, 1662, 1352, 1099, 1608 }, new int[] { 1, 0, 1, 1, -1, 1, 0, -1 });

            // test random polynomials
            SecureRandom rng = new SecureRandom();

            for (int i = 0; i < 10; i++)
            {
                int[] coeffs1 = new int[rng.NextInt(2000) + 1];
                int[] coeffs2 = DenseTernaryPolynomial.GenerateRandom(coeffs1.Length, rng).coeffs;
                testMult(coeffs1, coeffs2);
            }
        }
        /// <summary>
        /// Test the validity of the DenseTernaryPolynomial implementation
        /// </summary>
        ///
        /// <returns>State</returns>
        public string Test()
        {
            try
            {
                CheckTernarity(PolynomialGeneratorForTesting.generateRandom(1499));

                CSPRng rng = new CSPRng();
                for (int i = 0; i < 10; i++)
                {
                    int N          = rng.Next(2000) + 10;
                    int numOnes    = rng.Next(N);
                    int numNegOnes = rng.Next(N - numOnes);
                    CheckTernarity(DenseTernaryPolynomial.GenerateRandom(N, numOnes, numNegOnes, rng));
                }
                OnProgress(new TestEventArgs("Passed DenseTernaryPolynomial Ternarity"));

                return(SUCCESS);
            }
            catch (Exception Ex)
            {
                string message = Ex.Message == null ? "" : Ex.Message;
                throw new Exception(FAILURE + message);
            }
        }
        public AsymmetricCipherKeyPair GenerateKeyPair()
        {
            int  N      = Parameters.N;
            int  q      = Parameters.q;
            int  df     = Parameters.df;
            int  df1    = Parameters.df1;
            int  df2    = Parameters.df2;
            int  df3    = Parameters.df3;
            int  dg     = Parameters.dg;
            bool fastFp = Parameters.fastFp;
            bool sparse = Parameters.sparse;

            IPolynomial       t;
            IntegerPolynomial fq;
            IntegerPolynomial fp = null;

            // choose a random f that is invertible mod 3 and q
            while (true)
            {
                IntegerPolynomial f;

                // choose random t, calculate f and fp
                if (fastFp)
                {
                    // if fastFp=true, f is always invertible mod 3
                    t = Parameters.polyType == (int)NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE ? Util.GenerateRandomTernary(N, df, df, sparse, Parameters.Random) : (IPolynomial)ProductFormPolynomial.GenerateRandom(N, df1, df2, df3, df3, Parameters.Random);
                    f = t.ToIntegerPolynomial();
                    f.Multiply(3);
                    f.coeffs[0] += 1;
                }
                else
                {
                    t  = Parameters.polyType == (int)NTRUParameters.TERNARY_POLYNOMIAL_TYPE_SIMPLE ? Util.GenerateRandomTernary(N, df, df - 1, sparse, Parameters.Random) : (IPolynomial)ProductFormPolynomial.GenerateRandom(N, df1, df2, df3, df3 - 1, Parameters.Random);
                    f  = t.ToIntegerPolynomial();
                    fp = f.InvertF3();
                    if (fp == null)
                    {
                        continue;
                    }
                }

                fq = f.InvertFq(q);
                if (fq == null)
                {
                    continue;
                }
                break;
            }

            // if fastFp=true, fp=1
            if (fastFp)
            {
                fp           = new IntegerPolynomial(N);
                fp.coeffs[0] = 1;
            }

            // choose a random g that is invertible mod q
            DenseTernaryPolynomial g;

            while (true)
            {
                g = DenseTernaryPolynomial.GenerateRandom(N, dg, dg - 1, Parameters.Random);
                if (g.InvertFq(q) != null)
                {
                    break;
                }
            }

            IntegerPolynomial h = g.Multiply(fq, q);

            h.Multiply3(q);
            h.EnsurePositive(q);
            g.Clear();
            fq.Clear();

            NTRUEncryptionPrivateKeyParameters priv = new NTRUEncryptionPrivateKeyParameters(h, t, fp, Parameters.GetEncryptionParameters());
            NTRUEncryptionPublicKeyParameters  pub  = new NTRUEncryptionPublicKeyParameters(h, Parameters.GetEncryptionParameters());

            return(new AsymmetricCipherKeyPair(pub, priv));
        }
Beispiel #20
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));
        }