예제 #1
0
        /// <summary>
        /// Compute the result of the division of two polynomials over the field <c>GF(2^m)</c>
        /// </summary>
        ///
        /// <param name="A">The first polynomial</param>
        /// <param name="F">The second polynomial</param>
        /// <param name="GF2">The GF2 field</param>
        ///
        /// <returns>Returns <c>int[][] {q,r}</c>, where <c>a = q*f+r</c> and <c>deg(r) &lt; deg(f)</c></returns>
        private static int[][] Divide(int[] A, int[] F, GF2mField GF2)
        {
            int df = ComputeDegree(F);
            int da = ComputeDegree(A) + 1;

            if (df == -1)
            {
                throw new ArithmeticException("Division by zero.");
            }

            int[][] result = new int[2][];
            result[0] = new int[1];
            result[1] = new int[da];
            int hc = HeadCoefficient(F);

            hc           = GF2.Inverse(hc);
            result[0][0] = 0;
            Array.Copy(A, 0, result[1], 0, result[1].Length);

            while (df <= ComputeDegree(result[1]))
            {
                int[] q;
                int[] coeff = new int[1];
                coeff[0] = GF2.Multiply(HeadCoefficient(result[1]), hc);
                q        = MultWithElement(F, coeff[0], GF2);
                int n = ComputeDegree(result[1]) - df;
                q         = MultWithMonomial(q, n);
                coeff     = MultWithMonomial(coeff, n);
                result[0] = Add(coeff, result[0], GF2);
                result[1] = Add(q, result[1], GF2);
            }

            return(result);
        }
예제 #2
0
 /// <summary>
 /// Construct a monomial of the given degree over the finite field GF(2^m)
 /// </summary>
 ///
 /// <param name="Field">The finite field GF(2^m)</param>
 /// <param name="Degree">The degree of the monomial</param>
 public PolynomialGF2mSmallM(GF2mField Field, int Degree)
 {
     _field                = Field;
     _degree               = Degree;
     _coefficients         = new int[Degree + 1];
     _coefficients[Degree] = 1;
 }
예제 #3
0
        /// <summary>
        /// Creates the vector over GF(2^m) of given length and with elements from array V (beginning at the first bit)
        /// </summary>
        /// 
        /// <param name="Field">The finite field</param>
        /// <param name="V">An array with elements of vector</param>
        public GF2mVector(GF2mField Field, byte[] V)
        {
            _field = new GF2mField(Field);

            // decode vector
            int d = 8;
            int count = 1;
            while (Field.Degree > d)
            {
                count++;
                d += 8;
            }

            if ((V.Length % count) != 0)
                throw new ArgumentException("GF2mVector: Byte array is not an encoded vector over the given finite field!");

            Length = V.Length / count;
            _vector = new int[Length];
            count = 0;

            for (int i = 0; i < _vector.Length; i++)
            {
                for (int j = 0; j < d; j += 8)
                    _vector[i] |= (V[count++] & 0xff) << j;

                if (!Field.IsElementOfThisField(_vector[i]))
                    throw new ArgumentException("GF2mVector: Byte array is not an encoded vector over the given finite field!");
            }
        }
예제 #4
0
        /// <summary>
        /// Reduce a polynomial modulo another polynomial
        /// </summary>
        ///
        /// <param name="A">The polynomial</param>
        /// <param name="F">The reduction polynomial</param>
        /// <param name="GF2">The GF2 field</param>
        ///
        /// <returns>Returns <c>a mod f</c></returns>
        private static int[] Mod(int[] A, int[] F, GF2mField GF2)
        {
            int df = ComputeDegree(F);

            if (df == -1)
            {
                throw new ArithmeticException("Division by zero");
            }

            int[] result = new int[A.Length];
            int   hc     = HeadCoefficient(F);

            hc = GF2.Inverse(hc);
            Array.Copy(A, 0, result, 0, result.Length);
            while (df <= ComputeDegree(result))
            {
                int[] q;
                int   coeff = GF2.Multiply(HeadCoefficient(result), hc);
                q      = MultWithMonomial(F, ComputeDegree(result) - df);
                q      = MultWithElement(q, coeff, GF2);
                result = Add(q, result, GF2);
            }

            return(result);
        }
예제 #5
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();
 }
예제 #6
0
 /// <summary>
 /// Create an instance using values from a field and matrix
 /// </summary>
 ///
 /// <param name="FieldG">A finite field GF(2^m)</param>
 /// <param name="MatrixN">The matrix as int array; only the reference is copied.</param>
 protected GF2mMatrix(GF2mField FieldG, int[][] MatrixN)
 {
     this.FieldG  = FieldG;
     this.MatrixN = MatrixN;
     RowCount     = MatrixN.Length;
     ColumnCount  = MatrixN[0].Length;
 }
 /// <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();
 }
예제 #8
0
        /// <summary>
        /// Rewrite this vector as a vector over <c>GF(2^m)</c> with <c>t</c> elements
        /// </summary>
        ///
        /// <param name="Field">The finite field <c>GF(2<sup>m</sup>)</c></param>
        ///
        /// <returns>Returns the converted vector over <c>GF(2<sup>m</sup>)</c></returns>
        public GF2mVector ToExtensionFieldVector(GF2mField Field)
        {
            int m = Field.Degree;

            if ((Length % m) != 0)
            {
                throw new ArithmeticException("GF2Vector: Conversion is impossible!");
            }

            int t = Length / m;

            int[] result = new int[t];
            int   count  = 0;

            for (int i = t - 1; i >= 0; i--)
            {
                for (int j = Field.Degree - 1; j >= 0; j--)
                {
                    int q = IntUtils.URShift(count, 5);
                    int r = count & 0x1f;

                    int e = (IntUtils.URShift(m_elements[q], r)) & 1;
                    if (e == 1)
                    {
                        result[i] ^= 1 << j;
                    }

                    count++;
                }
            }
            return(new GF2mVector(Field, result));
        }
 /// <summary>
 /// Construct a monomial of the given degree over the finite field GF(2^m)
 /// </summary>
 /// 
 /// <param name="Field">The finite field GF(2^m)</param>
 /// <param name="Degree">The degree of the monomial</param>
 public PolynomialGF2mSmallM(GF2mField Field, int Degree)
 {
     _field = Field;
     _degree = Degree;
     _coefficients = new int[Degree + 1];
     _coefficients[Degree] = 1;
 }
