/// <summary>
 /// Copy constructor
 /// </summary>
 ///
 /// <param name="Gf">The PolynomialGF2mSmallM to copy</param>
 public PolynomialGF2mSmallM(PolynomialGF2mSmallM Gf)
 {
     // field needs not to be cloned since it is immutable
     _field        = Gf._field;
     _degree       = Gf._degree;
     _coefficients = IntUtils.DeepCopy(Gf._coefficients);
 }
示例#2
0
        /// <summary>
        /// Swap two columns
        /// </summary>
        private static void SwapColumns(PolynomialGF2mSmallM[] Matrix, int First, int Second)
        {
            PolynomialGF2mSmallM tmp = Matrix[First];

            Matrix[First]  = Matrix[Second];
            Matrix[Second] = tmp;
        }
        /// <summary>
        /// Compute the inverse of this polynomial modulo the given polynomial
        /// </summary>
        ///
        /// <param name="A">The reduction polynomial</param>
        ///
        /// <returns>Returns <c>this^(-1) mod a</c></returns>
        public PolynomialGF2mSmallM ModInverse(PolynomialGF2mSmallM A)
        {
            int[] unit        = { 1 };
            int[] resultCoeff = ModDiv(unit, _coefficients, A._coefficients, _field);

            return(new PolynomialGF2mSmallM(_field, resultCoeff));
        }
示例#4
0
 /// <summary>
 /// Initialize this class
 /// </summary>
 ///
 /// <param name="Field">The finite field</param>
 /// <param name="Poly">The reduction polynomial</param>
 public PolynomialRingGF2m(GF2mField Field, PolynomialGF2mSmallM Poly)
 {
     m_field = Field;
     m_poly  = Poly;
     ComputeSquaringMatrix();
     ComputeSquareRootMatrix();
 }
 /// <summary>
 /// Initialize this class
 /// </summary>
 /// 
 /// <param name="Field">The finite field</param>
 /// <param name="Poly">The reduction polynomial</param>
 public PolynomialRingGF2m(GF2mField Field, PolynomialGF2mSmallM Poly)
 {
     _field = Field;
     _poly = Poly;
     ComputeSquaringMatrix();
     ComputeSquareRootMatrix();
 }
 /// <summary>
 /// Divide this polynomial by the given polynomial
 /// </summary>
 /// <param name="F">The polynomial</param>
 /// <returns>Returns polynomial pair = {q,r} where this = q*f+r and deg(r) &lt; deg(f)</returns>
 public PolynomialGF2mSmallM[] Divide(PolynomialGF2mSmallM F)
 {
     int[][] resultCoeffs = Divide(_coefficients, F._coefficients, _field);
     return(new PolynomialGF2mSmallM[] {
         new PolynomialGF2mSmallM(_field, resultCoeffs[0]),
         new PolynomialGF2mSmallM(_field, resultCoeffs[1])
     });
 }
        /// <summary>
        /// Reads a Private Key from a Stream
        /// </summary>
        /// 
        /// <param name="KeyStream">An input stream containing an encoded key</param>
        /// 
        /// <exception cref="CryptoAsymmetricException">Thrown if the key could not be loaded</exception>
        public MPKCPrivateKey(Stream KeyStream)
        {
            try
            {
                int len;
                BinaryReader reader = new BinaryReader(KeyStream);

                // length
                _N = reader.ReadInt32();
                // dimension
                _K = reader.ReadInt32();

                // gf
                byte[] gf = reader.ReadBytes(GF_LENGTH);
                _gField = new GF2mField(gf);

                // gp
                len = reader.ReadInt32();
                byte[] gp = reader.ReadBytes(len);
                _goppaPoly = new PolynomialGF2mSmallM(_gField, gp);

                // p1
                len = reader.ReadInt32();
                byte[] p1 = reader.ReadBytes(len);
                _P1 = new Permutation(p1);

                // check matrix
                len = reader.ReadInt32();
                byte[] h = reader.ReadBytes(len);
                _H = new GF2Matrix(h);

                // length of first dimension
                len = reader.ReadInt32();
                byte[][] qi = new byte[len][];

                // get the qinv encoded array
                for (int i = 0; i < qi.Length; i++)
                {
                    len = reader.ReadInt32();
                    qi[i] = reader.ReadBytes(len);
                }

                // assign qinv
                _qInv = new PolynomialGF2mSmallM[qi.Length];

                for (int i = 0; i < QInv.Length; i++)
                    _qInv[i] = new PolynomialGF2mSmallM(_gField, qi[i]);
            }
            catch (Exception ex)
            {
                throw new CryptoAsymmetricException("MPKCPrivateKey:CTor", "The Private key could not be loaded!", ex);
            }
        }
        /// <summary>
        /// Initialize this class CCA2 MPKCS using encoded byte arrays
        /// </summary>
        /// 
        /// <param name="N">Length of the code</param>
        /// <param name="K">The dimension of the code</param>
        /// <param name="Gf">Encoded field polynomial defining the finite field <c>GF(2^m)</c></param>
        /// <param name="Gp">Encoded irreducible Goppa polynomial</param>
        /// <param name="P">The encoded permutation</param>
        /// <param name="H">Encoded canonical check matrix</param>
        /// <param name="QInv">The encoded matrix used to compute square roots in <c>(GF(2^m))^t</c></param>
        public MPKCPrivateKey(int N, int K, byte[] Gf, byte[] Gp, byte[] P, byte[] H, byte[][] QInv)
        {
            _N = N;
            _K = K;
            _gField = new GF2mField(Gf);
            _goppaPoly = new PolynomialGF2mSmallM(_gField, Gp);
            _P1 = new Permutation(P);
            _H = new GF2Matrix(H);
            _qInv = new PolynomialGF2mSmallM[QInv.Length];

            for (int i = 0; i < QInv.Length; i++)
                _qInv[i] = new PolynomialGF2mSmallM(_gField, QInv[i]);
        }
        /// <summary>
        /// Compute the square root of this polynomial modulo the given polynomial
        /// </summary>
        ///
        /// <param name="A">The reduction polynomial</param>
        ///
        /// <returns>Returns <c>this^(1/2) mod A</c></returns>
        public PolynomialGF2mSmallM ModSquareRoot(PolynomialGF2mSmallM A)
        {
            int[] resultCoeff = IntUtils.DeepCopy(_coefficients);
            int[] help        = ModMultiply(resultCoeff, resultCoeff, A._coefficients, _field);

            while (!IsEqual(help, _coefficients))
            {
                resultCoeff = NormalForm(help);
                help        = ModMultiply(resultCoeff, resultCoeff, A._coefficients, _field);
            }

            return(new PolynomialGF2mSmallM(_field, resultCoeff));
        }
