Beispiel #1
0
        private IntegerPolynomial sign(IntegerPolynomial i, SignatureKeyPair kp)
        {
            int N = param.N;
            int q = param.q;
            int perturbationBases = param.B;

            IntegerPolynomial s = new IntegerPolynomial(N);
            int iLoop           = perturbationBases;

            while (iLoop >= 1)
            {
                IPolynomial f      = kp.priv.getBasis(iLoop).f;
                IPolynomial fPrime = kp.priv.getBasis(iLoop).fPrime;

                IntegerPolynomial y = f.Multiply(i);
                y.Divide(q);
                y = fPrime.Multiply(y);

                IntegerPolynomial x = fPrime.Multiply(i);
                x.Divide(q);
                x = f.Multiply(x);

                IntegerPolynomial si = y;
                si.Subtract(x);
                s.Add(si);

                IntegerPolynomial hi = kp.priv.getBasis(iLoop).h.Clone();
                if (iLoop > 1)
                {
                    hi.Subtract(kp.priv.getBasis(iLoop - 1).h);
                }
                else
                {
                    hi.Subtract(kp.pub.h);
                }
                i = si.Multiply(hi, q);

                iLoop--;
            }

            IPolynomial f2      = kp.priv.getBasis(0).f;
            IPolynomial fPrime2 = kp.priv.getBasis(0).fPrime;

            IntegerPolynomial y2 = f2.Multiply(i);

            y2.Divide(q);
            y2 = fPrime2.Multiply(y2);

            IntegerPolynomial x2 = fPrime2.Multiply(i);

            x2.Divide(q);
            x2 = f2.Multiply(x2);

            y2.Subtract(x2);
            s.Add(y2);
            s.ModPositive(q);
            return(s);
        }
        /// <summary>
        /// Returns a polynomial that is equal to this polynomial (in the sense that mult(IntegerPolynomial, int)
        /// returns equal <c>IntegerPolynomial</c>s). The new polynomial is guaranteed to be independent of the original.
        /// </summary>
        ///
        /// <returns>The polynomial product</returns>
        public IntegerPolynomial ToIntegerPolynomial()
        {
            IntegerPolynomial i = m_f1.Multiply(m_f2.ToIntegerPolynomial());

            i.Add(m_f3);

            return(i);
        }
        /// <summary>
        /// Multiplies the polynomial by an <c>IntegerPolynomial</c>,
        /// taking the indices mod <c>N</c>.
        /// </summary>
        ///
        /// <param name="Factor">A polynomial factor</param>
        ///
        /// <returns>The product of the two polynomials</returns>
        public IntegerPolynomial Multiply(IntegerPolynomial Factor)
        {
            IntegerPolynomial c = m_f1.Multiply(Factor);

            c = m_f2.Multiply(c);
            c.Add(m_f3.Multiply(Factor));

            return(c);
        }
Beispiel #4
0
        /**
         * Implementation of the optional steps 20 through 26 in EESS1v2.pdf, section 3.5.1.1.
         * This doesn't seem to have much of an effect and sometimes actually increases the
         * norm of F, but on average it slightly reduces the norm.<br/>
         * This method changes <code>F</code> and <code>G</code> but leaves <code>f</code> and
         * <code>g</code> unchanged.
         * @param f
         * @param g
         * @param F
         * @param G
         * @param N
         */
        private void minimizeFG(IntegerPolynomial f, IntegerPolynomial g, IntegerPolynomial F, IntegerPolynomial G, int N)
        {
            int E = 0;

            for (int j = 0; j < N; j++)
            {
                E += 2 * N * (f.Coeffs[j] * f.Coeffs[j] + g.Coeffs[j] * g.Coeffs[j]);
            }

            // [f(1)+g(1)]^2 = 4
            E -= 4;

            IntegerPolynomial u = f.Clone();
            IntegerPolynomial v = g.Clone();
            int j2            = 0;
            int k             = 0;
            int maxAdjustment = N;

            while (k < maxAdjustment && j2 < N)
            {
                int D = 0;
                int i = 0;
                while (i < N)
                {
                    int D1 = F.Coeffs[i] * f.Coeffs[i];
                    int D2 = G.Coeffs[i] * g.Coeffs[i];
                    int D3 = 4 * N * (D1 + D2);
                    D += D3;
                    i++;
                }
                // f(1)+g(1) = 2
                int D4 = 4 * (F.SumCoeffs() + G.SumCoeffs());
                D -= D4;

                if (D > E)
                {
                    F.Subtract(u);
                    G.Subtract(v);
                    k++;
                    j2 = 0;
                }
                else if (D < -E)
                {
                    F.Add(u);
                    G.Add(v);
                    k++;
                    j2 = 0;
                }
                j2++;
                u.Rotate1();
                v.Rotate1();
            }
        }
        private void AddTest()
        {
            NTRUParameters     param = NTRUParamSets.EES1087EP2;
            IntegerPolynomial  a     = PolynomialGeneratorForTesting.GenerateRandom(param.N, param.Q);
            ITernaryPolynomial b     = PolynomialGeneratorForTesting.generateRandom(1087);

            IntegerPolynomial c1 = a.Clone();

            c1.Add(b.ToIntegerPolynomial());

            IntegerPolynomial c2 = a.Clone();

            c2.Add(b);

            if (!Compare.Equals(c1, c2))
            {
                throw new Exception("IntegerPolynomialTest addition test failed!");
            }
        }