예제 #10
0
 /// <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);
 }
예제 #11
0
        /// <summary>
        /// Create an instance using values from another GF2mMatrix instance
        /// </summary>
        /// 
        /// <param name="G">The GF2mMatrix instance</param>
        public GF2mMatrix(GF2mMatrix G)
        {
            RowCount = G.RowCount;
            ColumnCount = G.ColumnCount;
            FieldG = G.FieldG;
            MatrixN = new int[RowCount][];

            for (int i = 0; i < RowCount; i++)
                MatrixN[i] = IntUtils.DeepCopy(G.MatrixN[i]);
        }
예제 #12
0
 /// <summary>
 /// Create a new vector over <c>GF(2^m)</c> of the given length and element array
 /// </summary>
 /// 
 /// <param name="Field">The finite field <c>GF(2^m)</c></param>
 /// <param name="Vector">The element array</param>
 public GF2mVector(GF2mField Field, int[] Vector)
 {
     _field = Field;
     Length = Vector.Length;
     for (int i = Vector.Length - 1; i >= 0; i--)
     {
         if (!Field.IsElementOfThisField(Vector[i]))
             throw new ArithmeticException("Element array is not specified over the given finite field.");
     }
     _vector = IntUtils.DeepCopy(Vector);
 }
예제 #13
0
        /// <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);
            }
        }
예제 #14
0
        /// <summary>
        /// Create an instance using values from another GF2mMatrix instance
        /// </summary>
        ///
        /// <param name="G">The GF2mMatrix instance</param>
        public GF2mMatrix(GF2mMatrix G)
        {
            RowCount    = G.RowCount;
            ColumnCount = G.ColumnCount;
            FieldG      = G.FieldG;
            MatrixN     = new int[RowCount][];

            for (int i = 0; i < RowCount; i++)
            {
                MatrixN[i] = IntUtils.DeepCopy(G.MatrixN[i]);
            }
        }
예제 #15
0
 /// <summary>
 /// Create a new vector over <c>GF(2^m)</c> of the given length and element array
 /// </summary>
 ///
 /// <param name="Field">The finite field <c>GF(2^m)</c></param>
 /// <param name="Vector">The element array</param>
 public GF2mVector(GF2mField Field, int[] Vector)
 {
     m_field = Field;
     Length  = Vector.Length;
     for (int i = Vector.Length - 1; i >= 0; i--)
     {
         if (!Field.IsElementOfThisField(Vector[i]))
         {
             throw new ArithmeticException("Element array is not specified over the given finite field.");
         }
     }
     m_vector = IntUtils.DeepCopy(Vector);
 }
예제 #16
0
        /// <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]);
        }
예제 #17
0
        /// <summary>
        /// Checks if the given object is equal to this field
        /// </summary>
        ///
        /// <param name="Obj">The object for comparison</param>
        ///
        /// <returns>Returns false if the object is not equal</returns>
        public override bool Equals(Object Obj)
        {
            if (Obj == null)
            {
                return(false);
            }
            if (!(Obj is GF2mField))
            {
                return(false);
            }

            GF2mField other = (GF2mField)Obj;

            return((m_degree == other.m_degree) && (m_polynomial == other.m_polynomial));
        }
        /// <summary>
        /// Construct a polynomial over the finite field GF(2^m)
        /// </summary>
        /// 
        /// <param name="Field">The finite field GF(2^m)</param>
        /// <param name="Degree">The  degree of polynomial</param>
        /// <param name="PolynomialType">The  type of polynomial</param>
        /// <param name="Rand">The IRandom instance</param>
        public PolynomialGF2mSmallM(GF2mField Field, int Degree, char PolynomialType, IRandom Rand)
        {
            _field = Field;

            switch (PolynomialType)
            {
                case PolynomialGF2mSmallM.RANDOM_IRREDUCIBLE_POLYNOMIAL:
                    _coefficients = CreateRandomIrreduciblePolynomial(Degree, Rand);
                    break;
                default:
                    throw new ArgumentException(" Error: type " + PolynomialType + " is not defined for GF2smallmPolynomial");
            }

            ComputeDegree();
        }
예제 #19
0
        /// <summary>
        /// Construct a polynomial over the finite field GF(2^m)
        /// </summary>
        ///
        /// <param name="Field">The finite field GF(2^m)</param>
        /// <param name="Degree">The  degree of polynomial</param>
        /// <param name="PolynomialType">The  type of polynomial</param>
        /// <param name="Rand">The IRandom instance</param>
        public PolynomialGF2mSmallM(GF2mField Field, int Degree, char PolynomialType, IRandom Rand)
        {
            _field = Field;

            switch (PolynomialType)
            {
            case PolynomialGF2mSmallM.RANDOM_IRREDUCIBLE_POLYNOMIAL:
                _coefficients = CreateRandomIrreduciblePolynomial(Degree, Rand);
                break;

            default:
                throw new ArgumentException(" Error: type " + PolynomialType + " is not defined for GF2smallmPolynomial");
            }

            ComputeDegree();
        }