示例#10
0
        /// <summary>
        /// Compare this element with another object
        /// </summary>
        ///
        /// <param name="Obj">The object for comprison</param>
        ///
        /// <returns>Returns <c>true</c> if the two objects are equal, <c>false</c> otherwise</returns>
        public override bool Equals(Object Obj)
        {
            if (Obj == null || !(Obj is PolynomialGF2mSmallM))
            {
                return(false);
            }

            PolynomialGF2mSmallM p = (PolynomialGF2mSmallM)Obj;

            if ((_field.Equals(p._field)) && (_degree.Equals(p._degree)) && (Compare.AreEqual(_coefficients, p._coefficients)))
            {
                return(true);
            }

            return(false);
        }
示例#11
0
        /// <summary>
        /// Find an error vector <c>E</c> over <c>GF(2)</c> from an input syndrome <c>S</c> over <c>GF(2^M)</c>
        /// </summary>
        ///
        /// <param name="SyndVec">The syndrome</param>
        /// <param name="Field">The finite field</param>
        /// <param name="Gp">The irreducible Goppa polynomial</param>
        /// <param name="SqRootMatrix">The matrix for computing square roots in <c>(GF(2M))<sup>T</sup></c></param>
        ///
        /// <returns>The error vector</returns>
        public static GF2Vector SyndromeDecode(GF2Vector SyndVec, GF2mField Field, PolynomialGF2mSmallM Gp, PolynomialGF2mSmallM[] SqRootMatrix)
        {
            int n = 1 << Field.Degree;
            // the error vector
            GF2Vector errors = new GF2Vector(n);

            // if the syndrome vector is zero, the error vector is also zero
            if (!SyndVec.IsZero())
            {
                // convert syndrome vector to polynomial over GF(2^m)
                PolynomialGF2mSmallM syndrome = new PolynomialGF2mSmallM(SyndVec.ToExtensionFieldVector(Field));
                // compute T = syndrome^-1 mod gp
                PolynomialGF2mSmallM t = syndrome.ModInverse(Gp);
                // compute tau = sqRoot(T + X) mod gp
                PolynomialGF2mSmallM tau = t.AddMonomial(1);
                tau = tau.ModSquareRootMatrix(SqRootMatrix);
                // compute polynomials a and b satisfying a + b*tau = 0 mod gp
                PolynomialGF2mSmallM[] ab = tau.ModPolynomialToFracton(Gp);
                // compute the polynomial a^2 + X*b^2
                PolynomialGF2mSmallM a2        = ab[0].Multiply(ab[0]);
                PolynomialGF2mSmallM b2        = ab[1].Multiply(ab[1]);
                PolynomialGF2mSmallM xb2       = b2.MultWithMonomial(1);
                PolynomialGF2mSmallM a2plusXb2 = a2.Add(xb2);
                // normalize a^2 + X*b^2 to obtain the error locator polynomial
                int headCoeff            = a2plusXb2.Head;
                int invHeadCoeff         = Field.Inverse(headCoeff);
                PolynomialGF2mSmallM elp = a2plusXb2.MultWithElement(invHeadCoeff);

                // for all elements i of GF(2^m)
                for (int i = 0; i < n; i++)
                {
                    // evaluate the error locator polynomial at i
                    int z = elp.EvaluateAt(i);
                    // if polynomial evaluates to zero
                    if (z == 0)
                    {
                        // set the i-th coefficient of the error vector
                        errors.SetBit(i);
                    }
                }
            }

            return(errors);
        }
示例#12
0
        /// <summary>
        /// Compute the squaring matrix for this polynomial ring, using the base field and the reduction polynomial
        /// </summary>
        private void ComputeSquaringMatrix()
        {
            int numColumns = m_poly.Degree;

            m_sqMatrix = new PolynomialGF2mSmallM[numColumns];
            PolynomialGF2mSmallM[] _sqMatrix2 = new PolynomialGF2mSmallM[numColumns];

            if (ParallelUtils.IsParallel)
            {
                int nct = numColumns >> 1;
                Parallel.For(0, nct, i =>
                {
                    int[] monomCoeffs   = new int[(i << 1) + 1];
                    monomCoeffs[i << 1] = 1;
                    m_sqMatrix[i]       = new PolynomialGF2mSmallM(m_field, monomCoeffs);
                });

                Parallel.For(nct, numColumns, i =>
                {
                    int[] monomCoeffs             = new int[(i << 1) + 1];
                    monomCoeffs[i << 1]           = 1;
                    PolynomialGF2mSmallM monomial = new PolynomialGF2mSmallM(m_field, monomCoeffs);
                    m_sqMatrix[i] = monomial.Mod(m_poly);
                });
            }
            else
            {
                for (int i = 0; i < (numColumns >> 1); i++)
                {
                    int[] monomCoeffs = new int[(i << 1) + 1];
                    monomCoeffs[i << 1] = 1;
                    m_sqMatrix[i]       = new PolynomialGF2mSmallM(m_field, monomCoeffs);
                }

                for (int i = numColumns >> 1; i < numColumns; i++)
                {
                    int[] monomCoeffs = new int[(i << 1) + 1];
                    monomCoeffs[i << 1] = 1;
                    PolynomialGF2mSmallM monomial = new PolynomialGF2mSmallM(m_field, monomCoeffs);
                    m_sqMatrix[i] = monomial.Mod(m_poly);
                }
            }
        }