Beispiel #6
0
        /// <summary>
        /// Encrypts a message
        /// </summary>
        ///
        /// <param name="Input">The message to encrypt</param>
        ///
        /// <returns>The encrypted message</returns>
        ///
        /// <exception cref="NTRUException">If not initialized, the specified hash algorithm is invalid, the encrypted data is invalid, or <c>maxLenBytes</c> is greater than 255</exception>
        public byte[] Encrypt(byte[] Input)
        {
            if (!_isInitialized)
            {
                throw new NTRUException("NTRUEncrypt:Encrypt", "The cipher has not been initialized!", new InvalidOperationException());
            }

            IntegerPolynomial pub = ((NTRUPublicKey)_keyPair.PublicKey).H;
            int  N             = _encParams.N;
            int  q             = _encParams.Q;
            int  maxLenBytes   = _encParams.MaxMsgLenBytes;
            int  db            = _encParams.Db;
            int  bufferLenBits = _encParams.BufferLenBits;
            int  dm0           = _encParams.Dm0;
            int  maxM1         = _encParams.MaxM1;
            int  minCallsMask  = _encParams.MinMGFHashCalls;
            bool hashSeed      = _encParams.HashSeed;
            int  msgLen        = Input.Length;

            //if (maxLenBytes > 255)
            //    throw new NTRUException("len values bigger than 255 are not supported");
            if (msgLen > maxLenBytes)
            {
                throw new NTRUException("NTRUEncrypt:Encrypt", string.Format("Message too long: {0} > {1}!", msgLen, maxLenBytes), new InvalidDataException());
            }

            while (true)
            {
                // M = b|octL|m|p0
                byte[] b = new byte[db / 8];
                // forward padding
                _rndEngine.GetBytes(b);
                byte[] p0 = new byte[maxLenBytes + 1 - msgLen];
                byte[] msgTmp;

                using (BinaryWriter writer = new BinaryWriter(new MemoryStream((bufferLenBits + 7) / 8)))
                {
                    writer.Write(b);
                    writer.Write((byte)msgLen);
                    writer.Write(Input);
                    writer.Write(p0);
                    msgTmp = ((MemoryStream)writer.BaseStream).ToArray();
                }

                // don't use the constant coeff if maxM1 is set; see below
                IntegerPolynomial mTrin = IntegerPolynomial.FromBinary3Sves(msgTmp, N, maxM1 > 0);
                byte[]            sData = GetSeed(Input, pub, b);
                IPolynomial       r     = GenerateBlindingPoly(sData);
                IntegerPolynomial R     = r.Multiply(pub, q);
                byte[]            oR4   = R.ToBinary4();
                IntegerPolynomial mask  = MGF(oR4, N, minCallsMask, hashSeed);
                mTrin.Add(mask);

                // If df and dr are close to N/3, and the absolute value of mTrin.sumCoeffs() is
                // large enough, the message becomes vulnerable to a meet-in-the-middle attack.
                // To prevent this, we set the constant coefficient to zero but first check to ensure
                // sumCoeffs() is small enough to keep the likelihood of a decryption failure low.
                if (maxM1 > 0)
                {
                    if (mTrin.SumCoeffs() > maxM1)
                    {
                        continue;
                    }
                    mTrin.Coeffs[0] = 0;
                }

                mTrin.Mod3();

                if (mTrin.Count(-1) < dm0)
                {
                    continue;
                }
                if (mTrin.Count(0) < dm0)
                {
                    continue;
                }
                if (mTrin.Count(1) < dm0)
                {
                    continue;
                }

                R.Add(mTrin, q);
                R.EnsurePositive(q);

                return(R.ToBinary(q));
            }
        }