예제 #20
0
        /// <summary>
        /// Initialze this class with an encoded matrix
        /// </summary>
        ///
        /// <param name="FieldG">The finite field GF(2^m)</param>
        /// <param name="Encoded">The matrix in byte array form</param>
        public GF2mMatrix(GF2mField FieldG, byte[] Encoded)
        {
            this.FieldG = FieldG;
            int d     = 8;
            int count = 1;

            while (FieldG.Degree > d)
            {
                count++;
                d += 8;
            }

            if (Encoded.Length < 5)
            {
                throw new ArgumentException("GF2mMatrix: Given array is not encoded matrix over GF(2^m)!");
            }

            this.RowCount = ((Encoded[3] & 0xff) << 24) ^ ((Encoded[2] & 0xff) << 16) ^ ((Encoded[1] & 0xff) << 8) ^ (Encoded[0] & 0xff);
            int n = count * this.RowCount;

            if ((this.RowCount <= 0) || (((Encoded.Length - 4) % n) != 0))
            {
                throw new ArgumentException("GF2mMatrix: Given array is not encoded matrix over GF(2^m)!");
            }

            this.ColumnCount = (Encoded.Length - 4) / n;
            MatrixN          = ArrayUtils.CreateJagged <int[][]>(this.RowCount, this.ColumnCount);
            count            = 4;

            for (int i = 0; i < this.RowCount; i++)
            {
                for (int j = 0; j < this.ColumnCount; j++)
                {
                    for (int k = 0; k < d; k += 8)
                    {
                        MatrixN[i][j] ^= (Encoded[count++] & 0x000000ff) << k;
                    }

                    if (!this.FieldG.IsElementOfThisField(MatrixN[i][j]))
                    {
                        throw new ArgumentException("GF2mMatrix: Given array is not encoded matrix over GF(2^m)!");
                    }
                }
            }
        }
예제 #21
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);
        }
예제 #22
0
        /// <summary>
        /// Return the greatest common divisor of two polynomials over the field <c>GF(2^m)</c>
        /// </summary>
        ///
        /// <param name="F">The first polynomial</param>
        /// <param name="G">The second polynomial</param>
        /// <param name="GF2">The GF2 field</param>
        ///
        /// <returns>Returns <c>Gcd(f, g)</c></returns>
        private static int[] Gcd(int[] F, int[] G, GF2mField GF2)
        {
            int[] a = F;
            int[] b = G;
            if (ComputeDegree(a) == -1)
            {
                return(b);
            }

            while (ComputeDegree(b) != -1)
            {
                int[] c = Mod(a, b, GF2);
                a = new int[b.Length];
                Array.Copy(b, 0, a, 0, a.Length);
                b = new int[c.Length];
                Array.Copy(c, 0, b, 0, b.Length);
            }
            int coeff = GF2.Inverse(HeadCoefficient(a));

            return(MultWithElement(a, coeff, GF2));
        }
예제 #23
0
        /// <summary>
        /// Create a polynomial over the finite field GF(2^m)
        /// </summary>
        ///
        /// <param name="Field">The finite field GF(2^m)</param>
        /// <param name="Encoded">The polynomial in byte array form</param>
        public PolynomialGF2mSmallM(GF2mField Field, byte[] Encoded)
        {
            _field = Field;
            int d     = 8;
            int count = 1;

            while (Field.Degree > d)
            {
                count++;
                d += 8;
            }

            if ((Encoded.Length % count) != 0)
            {
                throw new ArgumentException("PolynomialGF2mSmallM: byte array is not encoded polynomial over given finite field GF2m!");
            }

            _coefficients = new int[Encoded.Length / count];
            count         = 0;
            for (int i = 0; i < _coefficients.Length; i++)
            {
                for (int j = 0; j < d; j += 8)
                {
                    _coefficients[i] ^= (Encoded[count++] & 0x000000ff) << j;
                }

                if (!this._field.IsElementOfThisField(_coefficients[i]))
                {
                    throw new ArgumentException(" PolynomialGF2mSmallM: byte array is not encoded polynomial over given finite field GF2m!");
                }
            }

            // if HC = 0 for non-zero polynomial, returns error
            if ((_coefficients.Length != 1) && (_coefficients[_coefficients.Length - 1] == 0))
            {
                throw new ArgumentException("PolynomialGF2mSmallM: byte array is not encoded polynomial over given finite field GF2m");
            }

            ComputeDegree();
        }
예제 #24
0
        /// <summary>
        /// Compute the product of a polynomial a with an element from the finite field <c>GF(2^m)</c>
        /// </summary>
        ///
        /// <param name="A">The polynomial</param>
        /// <param name="Element">An element of the finite field GF(2^m)</param>
        /// <param name="GF2">The GF2 field</param>
        ///
        /// <returns>Return <c>a * element</c></returns>
        private static int[] MultWithElement(int[] A, int Element, GF2mField GF2)
        {
            int degree = ComputeDegree(A);

            if (degree == -1 || Element == 0)
            {
                return(new int[1]);
            }

            if (Element == 1)
            {
                return(IntUtils.DeepCopy(A));
            }

            int[] result = new int[degree + 1];
            for (int i = degree; i >= 0; i--)
            {
                result[i] = GF2.Multiply(A[i], Element);
            }

            return(result);
        }
예제 #25
0
        /// <summary>
        /// Compute the sum of two polynomials a and b over the finite field <c>GF(2^m)</c>
        /// </summary>
        ///
        /// <param name="A">The first polynomial</param>
        /// <param name="B">The second polynomial</param>
        /// <param name="GF2">The GF2 field</param>
        ///
        /// <returns>Return a + b</returns>
        private static int[] Add(int[] A, int[] B, GF2mField GF2)
        {
            int[] result, addend;
            if (A.Length < B.Length)
            {
                result = new int[B.Length];
                Array.Copy(B, 0, result, 0, B.Length);
                addend = A;
            }
            else
            {
                result = new int[A.Length];
                Array.Copy(A, 0, result, 0, A.Length);
                addend = B;
            }

            for (int i = addend.Length - 1; i >= 0; i--)
            {
                result[i] = GF2.Add(result[i], addend[i]);
            }

            return(result);
        }