示例#13
0
        /// <summary>
        /// Compute a polynomial pair (a,b) from this polynomial and the given
        /// polynomial g with the property b*this = a mod g and deg(a)&lt;=deg(g)/2
        /// </summary>
        ///
        /// <param name="G">The reduction polynomial</param>
        ///
        /// <returns>Returns PolynomialGF2mSmallM[] {a,b} with b*this = a mod g and deg(a)&lt;= deg(g)/2</returns>
        public PolynomialGF2mSmallM[] ModPolynomialToFracton(PolynomialGF2mSmallM G)
        {
            int dg = G._degree >> 1;

            int[] a0 = NormalForm(G._coefficients);
            int[] a1 = Mod(_coefficients, G._coefficients, _field);
            int[] b0 = { 0 };
            int[] b1 = { 1 };

            while (ComputeDegree(a1) > dg)
            {
                int[][] q = Divide(a0, a1, _field);
                a0 = a1;
                a1 = q[1];
                int[] b2 = Add(b0, ModMultiply(q[0], b1, G._coefficients, _field), _field);
                b0 = b1;
                b1 = b2;
            }

            return(new PolynomialGF2mSmallM[] { new PolynomialGF2mSmallM(_field, a1), new PolynomialGF2mSmallM(_field, b1) });
        }
示例#14
0
        /// <summary>
        /// Construct the check matrix of a Goppa code in canonical form from the irreducible Goppa polynomial over the finite field <c>GF(2^m)</c>.
        /// </summary>
        ///
        /// <param name="Field">The finite field</param>
        /// <param name="Gp">The irreducible Goppa polynomial</param>
        ///
        /// <returns>The new GF2Matrix</returns>
        public static GF2Matrix CreateCanonicalCheckMatrix(GF2mField Field, PolynomialGF2mSmallM Gp)
        {
            int m = Field.Degree;
            int n = 1 << m;
            int t = Gp.Degree;

            // create matrix H over GF(2^m)
            int[][] hArray = ArrayUtils.CreateJagged <int[][]>(t, n);
            // create matrix YZ
            int[][] yz = ArrayUtils.CreateJagged <int[][]>(t, n);

            if (ParallelUtils.IsParallel)
            {
                Parallel.For(0, n, j =>
                             yz[0][j] = Field.Inverse(Gp.EvaluateAt(j)));
            }
            else
            {
                // here j is used as index and as element of field GF(2^m)
                for (int j = 0; j < n; j++)
                {
                    yz[0][j] = Field.Inverse(Gp.EvaluateAt(j));
                }
            }

            for (int i = 1; i < t; i++)
            {
                // here j is used as index and as element of field GF(2^m)
                if (ParallelUtils.IsParallel)
                {
                    Parallel.For(0, n, j =>
                    {
                        yz[i][j] = Field.Multiply(yz[i - 1][j], j);
                    });
                }
                else
                {
                    for (int j = 0; j < n; j++)
                    {
                        yz[i][j] = Field.Multiply(yz[i - 1][j], j);
                    }
                }
            }

            // create matrix H = XYZ
            for (int i = 0; i < t; i++)
            {
                if (ParallelUtils.IsParallel)
                {
                    Parallel.For(0, n, j =>
                    {
                        for (int k = 0; k <= i; k++)
                        {
                            hArray[i][j] = Field.Add(hArray[i][j], Field.Multiply(yz[k][j], Gp.GetCoefficient(t + k - i)));
                        }
                    });
                }
                else
                {
                    for (int j = 0; j < n; j++)
                    {
                        for (int k = 0; k <= i; k++)
                        {
                            hArray[i][j] = Field.Add(hArray[i][j], Field.Multiply(yz[k][j], Gp.GetCoefficient(t + k - i)));
                        }
                    }
                }
            }

            // convert to matrix over GF(2)
            int[][] result = ArrayUtils.CreateJagged <int[][]>(t * m, IntUtils.URShift((n + 31), 5));

            if (ParallelUtils.IsParallel)
            {
                for (int j = 0; j < n; j++)
                {
                    int q = IntUtils.URShift(j, 5);
                    int r = 1 << (j & 0x1f);
                    for (int i = 0; i < t; i++)
                    {
                        int e = hArray[i][j];
                        Parallel.For(0, m, u =>
                        {
                            int b = (IntUtils.URShift(e, u)) & 1;
                            if (b != 0)
                            {
                                int ind         = (i + 1) * m - u - 1;
                                result[ind][q] ^= r;
                            }
                        });
                    }
                }
            }
            else
            {
                for (int j = 0; j < n; j++)
                {
                    int q = IntUtils.URShift(j, 5);
                    int r = 1 << (j & 0x1f);
                    for (int i = 0; i < t; i++)
                    {
                        int e = hArray[i][j];
                        for (int u = 0; u < m; u++)
                        {
                            int b = (IntUtils.URShift(e, u)) & 1;
                            if (b != 0)
                            {
                                int ind = (i + 1) * m - u - 1;
                                result[ind][q] ^= r;
                            }
                        }
                    }
                }
            }

            return(new GF2Matrix(n, result));
        }
示例#15
0
 /// <summary>
 /// Compute the sum of this polynomial and the given polynomial
 /// </summary>
 ///
 /// <param name="Addend">he addend</param>
 ///
 /// <returns>Return <c>this + a</c> (newly created)</returns>
 public PolynomialGF2mSmallM Add(PolynomialGF2mSmallM Addend)
 {
     int[] resultCoeff = Add(_coefficients, Addend._coefficients, _field);
     return(new PolynomialGF2mSmallM(_field, resultCoeff));
 }