Beispiel #7
0
        /**
         * Implementation of the optional steps 20 through 26 in EESS1v2.pdf, section 3.5.1.1.
         * This doesn't seem to have much of an effect and sometimes actually increases the
         * norm of F, but on average it slightly reduces the norm.<br/>
         * This method changes <code>F</code> and <code>G</code> but leaves <code>f</code> and
         * <code>g</code> unchanged.
         * @param f
         * @param g
         * @param F
         * @param G
         * @param N
         */
        private void minimizeFG(IntegerPolynomial f, IntegerPolynomial g, IntegerPolynomial F, IntegerPolynomial G, int N)
        {
            int E = 0;
            for (int j = 0; j < N; j++)
                E += 2 * N * (f.Coeffs[j] * f.Coeffs[j] + g.Coeffs[j] * g.Coeffs[j]);

            // [f(1)+g(1)]^2 = 4
            E -= 4;

            IntegerPolynomial u = f.Clone();
            IntegerPolynomial v = g.Clone();
            int j2 = 0;
            int k = 0;
            int maxAdjustment = N;
            while (k < maxAdjustment && j2 < N)
            {
                int D = 0;
                int i = 0;
                while (i < N)
                {
                    int D1 = F.Coeffs[i] * f.Coeffs[i];
                    int D2 = G.Coeffs[i] * g.Coeffs[i];
                    int D3 = 4 * N * (D1 + D2);
                    D += D3;
                    i++;
                }
                // f(1)+g(1) = 2
                int D4 = 4 * (F.SumCoeffs() + G.SumCoeffs());
                D -= D4;

                if (D > E)
                {
                    F.Subtract(u);
                    G.Subtract(v);
                    k++;
                    j2 = 0;
                }
                else if (D < -E)
                {
                    F.Add(u);
                    G.Add(v);
                    k++;
                    j2 = 0;
                }
                j2++;
                u.Rotate1();
                v.Rotate1();
            }
        }
Beispiel #8
0
        private IntegerPolynomial sign(IntegerPolynomial i, SignatureKeyPair kp)
        {
            int N = param.N;
            int q = param.q;
            int perturbationBases = param.B;

            IntegerPolynomial s = new IntegerPolynomial(N);
            int iLoop = perturbationBases;
            while (iLoop >= 1)
            {
                IPolynomial f = kp.priv.getBasis(iLoop).f;
                IPolynomial fPrime = kp.priv.getBasis(iLoop).fPrime;

                IntegerPolynomial y = f.Multiply(i);
                y.Divide(q);
                y = fPrime.Multiply(y);

                IntegerPolynomial x = fPrime.Multiply(i);
                x.Divide(q);
                x = f.Multiply(x);

                IntegerPolynomial si = y;
                si.Subtract(x);
                s.Add(si);

                IntegerPolynomial hi = kp.priv.getBasis(iLoop).h.Clone();
                if (iLoop > 1)
                    hi.Subtract(kp.priv.getBasis(iLoop - 1).h);
                else
                    hi.Subtract(kp.pub.h);
                i = si.Multiply(hi, q);

                iLoop--;
            }

            IPolynomial f2 = kp.priv.getBasis(0).f;
            IPolynomial fPrime2 = kp.priv.getBasis(0).fPrime;

            IntegerPolynomial y2 = f2.Multiply(i);
            y2.Divide(q);
            y2 = fPrime2.Multiply(y2);

            IntegerPolynomial x2 = fPrime2.Multiply(i);
            x2.Divide(q);
            x2 = f2.Multiply(x2);

            y2.Subtract(x2);
            s.Add(y2);
            s.ModPositive(q);
            return s;
        }
Beispiel #9
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));
        }