예제 #26
0
        /// <summary>
        /// Initialze this class with an encoded matrix
        /// </summary>
        /// 
        /// <param name="FieldG">The finite field GF(2^m)</param>
        /// <param name="Encoded">The matrix in byte array form</param>
        public GF2mMatrix(GF2mField FieldG, byte[] Encoded)
        {
            this.FieldG = FieldG;
            int d = 8;
            int count = 1;

            while (FieldG.Degree > d)
            {
                count++;
                d += 8;
            }

            if (Encoded.Length < 5)
                throw new ArgumentException("GF2mMatrix: Given array is not encoded matrix over GF(2^m)!");

            this.RowCount = ((Encoded[3] & 0xff) << 24) ^ ((Encoded[2] & 0xff) << 16) ^ ((Encoded[1] & 0xff) << 8) ^ (Encoded[0] & 0xff);
            int n = count * this.RowCount;

            if ((this.RowCount <= 0) || (((Encoded.Length - 4) % n) != 0))
                throw new ArgumentException("GF2mMatrix: Given array is not encoded matrix over GF(2^m)!");

            this.ColumnCount = (Encoded.Length - 4) / n;
            MatrixN = ArrayUtils.CreateJagged<int[][]>(this.RowCount, this.ColumnCount);
            count = 4;

            for (int i = 0; i < this.RowCount; i++)
            {
                for (int j = 0; j < this.ColumnCount; j++)
                {
                    for (int k = 0; k < d; k += 8)
                        MatrixN[i][j] ^= (Encoded[count++] & 0x000000ff) << k;

                    if (!this.FieldG.IsElementOfThisField(MatrixN[i][j]))
                        throw new ArgumentException("GF2mMatrix: Given array is not encoded matrix over GF(2^m)!");
                }
            }
        }
예제 #27
0
        /// <summary>
        /// Creates the vector over GF(2^m) of given length and with elements from array V (beginning at the first bit)
        /// </summary>
        ///
        /// <param name="Field">The finite field</param>
        /// <param name="V">An array with elements of vector</param>
        public GF2mVector(GF2mField Field, byte[] V)
        {
            m_field = new GF2mField(Field);

            // decode vector
            int d     = 8;
            int count = 1;

            while (Field.Degree > d)
            {
                count++;
                d += 8;
            }

            if ((V.Length % count) != 0)
            {
                throw new ArgumentException("GF2mVector: Byte array is not an encoded vector over the given finite field!");
            }

            Length   = V.Length / count;
            m_vector = new int[Length];
            count    = 0;

            for (int i = 0; i < m_vector.Length; i++)
            {
                for (int j = 0; j < d; j += 8)
                {
                    m_vector[i] |= (V[count++] & 0xff) << j;
                }

                if (!Field.IsElementOfThisField(m_vector[i]))
                {
                    throw new ArgumentException("GF2mVector: Byte array is not an encoded vector over the given finite field!");
                }
            }
        }
예제 #28
0
        /// <summary>
        /// Compute the result of the division of two polynomials modulo a third polynomial over the field <c>GF(2^m)</c>
        /// </summary>
        ///
        /// <param name="A">The first polynomial</param>
        /// <param name="B">The second polynomial</param>
        /// <param name="G">The reduction polynomial</param>
        /// <param name="GF2">The GF2 field</param>
        ///
        /// <returns>Returns <c>a * b^(-1) mod g</c></returns>
        private static int[] ModDiv(int[] A, int[] B, int[] G, GF2mField GF2)
        {
            int[]   r0 = NormalForm(G);
            int[]   r1 = Mod(B, G, GF2);
            int[]   s0 = { 0 };
            int[]   s1 = Mod(A, G, GF2);
            int[]   s2;
            int[][] q;

            while (ComputeDegree(r1) != -1)
            {
                q  = Divide(r0, r1, GF2);
                r0 = NormalForm(r1);
                r1 = NormalForm(q[1]);
                s2 = Add(s0, ModMultiply(q[0], s1, G, GF2), GF2);
                s0 = NormalForm(s1);
                s1 = NormalForm(s2);
            }
            int hc = HeadCoefficient(r0);

            s0 = MultWithElement(s0, GF2.Inverse(hc), GF2);

            return(s0);
        }
        /// <summary>
        /// Create a polynomial over the finite field GF(2^m)
        /// </summary>
        /// 
        /// <param name="Field">The finite field GF(2^m)</param>
        /// <param name="Encoded">The polynomial in byte array form</param>
        public PolynomialGF2mSmallM(GF2mField Field, byte[] Encoded)
        {
            _field = Field;
            int d = 8;
            int count = 1;
            while (Field.Degree > d)
            {
                count++;
                d += 8;
            }

            if ((Encoded.Length % count) != 0)
                throw new ArgumentException("PolynomialGF2mSmallM: byte array is not encoded polynomial over given finite field GF2m!");

            _coefficients = new int[Encoded.Length / count];
            count = 0;
            for (int i = 0; i < _coefficients.Length; i++)
            {
                for (int j = 0; j < d; j += 8)
                    _coefficients[i] ^= (Encoded[count++] & 0x000000ff) << j;

                if (!this._field.IsElementOfThisField(_coefficients[i]))
                    throw new ArgumentException(" PolynomialGF2mSmallM: byte array is not encoded polynomial over given finite field GF2m!");
            }

            // if HC = 0 for non-zero polynomial, returns error
            if ((_coefficients.Length != 1) && (_coefficients[_coefficients.Length - 1] == 0))
                throw new ArgumentException("PolynomialGF2mSmallM: byte array is not encoded polynomial over given finite field GF2m");

            ComputeDegree();
        }
        /// <summary>
        /// Compute the product of a polynomial a with an element from the finite field <c>GF(2^m)</c>
        /// </summary>
        /// 
        /// <param name="A">The polynomial</param>
        /// <param name="Element">An element of the finite field GF(2^m)</param>
        /// <param name="GF2">The GF2 field</param>
        /// 
        /// <returns>Return <c>a * element</c></returns>
        private static int[] MultWithElement(int[] A, int Element, GF2mField GF2)
        {
            int degree = ComputeDegree(A);
            if (degree == -1 || Element == 0)
                return new int[1];

            if (Element == 1)
                return IntUtils.DeepCopy(A);

            int[] result = new int[degree + 1];
            for (int i = degree; i >= 0; i--)
                result[i] = GF2.Multiply(A[i], Element);

            return result;
        }