示例#16
0
 /// <summary>
 /// Return the greatest common divisor of this and a polynomial <c>F</c>
 /// </summary>
 ///
 /// <param name="F">The polynomial</param>
 ///
 /// <returns>Returns Gcd(this, f)</returns>
 public PolynomialGF2mSmallM Gcd(PolynomialGF2mSmallM F)
 {
     int[] resultCoeff = Gcd(m_coefficients, F.m_coefficients, m_field);
     return(new PolynomialGF2mSmallM(m_field, resultCoeff));
 }
 /// <summary>
 /// Compute the result of the division of this polynomial by another polynomial modulo a third polynomial
 /// </summary>
 /// 
 /// <param name="Divisor">The divisor</param>
 /// <param name="Modulus">The reduction polynomial</param>
 /// 
 /// <returns>Returns <c>this * divisor^(-1) mod modulus</c></returns>
 public PolynomialGF2mSmallM ModDivide(PolynomialGF2mSmallM Divisor, PolynomialGF2mSmallM Modulus)
 {
     int[] resultCoeff = ModDiv(_coefficients, Divisor._coefficients, Modulus._coefficients, _field);
     return new PolynomialGF2mSmallM(_field, resultCoeff);
 }
 /// <summary>
 /// Compute the product of this polynomial and another polynomial modulo a third polynomial
 /// </summary>
 /// 
 /// <param name="A">The polynomial</param>
 /// <param name="B">The reduction polynomial</param>
 /// 
 /// <returns>Returns <c>this * a mod b</c></returns>
 public PolynomialGF2mSmallM ModMultiply(PolynomialGF2mSmallM A, PolynomialGF2mSmallM B)
 {
     int[] resultCoeff = ModMultiply(_coefficients, A._coefficients, B._coefficients, _field);
     return new PolynomialGF2mSmallM(_field, resultCoeff);
 }
 /// <summary>
 /// Compute the sum of this polynomial and the given polynomial
 /// </summary>
 /// 
 /// <param name="Addend">he addend</param>
 /// 
 /// <returns>Return <c>this + a</c> (newly created)</returns>
 public PolynomialGF2mSmallM Add(PolynomialGF2mSmallM Addend)
 {
     int[] resultCoeff = Add(_coefficients, Addend._coefficients, _field);
     return new PolynomialGF2mSmallM(_field, resultCoeff);
 }
 /// <summary>
 /// Divide this polynomial by the given polynomial
 /// </summary>
 /// <param name="F">The polynomial</param>
 /// <returns>Returns polynomial pair = {q,r} where this = q*f+r and deg(r) &lt; deg(f)</returns>
 public PolynomialGF2mSmallM[] Divide(PolynomialGF2mSmallM F)
 {
     int[][] resultCoeffs = Divide(_coefficients, F._coefficients, _field);
     return new PolynomialGF2mSmallM[]{
     new PolynomialGF2mSmallM(_field, resultCoeffs[0]),
     new PolynomialGF2mSmallM(_field, resultCoeffs[1])};
 }
        /// <summary>
        /// Compute the square root of this polynomial using a square root matrix
        /// </summary>
        /// 
        /// <param name="M">The matrix for computing square roots in <c>(GF(2^m))^t</c> the polynomial ring defining the square root matrix</param>
        /// 
        /// <returns>Returns <c>this^(1/2)</c> modulo the reduction polynomial implicitly given via the square root matrix</returns>
        public PolynomialGF2mSmallM ModSquareRootMatrix(PolynomialGF2mSmallM[] M)
        {
            int length = M.Length;
            int[] resultCoeff = new int[length];

            // do matrix multiplication
            for (int i = 0; i < length; i++)
            {
                // compute scalar product of i-th row and j-th column
                for (int j = 0; j < length; j++)
                {
                    if (i >= M[j]._coefficients.Length)
                        continue;

                    if (j < _coefficients.Length)
                    {
                        int scalarTerm = _field.Multiply(M[j]._coefficients[i], _coefficients[j]);
                        resultCoeff[i] = _field.Add(resultCoeff[i], scalarTerm);
                    }
                }
            }

            // compute the square root of each entry of the result coefficients
            for (int i = 0; i < length; i++)
                resultCoeff[i] = _field.Sqrt(resultCoeff[i]);

            return new PolynomialGF2mSmallM(_field, resultCoeff);
        }
示例#22
0
        /// <summary>
        /// Find an error vector <c>E</c> over <c>GF(2)</c> from an input syndrome <c>S</c> over <c>GF(2^M)</c>
        /// </summary>
        /// 
        /// <param name="SyndVec">The syndrome</param>
        /// <param name="Field">The finite field</param>
        /// <param name="Gp">The irreducible Goppa polynomial</param>
        /// <param name="SqRootMatrix">The matrix for computing square roots in <c>(GF(2M))<sup>T</sup></c></param>
        /// 
        /// <returns>The error vector</returns>
        public static GF2Vector SyndromeDecode(GF2Vector SyndVec, GF2mField Field, PolynomialGF2mSmallM Gp, PolynomialGF2mSmallM[] SqRootMatrix)
        {
            int n = 1 << Field.Degree;
            // the error vector
            GF2Vector errors = new GF2Vector(n);

            // if the syndrome vector is zero, the error vector is also zero
            if (!SyndVec.IsZero())
            {
                // convert syndrome vector to polynomial over GF(2^m)
                PolynomialGF2mSmallM syndrome = new PolynomialGF2mSmallM(SyndVec.ToExtensionFieldVector(Field));
                // compute T = syndrome^-1 mod gp
                PolynomialGF2mSmallM t = syndrome.ModInverse(Gp);
                // compute tau = sqRoot(T + X) mod gp
                PolynomialGF2mSmallM tau = t.AddMonomial(1);
                tau = tau.ModSquareRootMatrix(SqRootMatrix);
                // compute polynomials a and b satisfying a + b*tau = 0 mod gp
                PolynomialGF2mSmallM[] ab = tau.ModPolynomialToFracton(Gp);
                // compute the polynomial a^2 + X*b^2
                PolynomialGF2mSmallM a2 = ab[0].Multiply(ab[0]);
                PolynomialGF2mSmallM b2 = ab[1].Multiply(ab[1]);
                PolynomialGF2mSmallM xb2 = b2.MultWithMonomial(1);
                PolynomialGF2mSmallM a2plusXb2 = a2.Add(xb2);
                // normalize a^2 + X*b^2 to obtain the error locator polynomial
                int headCoeff = a2plusXb2.Head;
                int invHeadCoeff = Field.Inverse(headCoeff);
                PolynomialGF2mSmallM elp = a2plusXb2.MultWithElement(invHeadCoeff);

                // for all elements i of GF(2^m)
                for (int i = 0; i < n; i++)
                {
                    // evaluate the error locator polynomial at i
                    int z = elp.EvaluateAt(i);
                    // if polynomial evaluates to zero
                    if (z == 0)
                    {
                        // set the i-th coefficient of the error vector
                        errors.SetBit(i);
                    }
                }
            }

            return errors;
        }
