Beispiel #1
0
        // tests if a*b=1 (mod modulus)
        private void verifyInverse(IntegerPolynomial a, IntegerPolynomial b, int modulus)
        {
            IntegerPolynomial c = a.Multiply(b, modulus);

            for (int i = 1; i < c.coeffs.Length; i++)
            {
                c.coeffs[i] %= modulus;
            }
            c.EnsurePositive(modulus);
            Assert.True(c.EqualsOne());
        }
        // tests if a*b=1 (mod modulus)
        private void VerifyInverse(IntegerPolynomial a, IntegerPolynomial b, int modulus)
        {
            IntegerPolynomial c = a.Multiply(b, modulus);

            for (int i = 1; i < c.Coeffs.Length; i++)
            {
                c.Coeffs[i] %= modulus;
            }

            c.EnsurePositive(modulus);
            if (!c.EqualsOne())
            {
                throw new Exception("IntegerPolynomialTest Modulus inverse test failed!");
            }
        }
        /// <summary>
        /// Generates a new encryption key pair
        /// </summary>
        ///
        /// <param name="RngF">The random number generator to use for generating the secret polynomial f</param>
        /// <param name="RngG">The random number generator to use for generating the secret polynomial g</param>
        ///
        /// <returns>A key pair</returns>
        private IAsymmetricKeyPair GenerateKeyPair(IRandom RngF, IRandom RngG)
        {
            int  N      = _encParams.N;
            int  q      = _encParams.Q;
            bool fastFp = _encParams.FastFp;
            bool sparse = _encParams.Sparse;
            TernaryPolynomialType polyType = _encParams.PolyType;
            IPolynomial           t        = null;
            IntegerPolynomial     fq       = null;
            IntegerPolynomial     fp       = null;
            IntegerPolynomial     g        = null;

            if (ParallelUtils.IsParallel && _isParallel)
            {
                Action[] gA = new Action[] {
                    new Action(() => g = GenerateG(RngG)),
                    new Action(() => GenerateFQ(RngF, out t, out fq, out fp))
                };
                Parallel.Invoke(gA);
            }
            else
            {
                // Choose a random g that is invertible mod q.
                g = GenerateG(RngG);
                // choose a random f that is invertible mod 3 and q
                GenerateFQ(RngF, out t, out fq, out fp);
            }

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

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

            h.Mult3(q);
            h.EnsurePositive(q);

            NTRUPrivateKey priv = new NTRUPrivateKey(t, fp, N, q, sparse, fastFp, polyType);
            NTRUPublicKey  pub  = new NTRUPublicKey(h, N, q);

            return(new NTRUKeyPair(pub, priv));
        }
        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 #5
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));
            }
        }