예제 #31
0
        /// <summary>
        /// Check a polynomial for irreducibility over the field <c>GF(2^m)</c>
        /// </summary>
        ///
        /// <param name="A">The polynomial to check</param>
        /// <param name="GF2">The GF2 field</param>
        ///
        /// <returns>Returns true if a is irreducible, false otherwise</returns>
        private static bool IsIrreducible(int[] A, GF2mField GF2)
        {
            if (A[0] == 0)
            {
                return(false);
            }

            bool state = true;
            int  d     = ComputeDegree(A) >> 1;

            int[] u           = { 0, 1 };
            int[] Y           = { 0, 1 };
            int   fieldDegree = GF2.Degree;

            if (ParallelUtils.IsParallel)
            {
                CancellationTokenSource cts     = new CancellationTokenSource();
                ParallelOptions         options = new ParallelOptions();
                options.MaxDegreeOfParallelism = Environment.ProcessorCount;
                options.CancellationToken      = cts.Token;
                options.CancellationToken.ThrowIfCancellationRequested();

                try
                {
                    Parallel.For(0, d, options, loopState =>
                    {
                        if (!cts.IsCancellationRequested)
                        {
                            for (int j = fieldDegree - 1; j >= 0; j--)
                            {
                                u = ModMultiply(u, u, A, GF2);
                            }

                            u       = NormalForm(u);
                            int[] g = Gcd(Add(u, Y, GF2), A, GF2);

                            if (ComputeDegree(g) != 0)
                            {
                                state = false;
                                cts.Cancel();
                            }
                        }
                    });
                }
                catch { }
            }
            else
            {
                for (int i = 0; i < d; i++)
                {
                    for (int j = fieldDegree - 1; j >= 0; j--)
                    {
                        u = ModMultiply(u, u, A, GF2);
                    }

                    u = NormalForm(u);
                    int[] g = Gcd(Add(u, Y, GF2), A, GF2);

                    if (ComputeDegree(g) != 0)
                    {
                        state = false;
                    }
                }
            }

            return(state);
        }
예제 #32
0
        /// <summary>
        /// Rewrite this vector as a vector over <c>GF(2^m)</c> with <c>t</c> elements
        /// </summary>
        /// 
        /// <param name="Field">The finite field <c>GF(2<sup>m</sup>)</c></param>
        /// 
        /// <returns>Returns the converted vector over <c>GF(2<sup>m</sup>)</c></returns>
        public GF2mVector ToExtensionFieldVector(GF2mField Field)
        {
            int m = Field.Degree;
            if ((Length % m) != 0)
                throw new ArithmeticException("GF2Vector: Conversion is impossible!");

            int t = Length / m;
            int[] result = new int[t];
            int count = 0;
            for (int i = t - 1; i >= 0; i--)
            {
                for (int j = Field.Degree - 1; j >= 0; j--)
                {
                    int q = IntUtils.URShift(count, 5);
                    int r = count & 0x1f;

                    int e = (IntUtils.URShift(_elements[q], r)) & 1;
                    if (e == 1)
                        result[i] ^= 1 << j;

                    count++;
                }
            }
            return new GF2mVector(Field, result);
        }
        /// <summary>
        /// Compute the result of the division of two polynomials modulo a third polynomial over the field <c>GF(2^m)</c>
        /// </summary>
        /// 
        /// <param name="A">The first polynomial</param>
        /// <param name="B">The second polynomial</param>
        /// <param name="G">The reduction polynomial</param>
        /// <param name="GF2">The GF2 field</param>
        /// 
        /// <returns>Returns <c>a * b^(-1) mod g</c></returns>
        private static int[] ModDiv(int[] A, int[] B, int[] G, GF2mField GF2)
        {
            int[] r0 = NormalForm(G);
            int[] r1 = Mod(B, G, GF2);
            int[] s0 = { 0 };
            int[] s1 = Mod(A, G, GF2);
            int[] s2;
            int[][] q;

            while (ComputeDegree(r1) != -1)
            {
                q = Divide(r0, r1, GF2);
                r0 = NormalForm(r1);
                r1 = NormalForm(q[1]);
                s2 = Add(s0, ModMultiply(q[0], s1, G, GF2), GF2);
                s0 = NormalForm(s1);
                s1 = NormalForm(s2);
            }
            int hc = HeadCoefficient(r0);
            s0 = MultWithElement(s0, GF2.Inverse(hc), GF2);

            return s0;
        }
예제 #34
0
 /// <summary>
 /// The copy constructor
 /// </summary>
 /// 
 /// <param name="GF">The GF2mVector to copy</param>
 public GF2mVector(GF2mVector GF)
 {
     _field = new GF2mField(GF._field);
     Length = GF.Length;
     _vector = IntUtils.DeepCopy(GF._vector);
 }