示例#23
0
 /// <summary>
 /// Compute the product of this polynomial and another polynomial modulo a third polynomial
 /// </summary>
 ///
 /// <param name="A">The polynomial</param>
 /// <param name="B">The reduction polynomial</param>
 ///
 /// <returns>Returns <c>this * a mod b</c></returns>
 public PolynomialGF2mSmallM ModMultiply(PolynomialGF2mSmallM A, PolynomialGF2mSmallM B)
 {
     int[] resultCoeff = ModMultiply(_coefficients, A._coefficients, B._coefficients, _field);
     return(new PolynomialGF2mSmallM(_field, resultCoeff));
 }
        /// <summary>
        /// Square this polynomial using a squaring matrix
        /// </summary>
        /// 
        /// <param name="M">The squaring matrix</param>
        /// 
        /// <returns>Returns <c>this^2</c> modulo the reduction polynomial implicitly given via the squaring matrix</returns>
        public PolynomialGF2mSmallM ModSquareMatrix(PolynomialGF2mSmallM[] M)
        {
            int length = M.Length;
            int[] resultCoeff = new int[length];
            int[] thisSquare = new int[length];

            // square each entry of this polynomial
            for (int i = 0; i < _coefficients.Length; i++)
                thisSquare[i] = _field.Multiply(_coefficients[i], _coefficients[i]);

            // do matrix-vector multiplication
            for (int i = 0; i < length; i++)
            {
                // compute scalar product of i-th row and coefficient vector
                for (int j = 0; j < length; j++)
                {
                    if (i >= M[j]._coefficients.Length)
                        continue;

                    int scalarTerm = _field.Multiply(M[j]._coefficients[i], thisSquare[j]);
                    resultCoeff[i] = _field.Add(resultCoeff[i], scalarTerm);
                }
            }

            return new PolynomialGF2mSmallM(_field, resultCoeff);
        }
示例#25
0
        /// <summary>
        /// Construct the check matrix of a Goppa code in canonical form from the irreducible Goppa polynomial over the finite field <c>GF(2^m)</c>.
        /// </summary>
        /// 
        /// <param name="Field">The finite field</param>
        /// <param name="Gp">The irreducible Goppa polynomial</param>
        /// 
        /// <returns>The new GF2Matrix</returns>
        public static GF2Matrix CreateCanonicalCheckMatrix(GF2mField Field, PolynomialGF2mSmallM Gp)
        {
            int m = Field.Degree;
            int n = 1 << m;
            int t = Gp.Degree;
            // create matrix H over GF(2^m)
            int[][] hArray = ArrayUtils.CreateJagged<int[][]>(t, n);
            // create matrix YZ
            int[][] yz = ArrayUtils.CreateJagged<int[][]>(t, n);

            if (ParallelUtils.IsParallel)
            {
                Parallel.For(0, n, j =>
                    yz[0][j] = Field.Inverse(Gp.EvaluateAt(j)));
            }
            else
            {
                // here j is used as index and as element of field GF(2^m)
                for (int j = 0; j < n; j++)
                    yz[0][j] = Field.Inverse(Gp.EvaluateAt(j));
            }

            for (int i = 1; i < t; i++)
            {
                // here j is used as index and as element of field GF(2^m)
                if (ParallelUtils.IsParallel)
                {
                    Parallel.For(0, n, j =>
                    {
                        yz[i][j] = Field.Multiply(yz[i - 1][j], j);
                    });
                }
                else
                {
                    for (int j = 0; j < n; j++)
                        yz[i][j] = Field.Multiply(yz[i - 1][j], j);
                }
            }

            // create matrix H = XYZ
            for (int i = 0; i < t; i++)
            {
                if (ParallelUtils.IsParallel)
                {
                    Parallel.For(0, n, j =>
                    {
                        for (int k = 0; k <= i; k++)
                            hArray[i][j] = Field.Add(hArray[i][j], Field.Multiply(yz[k][j], Gp.GetCoefficient(t + k - i)));
                    });
                }
                else
                {
                    for (int j = 0; j < n; j++)
                    {
                        for (int k = 0; k <= i; k++)
                            hArray[i][j] = Field.Add(hArray[i][j], Field.Multiply(yz[k][j], Gp.GetCoefficient(t + k - i)));
                    }
                }
            }

            // convert to matrix over GF(2)
            int[][] result = ArrayUtils.CreateJagged<int[][]>(t * m, IntUtils.URShift((n + 31), 5));

            if (ParallelUtils.IsParallel)
            {
                for (int j = 0; j < n; j++)
                {
                    int q = IntUtils.URShift(j, 5);
                    int r = 1 << (j & 0x1f);
                    for (int i = 0; i < t; i++)
                    {
                        int e = hArray[i][j];
                        Parallel.For(0, m, u =>
                        {
                            int b = (IntUtils.URShift(e, u)) & 1;
                            if (b != 0)
                            {
                                int ind = (i + 1) * m - u - 1;
                                result[ind][q] ^= r;
                            }
                        });
                    }
                }
            }
            else
            {
                for (int j = 0; j < n; j++)
                {
                    int q = IntUtils.URShift(j, 5);
                    int r = 1 << (j & 0x1f);
                    for (int i = 0; i < t; i++)
                    {
                        int e = hArray[i][j];
                        for (int u = 0; u < m; u++)
                        {
                            int b = (IntUtils.URShift(e, u)) & 1;
                            if (b != 0)
                            {
                                int ind = (i + 1) * m - u - 1;
                                result[ind][q] ^= r;
                            }
                        }
                    }
                }
            }

            return new GF2Matrix(n, result);
        }
示例#26
0
 /// <summary>
 /// Compute the result of the division of this polynomial by another polynomial modulo a third polynomial
 /// </summary>
 ///
 /// <param name="Divisor">The divisor</param>
 /// <param name="Modulus">The reduction polynomial</param>
 ///
 /// <returns>Returns <c>this * divisor^(-1) mod modulus</c></returns>
 public PolynomialGF2mSmallM ModDivide(PolynomialGF2mSmallM Divisor, PolynomialGF2mSmallM Modulus)
 {
     int[] resultCoeff = ModDiv(_coefficients, Divisor._coefficients, Modulus._coefficients, _field);
     return(new PolynomialGF2mSmallM(_field, resultCoeff));
 }