예제 #35
0
 /// <summary>
 /// Construct the polynomial over the given finite field GF(2^m) from the given coefficient vector
 /// </summary>
 ///
 /// <param name="Field">The finite field GF2m</param>
 /// <param name="Coeffs">The coefficient vector</param>
 public PolynomialGF2mSmallM(GF2mField Field, int[] Coeffs)
 {
     _field        = Field;
     _coefficients = NormalForm(Coeffs);
     ComputeDegree();
 }
        /// <summary>
        /// Compute the result of the division of two polynomials over the field <c>GF(2^m)</c>
        /// </summary>
        /// 
        /// <param name="A">The first polynomial</param>
        /// <param name="F">The second polynomial</param>
        /// <param name="GF2">The GF2 field</param>
        /// 
        /// <returns>Returns <c>int[][] {q,r}</c>, where <c>a = q*f+r</c> and <c>deg(r) &lt; deg(f)</c></returns>
        private static int[][] Divide(int[] A, int[] F, GF2mField GF2)
        {
            int df = ComputeDegree(F);
            int da = ComputeDegree(A) + 1;
            if (df == -1)
                throw new ArithmeticException("Division by zero.");

            int[][] result = new int[2][];
            result[0] = new int[1];
            result[1] = new int[da];
            int hc = HeadCoefficient(F);
            hc = GF2.Inverse(hc);
            result[0][0] = 0;
            Array.Copy(A, 0, result[1], 0, result[1].Length);

            while (df <= ComputeDegree(result[1]))
            {
                int[] q;
                int[] coeff = new int[1];
                coeff[0] = GF2.Multiply(HeadCoefficient(result[1]), hc);
                q = MultWithElement(F, coeff[0], GF2);
                int n = ComputeDegree(result[1]) - df;
                q = MultWithMonomial(q, n);
                coeff = MultWithMonomial(coeff, n);
                result[0] = Add(coeff, result[0], GF2);
                result[1] = Add(q, result[1], GF2);
            }

            return result;
        }
예제 #37
0
 /// <summary>
 /// The copy constructor
 /// </summary>
 ///
 /// <param name="GF">The GF2mVector to copy</param>
 public GF2mVector(GF2mVector GF)
 {
     m_field  = new GF2mField(GF.m_field);
     Length   = GF.Length;
     m_vector = IntUtils.DeepCopy(GF.m_vector);
 }
예제 #38
0
 /// <summary>
 /// Construct the zero polynomial over the finite field GF(2^m)
 /// </summary>
 ///
 /// <param name="Field">The finite field GF(2^m)</param>
 public PolynomialGF2mSmallM(GF2mField Field)
 {
     _field        = Field;
     _degree       = -1;
     _coefficients = new int[1];
 }
예제 #39
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));
        }
예제 #40
0
 /// <summary>
 /// Create a finite field GF(2^m) using another GF2mField class
 /// </summary>
 /// 
 /// <param name="Field">The GF2mField class to copy</param>
 public GF2mField(GF2mField Field)
 {
     _degree = Field._degree;
     _polynomial = Field._polynomial;
 }
예제 #41
0
 /// <summary>
 /// Compute the product of two polynomials modulo a third polynomial over the finite field <c>GF(2^m)</c>
 /// </summary>
 ///
 /// <param name="A">The first polynomial</param>
 /// <param name="B">The second polynomial</param>
 /// <param name="G">The reduction polynomial</param>
 /// <param name="GF2">The GF2 field</param>
 ///
 /// <returns>Returns <c>a * b mod g</c></returns>
 private static int[] ModMultiply(int[] A, int[] B, int[] G, GF2mField GF2)
 {
     return(Mod(Multiply(A, B, GF2), G, GF2));
 }
 /// <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>
 /// Get a randome element over degree Gf2
 /// </summary>
 /// 
 /// <param name="SecRnd">The source of randomness</param>
 /// <param name="GFM">The Gf2 field</param>
 /// 
 /// <returns>A random element</returns>
 private static int GetRandomElement(IRandom SecRnd, GF2mField GFM)
 {
     return RandomDegree.NextInt(SecRnd, 1 << GFM.Degree);
 }
 /// <summary>
 /// Construct the zero polynomial over the finite field GF(2^m)
 /// </summary>
 /// 
 /// <param name="Field">The finite field GF(2^m)</param>
 public PolynomialGF2mSmallM(GF2mField Field)
 {
     _field = Field;
     _degree = -1;
     _coefficients = new int[1];
 }
        /// <summary>
        /// Check a polynomial for irreducibility over the field <c>GF(2^m)</c>
        /// </summary>
        /// 
        /// <param name="A">The polynomial to check</param>
        /// <param name="GF2">The GF2 field</param>
        /// 
        /// <returns>Returns true if a is irreducible, false otherwise</returns>
        private static bool IsIrreducible(int[] A, GF2mField GF2)
        {
            if (A[0] == 0)
                return false;

            bool state = true;
            int d = ComputeDegree(A) >> 1;
            int[] u = { 0, 1 };
            int[] Y = { 0, 1 };
            int fieldDegree = GF2.Degree;

            if (ParallelUtils.IsParallel)
            {
                CancellationTokenSource cts = new CancellationTokenSource();
                ParallelOptions options = new ParallelOptions();
                options.MaxDegreeOfParallelism = Environment.ProcessorCount;
                options.CancellationToken = cts.Token;
                options.CancellationToken.ThrowIfCancellationRequested();

                try
                {
                    Parallel.For(0, d, options, loopState =>
                    {
                        if (!cts.IsCancellationRequested)
                        {
                            for (int j = fieldDegree - 1; j >= 0; j--)
                                u = ModMultiply(u, u, A, GF2);

                            u = NormalForm(u);
                            int[] g = Gcd(Add(u, Y, GF2), A, GF2);

                            if (ComputeDegree(g) != 0)
                            {
                                state = false;
                                cts.Cancel();
                            }
                        }
                    });
                }
                catch { }
            }
            else
            {
                for (int i = 0; i < d; i++)
                {
                    for (int j = fieldDegree - 1; j >= 0; j--)
                        u = ModMultiply(u, u, A, GF2);

                    u = NormalForm(u);
                    int[] g = Gcd(Add(u, Y, GF2), A, GF2);

                    if (ComputeDegree(g) != 0)
                        state = false;
                }
            }

            return state;
        }
        /// <summary>
        /// Compute the sum of two polynomials a and b over the finite field <c>GF(2^m)</c>
        /// </summary>
        /// 
        /// <param name="A">The first polynomial</param>
        /// <param name="B">The second polynomial</param>
        /// <param name="GF2">The GF2 field</param>
        /// 
        /// <returns>Return a + b</returns>
        private static int[] Add(int[] A, int[] B, GF2mField GF2)
        {
            int[] result, addend;
            if (A.Length < B.Length)
            {
                result = new int[B.Length];
                Array.Copy(B, 0, result, 0, B.Length);
                addend = A;
            }
            else
            {
                result = new int[A.Length];
                Array.Copy(A, 0, result, 0, A.Length);
                addend = B;
            }

            for (int i = addend.Length - 1; i >= 0; i--)
                result[i] = GF2.Add(result[i], addend[i]);

            return result;
        }
예제 #47
0
        /// <summary>
        /// Compute the product of two polynomials over the field <c>GF(2^m)</c> using a Karatzuba like multiplication
        /// </summary>
        ///
        /// <param name="A">The first polynomial</param>
        /// <param name="B">The second polynomial</param>
        /// <param name="GF2">The GF2 field</param>
        ///
        /// <returns>Returns <c>a * b</c></returns>
        private static int[] Multiply(int[] A, int[] B, GF2mField GF2)
        {
            int[] mult1, mult2;
            if (ComputeDegree(A) < ComputeDegree(B))
            {
                mult1 = B;
                mult2 = A;
            }
            else
            {
                mult1 = A;
                mult2 = B;
            }

            mult1 = NormalForm(mult1);
            mult2 = NormalForm(mult2);

            if (mult2.Length == 1)
            {
                return(MultWithElement(mult1, mult2[0], GF2));
            }

            int d1 = mult1.Length;
            int d2 = mult2.Length;

            int[] result = new int[d1 + d2 - 1];

            if (d2 != d1)
            {
                int[] res1 = new int[d2];
                int[] res2 = new int[d1 - d2];
                Array.Copy(mult1, 0, res1, 0, res1.Length);
                Array.Copy(mult1, d2, res2, 0, res2.Length);
                res1   = Multiply(res1, mult2, GF2);
                res2   = Multiply(res2, mult2, GF2);
                res2   = MultWithMonomial(res2, d2);
                result = Add(res1, res2, GF2);
            }
            else
            {
                d2 = IntUtils.URShift((d1 + 1), 1);
                int   d = d1 - d2;
                int[] firstPartMult1  = new int[d2];
                int[] firstPartMult2  = new int[d2];
                int[] secondPartMult1 = new int[d];
                int[] secondPartMult2 = new int[d];
                Array.Copy(mult1, 0, firstPartMult1, 0, firstPartMult1.Length);
                Array.Copy(mult1, d2, secondPartMult1, 0, secondPartMult1.Length);
                Array.Copy(mult2, 0, firstPartMult2, 0, firstPartMult2.Length);
                Array.Copy(mult2, d2, secondPartMult2, 0, secondPartMult2.Length);
                int[] helpPoly1 = Add(firstPartMult1, secondPartMult1, GF2);
                int[] helpPoly2 = Add(firstPartMult2, secondPartMult2, GF2);
                int[] res1      = Multiply(firstPartMult1, firstPartMult2, GF2);
                int[] res2      = Multiply(helpPoly1, helpPoly2, GF2);
                int[] res3      = Multiply(secondPartMult1, secondPartMult2, GF2);
                res2   = Add(res2, res1, GF2);
                res2   = Add(res2, res3, GF2);
                res3   = MultWithMonomial(res3, d2);
                result = Add(res2, res3, GF2);
                result = MultWithMonomial(result, d2);
                result = Add(result, res1, GF2);
            }

            return(result);
        }
        /// <summary>
        /// Return the greatest common divisor of two polynomials over the field <c>GF(2^m)</c>
        /// </summary>
        /// 
        /// <param name="F">The first polynomial</param>
        /// <param name="G">The second polynomial</param>
        /// <param name="GF2">The GF2 field</param>
        /// 
        /// <returns>Returns <c>Gcd(f, g)</c></returns>
        private static int[] Gcd(int[] F, int[] G, GF2mField GF2)
        {
            int[] a = F;
            int[] b = G;
            if (ComputeDegree(a) == -1)
                return b;

            while (ComputeDegree(b) != -1)
            {
                int[] c = Mod(a, b, GF2);
                a = new int[b.Length];
                Array.Copy(b, 0, a, 0, a.Length);
                b = new int[c.Length];
                Array.Copy(c, 0, b, 0, b.Length);
            }
            int coeff = GF2.Inverse(HeadCoefficient(a));

            return MultWithElement(a, coeff, GF2);
        }
예제 #49
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);
        }
예제 #50
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;
        }
 /// <summary>
 /// Compute the product of two polynomials modulo a third polynomial over the finite field <c>GF(2^m)</c>
 /// </summary>
 /// 
 /// <param name="A">The first polynomial</param>
 /// <param name="B">The second polynomial</param>
 /// <param name="G">The reduction polynomial</param>
 /// <param name="GF2">The GF2 field</param>
 /// 
 /// <returns>Returns <c>a * b mod g</c></returns>
 private static int[] ModMultiply(int[] A, int[] B, int[] G, GF2mField GF2)
 {
     return Mod(Multiply(A, B, GF2), G, GF2);
 }
        /// <summary>
        /// Reduce a polynomial modulo another polynomial
        /// </summary>
        /// 
        /// <param name="A">The polynomial</param>
        /// <param name="F">The reduction polynomial</param>
        /// <param name="GF2">The GF2 field</param>
        /// 
        /// <returns>Returns <c>a mod f</c></returns>
        private static int[] Mod(int[] A, int[] F, GF2mField GF2)
        {
            int df = ComputeDegree(F);
            if (df == -1)
                throw new ArithmeticException("Division by zero");

            int[] result = new int[A.Length];
            int hc = HeadCoefficient(F);
            hc = GF2.Inverse(hc);
            Array.Copy(A, 0, result, 0, result.Length);
            while (df <= ComputeDegree(result))
            {
                int[] q;
                int coeff = GF2.Multiply(HeadCoefficient(result), hc);
                q = MultWithMonomial(F, ComputeDegree(result) - df);
                q = MultWithElement(q, coeff, GF2);
                result = Add(q, result, GF2);
            }

            return result;
        }