示例#27
0
 /// <summary>
 /// Reduce this polynomial modulo another polynomial
 /// </summary>
 ///
 /// <param name="F">The reduction polynomial</param>
 ///
 /// <returns>Returns <c>this mod f</c></returns>
 public PolynomialGF2mSmallM Mod(PolynomialGF2mSmallM F)
 {
     int[] resultCoeff = Mod(_coefficients, F._coefficients, _field);
     return(new PolynomialGF2mSmallM(_field, resultCoeff));
 }
示例#28
0
        private void Dispose(bool Disposing)
        {
            if (!_isDisposed && Disposing)
            {
                try
                {
                    if (_gField != null)
                    {
                        _gField.Clear();
                        _gField = null;
                    }
                    if (_goppaPoly != null)
                    {
                        _goppaPoly.Clear();
                        _goppaPoly = null;
                    }
                    if (_H != null)
                    {
                        _H.Clear();
                        _H = null;
                    }
                    if (_P1 != null)
                    {
                        _P1.Clear();
                        _P1 = null;
                    }
                    if (_qInv != null)
                    {
                        for (int i = 0; i < _qInv.Length; i++)
                        {
                            _qInv[i].Clear();
                            _qInv[i] = null;
                        }
                        _qInv = null;
                    }
                    _K = 0;
                    _N = 0;
                }
                catch { }

                _isDisposed = true;
            }
        }
        /// <summary>
        /// Compute the matrix for computing square roots in this polynomial ring by inverting the squaring matrix
        /// </summary>
        private void ComputeSquareRootMatrix()
        {
            int numColumns = _poly.Degree;

            // clone squaring matrix
            PolynomialGF2mSmallM[] tmpMatrix = new PolynomialGF2mSmallM[numColumns];
            for (int i = numColumns - 1; i >= 0; i--)
                tmpMatrix[i] = new PolynomialGF2mSmallM(_sqMatrix[i]);

            // initialize square root matrix as unit matrix
            _sqRootMatrix = new PolynomialGF2mSmallM[numColumns];
            for (int i = numColumns - 1; i >= 0; i--)
                _sqRootMatrix[i] = new PolynomialGF2mSmallM(_field, i);

            // simultaneously compute Gaussian reduction of squaring matrix and unit matrix
            for (int i = 0; i < numColumns; i++)
            {
                // if diagonal element is zero
                if (tmpMatrix[i].GetCoefficient(i) == 0)
                {
                    bool foundNonZero = false;
                    // find a non-zero element in the same row
                    for (int j = i + 1; j < numColumns; j++)
                    {
                        if (tmpMatrix[j].GetCoefficient(i) != 0)
                        {
                            // found it, swap columns ...
                            foundNonZero = true;
                            SwapColumns(tmpMatrix, i, j);
                            SwapColumns(_sqRootMatrix, i, j);
                            // ... and quit searching
                            j = numColumns;
                            continue;
                        }
                    }
                    // if no non-zero element was found the matrix is not invertible
                    if (!foundNonZero)
                        throw new ArithmeticException("Squaring matrix is not invertible.");
                }

                // normalize i-th column
                int coef = tmpMatrix[i].GetCoefficient(i);
                int invCoef = _field.Inverse(coef);
                tmpMatrix[i].MultThisWithElement(invCoef);
                _sqRootMatrix[i].MultThisWithElement(invCoef);

                if (ParallelUtils.IsParallel)
                {
                    // normalize all other columns
                    Parallel.For(0, numColumns, j =>
                    {
                        if (j != i)
                        {
                            int coefp = tmpMatrix[j].GetCoefficient(i);
                            if (coefp != 0)
                            {
                                PolynomialGF2mSmallM tmpSqColumn = tmpMatrix[i].MultWithElement(coefp);
                                PolynomialGF2mSmallM tmpInvColumn = _sqRootMatrix[i].MultWithElement(coefp);
                                tmpMatrix[j].AddToThis(tmpSqColumn);
                                lock (_sqRootMatrix)
                                    _sqRootMatrix[j].AddToThis(tmpInvColumn);
                            }
                        }
                    });
                }
                else
                {
                    for (int j = 0; j < numColumns; j++)
                    {
                        if (j != i)
                        {
                            coef = tmpMatrix[j].GetCoefficient(i);
                            if (coef != 0)
                            {
                                PolynomialGF2mSmallM tmpSqColumn = tmpMatrix[i].MultWithElement(coef);
                                PolynomialGF2mSmallM tmpInvColumn = _sqRootMatrix[i].MultWithElement(coef);
                                tmpMatrix[j].AddToThis(tmpSqColumn);
                                lock (_sqRootMatrix)
                                    _sqRootMatrix[j].AddToThis(tmpInvColumn);
                            }
                        }
                    }
                }
            }
        }
 /// <summary>
 /// Copy constructor
 /// </summary>
 /// 
 /// <param name="Gf">The PolynomialGF2mSmallM to copy</param>
 public PolynomialGF2mSmallM(PolynomialGF2mSmallM Gf)
 {
     // field needs not to be cloned since it is immutable
     _field = Gf._field;
     _degree = Gf._degree;
     _coefficients = IntUtils.DeepCopy(Gf._coefficients);
 }
        /// <summary>
        /// Generate an encryption Key pair
        /// </summary>
        /// 
        /// <returns>A McElieceKeyPair containing public and private keys</returns>
        public IAsymmetricKeyPair GenerateKeyPair()
        {
            // finite field GF(2^m)
            GF2mField field = new GF2mField(_M, _fieldPoly);
            // irreducible Goppa polynomial
            PolynomialGF2mSmallM gp = new PolynomialGF2mSmallM(field, _T, PolynomialGF2mSmallM.RANDOM_IRREDUCIBLE_POLYNOMIAL, _rndEngine);
            PolynomialRingGF2m ring = new PolynomialRingGF2m(field, gp);
            // matrix for computing square roots in (GF(2^m))^t
            PolynomialGF2mSmallM[] qInv = ring.SquareRootMatrix;
            // generate canonical check matrix
            GF2Matrix h = GoppaCode.CreateCanonicalCheckMatrix(field, gp);
            // compute short systematic form of check matrix
            GoppaCode.MaMaPe mmp = GoppaCode.ComputeSystematicForm(h, _rndEngine);
            GF2Matrix shortH = mmp.SecondMatrix;
            Permutation p = mmp.Permutation;
            // compute short systematic form of generator matrix
            GF2Matrix shortG = (GF2Matrix)shortH.ComputeTranspose();
            // obtain number of rows of G (= dimension of the code)
            int k = shortG.RowCount;
            // generate keys
            IAsymmetricKey pubKey = new MPKCPublicKey(_N, _T, shortG);
            IAsymmetricKey privKey = new MPKCPrivateKey(_N, k, field, gp, p, h, qInv);

            // return key pair
            return new MPKCKeyPair(pubKey, privKey);
        }
 /// <summary>
 /// Add the given polynomial to this polynomial (overwrite this).
 /// </summary>
 /// 
 /// <param name="Addend">The addend</param>
 public void AddToThis(PolynomialGF2mSmallM Addend)
 {
     _coefficients = Add(_coefficients, Addend._coefficients, _field);
     ComputeDegree();
 }
示例#33
0
        /// <summary>
        /// Compute the matrix for computing square roots in this polynomial ring by inverting the squaring matrix
        /// </summary>
        private void ComputeSquareRootMatrix()
        {
            int numColumns = m_poly.Degree;

            // clone squaring matrix
            PolynomialGF2mSmallM[] tmpMatrix = new PolynomialGF2mSmallM[numColumns];
            for (int i = numColumns - 1; i >= 0; i--)
            {
                tmpMatrix[i] = new PolynomialGF2mSmallM(m_sqMatrix[i]);
            }

            // initialize square root matrix as unit matrix
            m_sqRootMatrix = new PolynomialGF2mSmallM[numColumns];
            for (int i = numColumns - 1; i >= 0; i--)
            {
                m_sqRootMatrix[i] = new PolynomialGF2mSmallM(m_field, i);
            }

            // simultaneously compute Gaussian reduction of squaring matrix and unit matrix
            for (int i = 0; i < numColumns; i++)
            {
                // if diagonal element is zero
                if (tmpMatrix[i].GetCoefficient(i) == 0)
                {
                    bool foundNonZero = false;
                    // find a non-zero element in the same row
                    for (int j = i + 1; j < numColumns; j++)
                    {
                        if (tmpMatrix[j].GetCoefficient(i) != 0)
                        {
                            // found it, swap columns ...
                            foundNonZero = true;
                            SwapColumns(tmpMatrix, i, j);
                            SwapColumns(m_sqRootMatrix, i, j);
                            // ... and quit searching
                            j = numColumns;
                            continue;
                        }
                    }
                    // if no non-zero element was found the matrix is not invertible
                    if (!foundNonZero)
                    {
                        throw new ArithmeticException("Squaring matrix is not invertible.");
                    }
                }

                // normalize i-th column
                int coef    = tmpMatrix[i].GetCoefficient(i);
                int invCoef = m_field.Inverse(coef);
                tmpMatrix[i].MultThisWithElement(invCoef);
                m_sqRootMatrix[i].MultThisWithElement(invCoef);

                if (ParallelUtils.IsParallel)
                {
                    // normalize all other columns
                    Parallel.For(0, numColumns, j =>
                    {
                        if (j != i)
                        {
                            int coefp = tmpMatrix[j].GetCoefficient(i);
                            if (coefp != 0)
                            {
                                PolynomialGF2mSmallM tmpSqColumn  = tmpMatrix[i].MultWithElement(coefp);
                                PolynomialGF2mSmallM tmpInvColumn = m_sqRootMatrix[i].MultWithElement(coefp);
                                tmpMatrix[j].AddToThis(tmpSqColumn);
                                lock (m_sqRootMatrix)
                                    m_sqRootMatrix[j].AddToThis(tmpInvColumn);
                            }
                        }
                    });
                }
                else
                {
                    for (int j = 0; j < numColumns; j++)
                    {
                        if (j != i)
                        {
                            coef = tmpMatrix[j].GetCoefficient(i);
                            if (coef != 0)
                            {
                                PolynomialGF2mSmallM tmpSqColumn  = tmpMatrix[i].MultWithElement(coef);
                                PolynomialGF2mSmallM tmpInvColumn = m_sqRootMatrix[i].MultWithElement(coef);
                                tmpMatrix[j].AddToThis(tmpSqColumn);
                                lock (m_sqRootMatrix)
                                    m_sqRootMatrix[j].AddToThis(tmpInvColumn);
                            }
                        }
                    }
                }
            }
        }
 /// <summary>
 /// Reduce this polynomial modulo another polynomial
 /// </summary>
 /// 
 /// <param name="F">The reduction polynomial</param>
 /// 
 /// <returns>Returns <c>this mod f</c></returns>
 public PolynomialGF2mSmallM Mod(PolynomialGF2mSmallM F)
 {
     int[] resultCoeff = Mod(_coefficients, F._coefficients, _field);
     return new PolynomialGF2mSmallM(_field, resultCoeff);
 }
 /// <summary>
 /// Swap two columns
 /// </summary>
 private static void SwapColumns(PolynomialGF2mSmallM[] Matrix, int First, int Second)
 {
     PolynomialGF2mSmallM tmp = Matrix[First];
     Matrix[First] = Matrix[Second];
     Matrix[Second] = tmp;
 }
        /// <summary>
        /// Compute the inverse of this polynomial modulo the given polynomial
        /// </summary>
        /// 
        /// <param name="A">The reduction polynomial</param>
        /// 
        /// <returns>Returns <c>this^(-1) mod a</c></returns>
        public PolynomialGF2mSmallM ModInverse(PolynomialGF2mSmallM A)
        {
            int[] unit = { 1 };
            int[] resultCoeff = ModDiv(unit, _coefficients, A._coefficients, _field);

            return new PolynomialGF2mSmallM(_field, resultCoeff);
        }
        /// <summary>
        /// Compute the squaring matrix for this polynomial ring, using the base field and the reduction polynomial
        /// </summary>
        private void ComputeSquaringMatrix()
        {
            int numColumns = _poly.Degree;
            _sqMatrix = new PolynomialGF2mSmallM[numColumns];
            PolynomialGF2mSmallM[] _sqMatrix2 = new PolynomialGF2mSmallM[numColumns];

            if (ParallelUtils.IsParallel)
            {
                int nct = numColumns >> 1;
                Parallel.For(0, nct, i =>
                {
                    int[] monomCoeffs = new int[(i << 1) + 1];
                    monomCoeffs[i << 1] = 1;
                    _sqMatrix[i] = new PolynomialGF2mSmallM(_field, monomCoeffs);
                });

                Parallel.For(nct, numColumns, i =>
                {
                    int[] monomCoeffs = new int[(i << 1) + 1];
                    monomCoeffs[i << 1] = 1;
                    PolynomialGF2mSmallM monomial = new PolynomialGF2mSmallM(_field, monomCoeffs);
                    _sqMatrix[i] = monomial.Mod(_poly);
                });
            }
            else
            {
                for (int i = 0; i < numColumns >> 1; i++)
                {
                    int[] monomCoeffs = new int[(i << 1) + 1];
                    monomCoeffs[i << 1] = 1;
                    _sqMatrix[i] = new PolynomialGF2mSmallM(_field, monomCoeffs);
                }

                for (int i = numColumns >> 1; i < numColumns; i++)
                {
                    int[] monomCoeffs = new int[(i << 1) + 1];
                    monomCoeffs[i << 1] = 1;
                    PolynomialGF2mSmallM monomial = new PolynomialGF2mSmallM(_field, monomCoeffs);
                    _sqMatrix[i] = monomial.Mod(_poly);
                }
            }
        }
        /// <summary>
        /// Compute a polynomial pair (a,b) from this polynomial and the given
        /// polynomial g with the property b*this = a mod g and deg(a)&lt;=deg(g)/2
        /// </summary>
        /// 
        /// <param name="G">The reduction polynomial</param>
        /// 
        /// <returns>Returns PolynomialGF2mSmallM[] {a,b} with b*this = a mod g and deg(a)&lt;= deg(g)/2</returns>
        public PolynomialGF2mSmallM[] ModPolynomialToFracton(PolynomialGF2mSmallM G)
        {
            int dg = G._degree >> 1;
            int[] a0 = NormalForm(G._coefficients);
            int[] a1 = Mod(_coefficients, G._coefficients, _field);
            int[] b0 = { 0 };
            int[] b1 = { 1 };

            while (ComputeDegree(a1) > dg)
            {
                int[][] q = Divide(a0, a1, _field);
                a0 = a1;
                a1 = q[1];
                int[] b2 = Add(b0, ModMultiply(q[0], b1, G._coefficients, _field), _field);
                b0 = b1;
                b1 = b2;
            }

            return new PolynomialGF2mSmallM[] { new PolynomialGF2mSmallM(_field, a1), new PolynomialGF2mSmallM(_field, b1) };
        }