예제 #53
0
 /// <summary>
 /// Create a finite field GF(2^m) using another GF2mField class
 /// </summary>
 ///
 /// <param name="Field">The GF2mField class to copy</param>
 public GF2mField(GF2mField Field)
 {
     m_degree     = Field.m_degree;
     m_polynomial = Field.m_polynomial;
 }
 /// <summary>
 /// Construct the polynomial over the given finite field GF(2^m) from the given coefficient vector
 /// </summary>
 /// 
 /// <param name="Field">The finite field GF2m</param>
 /// <param name="Coeffs">The coefficient vector</param>
 public PolynomialGF2mSmallM(GF2mField Field, int[] Coeffs)
 {
     _field = Field;
     _coefficients = NormalForm(Coeffs);
     ComputeDegree();
 }
예제 #55
0
 /// <summary>
 /// Get a randome element over degree Gf2
 /// </summary>
 ///
 /// <param name="SecRnd">The source of randomness</param>
 /// <param name="GFM">The Gf2 field</param>
 ///
 /// <returns>A random element</returns>
 private static int GetRandomElement(IRandom SecRnd, GF2mField GFM)
 {
     return(RandomDegree.NextInt(SecRnd, 1 << GFM.Degree));
 }
        /// <summary>
        /// Compute the product of two polynomials over the field <c>GF(2^m)</c> using a Karatzuba like multiplication
        /// </summary>
        /// 
        /// <param name="A">The first polynomial</param>
        /// <param name="B">The second polynomial</param>
        /// <param name="GF2">The GF2 field</param>
        /// 
        /// <returns>Returns <c>a * b</c></returns>
        private static int[] Multiply(int[] A, int[] B, GF2mField GF2)
        {
            int[] mult1, mult2;
            if (ComputeDegree(A) < ComputeDegree(B))
            {
                mult1 = B;
                mult2 = A;
            }
            else
            {
                mult1 = A;
                mult2 = B;
            }

            mult1 = NormalForm(mult1);
            mult2 = NormalForm(mult2);

            if (mult2.Length == 1)
                return MultWithElement(mult1, mult2[0], GF2);

            int d1 = mult1.Length;
            int d2 = mult2.Length;
            int[] result = new int[d1 + d2 - 1];

            if (d2 != d1)
            {
                int[] res1 = new int[d2];
                int[] res2 = new int[d1 - d2];
                Array.Copy(mult1, 0, res1, 0, res1.Length);
                Array.Copy(mult1, d2, res2, 0, res2.Length);
                res1 = Multiply(res1, mult2, GF2);
                res2 = Multiply(res2, mult2, GF2);
                res2 = MultWithMonomial(res2, d2);
                result = Add(res1, res2, GF2);
            }
            else
            {
                d2 = IntUtils.URShift((d1 + 1), 1);
                int d = d1 - d2;
                int[] firstPartMult1 = new int[d2];
                int[] firstPartMult2 = new int[d2];
                int[] secondPartMult1 = new int[d];
                int[] secondPartMult2 = new int[d];
                Array.Copy(mult1, 0, firstPartMult1, 0, firstPartMult1.Length);
                Array.Copy(mult1, d2, secondPartMult1, 0, secondPartMult1.Length);
                Array.Copy(mult2, 0, firstPartMult2, 0, firstPartMult2.Length);
                Array.Copy(mult2, d2, secondPartMult2, 0, secondPartMult2.Length);
                int[] helpPoly1 = Add(firstPartMult1, secondPartMult1, GF2);
                int[] helpPoly2 = Add(firstPartMult2, secondPartMult2, GF2);
                int[] res1 = Multiply(firstPartMult1, firstPartMult2, GF2);
                int[] res2 = Multiply(helpPoly1, helpPoly2, GF2);
                int[] res3 = Multiply(secondPartMult1, secondPartMult2, GF2);
                res2 = Add(res2, res1, GF2);
                res2 = Add(res2, res3, GF2);
                res3 = MultWithMonomial(res3, d2);
                result = Add(res2, res3, GF2);
                result = MultWithMonomial(result, d2);
                result = Add(result, res1, GF2);
            }

            return result;
        }
예제 #57
0
 /// <summary>
 /// Create a finite field GF(2^m) using another GF2mField class
 /// </summary>
 ///
 /// <param name="Field">The GF2mField class to copy</param>
 public GF2mField(GF2mField Field)
 {
     _degree     = Field._degree;
     _polynomial = Field._polynomial;
 }
예제 #58
0
        /// <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);
        }
예제 #59
0
 /// <summary>
 /// Create an instance using values from a field and matrix
 /// </summary>
 /// 
 /// <param name="FieldG">A finite field GF(2^m)</param>
 /// <param name="MatrixN">The matrix as int array; only the reference is copied.</param>
 protected GF2mMatrix(GF2mField FieldG, int[][] MatrixN)
 {
     this.FieldG = FieldG;
     this.MatrixN = MatrixN;
     RowCount = MatrixN.Length;
     ColumnCount = MatrixN[0].Length;
 }