示例#39
0
 /// <summary>
 /// Add the given polynomial to this polynomial (overwrite this).
 /// </summary>
 ///
 /// <param name="Addend">The addend</param>
 public void AddToThis(PolynomialGF2mSmallM Addend)
 {
     _coefficients = Add(_coefficients, Addend._coefficients, _field);
     ComputeDegree();
 }
        /// <summary>
        /// Compute the square root of this polynomial modulo the given polynomial
        /// </summary>
        /// 
        /// <param name="A">The reduction polynomial</param>
        /// 
        /// <returns>Returns <c>this^(1/2) mod A</c></returns>
        public PolynomialGF2mSmallM ModSquareRoot(PolynomialGF2mSmallM A)
        {
            int[] resultCoeff = IntUtils.DeepCopy(_coefficients);
            int[] help = ModMultiply(resultCoeff, resultCoeff, A._coefficients, _field);

            while (!IsEqual(help, _coefficients))
            {
                resultCoeff = NormalForm(help);
                help = ModMultiply(resultCoeff, resultCoeff, A._coefficients, _field);
            }

            return new PolynomialGF2mSmallM(_field, resultCoeff);
        }
示例#41
0
        /// <summary>
        /// Compute the product of this polynomial and the given factor using a Karatzuba like scheme
        /// </summary>
        ///
        /// <param name="Factor">the polynomial factor</param>
        ///
        /// <returns>Returns <c>this * factor</c></returns>
        public PolynomialGF2mSmallM Multiply(PolynomialGF2mSmallM Factor)
        {
            int[] resultCoeff = Multiply(_coefficients, Factor._coefficients, _field);

            return(new PolynomialGF2mSmallM(_field, resultCoeff));
        }
        /// <summary>
        /// Compute the product of this polynomial and the given factor using a Karatzuba like scheme
        /// </summary>
        /// 
        /// <param name="Factor">the polynomial factor</param>
        /// 
        /// <returns>Returns <c>this * factor</c></returns>
        public PolynomialGF2mSmallM Multiply(PolynomialGF2mSmallM Factor)
        {
            int[] resultCoeff = Multiply(_coefficients, Factor._coefficients, _field);

            return new PolynomialGF2mSmallM(_field, resultCoeff);
        }
示例#43
0
 /// <summary>
 /// Initialize this class for CCA2 MPKCS
 /// </summary>
 /// 
 /// <param name="N">Length of the code</param>
 /// <param name="K">The dimension of the code</param>
 /// <param name="Gf">The finite field <c>GF(2^m)</c></param>
 /// <param name="Gp">The irreducible Goppa polynomial</param>
 /// <param name="P">The permutation</param>
 /// <param name="H">The canonical check matrix</param>
 /// <param name="QInv">The matrix used to compute square roots in <c>(GF(2^m))^t</c></param>
 internal MPKCPrivateKey(int N, int K, GF2mField Gf, PolynomialGF2mSmallM Gp, Permutation P, GF2Matrix H, PolynomialGF2mSmallM[] QInv)
 {
     _N = N;
     _K = K;
     _gField = Gf;
     _goppaPoly = Gp;
     _P1 = P;
     _H = H;
     _qInv = QInv;
 }