Пример #1
0
        /// <summary>
        /// Decode a binary vector of length n and weight t into a number between 0 and (n|t) (binomial coefficient).
        /// <para>The result is given as a byte array of length floor[(s+7)/8], where s = floor[log(n|t)].</para>
        /// </summary>
        /// 
        /// <param name="N">The "n" integer</param>
        /// <param name="T">The "t" integer</param>
        /// <param name="GVector">The binary vector</param>
        /// 
        /// <returns>The decoded vector as a byte array</returns>
        public static byte[] Decode(int N, int T, GF2Vector GVector)
        {
            if ((GVector.Length != N) || (GVector.HammingWeight() != T))
                throw new ArgumentException("vector has wrong length or hamming weight");

            int[] vecArray = GVector.VectorArray;
            BigInteger bc = BigMath.Binomial(N, T);
            BigInteger d = ZERO;
            int nn = N;
            int tt = T;

            for (int i = 0; i < N; i++)
            {
                bc = bc.Multiply(BigInteger.ValueOf(nn - tt)).Divide(BigInteger.ValueOf(nn));
                nn--;

                int q = i >> 5;
                int e = vecArray[q] & (1 << (i & 0x1f));
                if (e != 0)
                {
                    d = d.Add(bc);
                    tt--;

                    if (nn == tt)
                        bc = ONE;
                    else
                        bc = bc.Multiply(BigInteger.ValueOf(tt + 1)).Divide(BigInteger.ValueOf(nn - tt));

                }
            }

            return BigIntUtils.ToMinimalByteArray(d);
        }
Пример #2
0
        /// <summary>
        /// Return a new vector consisting of the first <c>K</c> elements of this vector
        /// </summary>
        ///
        /// <param name="K">The number of elements to extract</param>
        ///
        /// <returns>Returns a new GF2Vector consisting of the first <c>K</c> elements of this vector</returns>
        public GF2Vector ExtractLeftVector(int K)
        {
            if (K > Length)
            {
                throw new ArithmeticException("invalid length");
            }

            if (K == Length)
            {
                return(new GF2Vector(this));
            }

            GF2Vector result = new GF2Vector(K);

            int q = K >> 5;
            int r = K & 0x1f;

            Array.Copy(_elements, 0, result._elements, 0, q);
            if (r != 0)
            {
                result._elements[q] = _elements[q] & ((1 << r) - 1);
            }

            return(result);
        }
Пример #3
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);
        }
Пример #4
0
        /// <summary>
        /// Decides whether the given object <c>other</c> is the same as this field
        /// </summary>
        ///
        /// <param name="Obj">The object for comparison</param>
        ///
        /// <returns>Returns <c>(this == other)</c></returns>
        public override bool Equals(Object Obj)
        {
            if (!(Obj is GF2Vector))
            {
                return(false);
            }
            GF2Vector otherVec = (GF2Vector)Obj;

            if (Length != otherVec.Length)
            {
                return(false);
            }
            if (!Compare.AreEqual(_elements, otherVec._elements))
            {
                return(false);
            }

            return(true);
        }
Пример #5
0
        /// <summary>
        /// Return a new vector consisting of the last <c>k</c> elements of this vector
        /// </summary>
        ///
        /// <param name="K">The number of elements to extract</param>
        ///
        /// <returns>Returns a new GF2Vector consisting of the last <c>K</c> elements of this vector</returns>
        public GF2Vector ExtractRightVector(int K)
        {
            if (K > base.Length)
            {
                throw new ArithmeticException("invalid length");
            }

            if (K == base.Length)
            {
                return(new GF2Vector(this));
            }

            GF2Vector result = new GF2Vector(K);

            int q      = (base.Length - K) >> 5;
            int r      = (base.Length - K) & 0x1f;
            int length = (K + 31) >> 5;
            int ind    = q;

            // if words have to be shifted
            if (r != 0)
            {
                // process all but last word
                for (int i = 0; i < length - 1; i++)
                {
                    result._elements[i] = (IntUtils.URShift(_elements[ind++], r)) | (_elements[ind] << (32 - r));
                }
                // process last word
                result._elements[length - 1] = IntUtils.URShift(_elements[ind++], r);
                if (ind < _elements.Length)
                {
                    result._elements[length - 1] |= _elements[ind] << (32 - r);
                }
            }
            else
            {
                // no shift necessary
                Array.Copy(_elements, q, result._elements, 0, length);
            }

            return(result);
        }
Пример #6
0
        /// <summary>
        /// Multiply this vector with a permutation
        /// </summary>
        ///
        /// <param name="P">The permutation</param>
        ///
        /// <returns>Returns <c>this*p = p*this</c></returns>
        public override Vector Multiply(Permutation P)
        {
            int[] pVec = P.GetVector();
            if (Length != pVec.Length)
            {
                throw new ArithmeticException("GF2Vector: Length mismatch!");
            }

            GF2Vector result = new GF2Vector(Length);

            for (int i = 0; i < pVec.Length; i++)
            {
                int e = _elements[pVec[i] >> 5] & (1 << (pVec[i] & 0x1f));
                if (e != 0)
                {
                    result._elements[i >> 5] |= 1 << (i & 0x1f);
                }
            }

            return(result);
        }
Пример #7
0
        /// <summary>
        /// Return a new vector consisting of the elements of this vector with the indices given by the set <c>SetJ</c>
        /// </summary>
        ///
        /// <param name="SetJ">The set of indices of elements to extract</param>
        ///
        /// <returns>Return the new GF2Vector <c>[SetJ[0], SetJ[1], ..., SetJ[#SetJ-1]]</c></returns>
        public GF2Vector ExtractVector(int[] SetJ)
        {
            int k = SetJ.Length;

            if (SetJ[k - 1] > Length)
            {
                throw new ArithmeticException("invalid index set");
            }

            GF2Vector result = new GF2Vector(k);

            for (int i = 0; i < k; i++)
            {
                int e = _elements[SetJ[i] >> 5] & (1 << (SetJ[i] & 0x1f));
                if (e != 0)
                {
                    result._elements[i >> 5] |= 1 << (i & 0x1f);
                }
            }

            return(result);
        }
Пример #8
0
        /// <summary>
        /// Adds another GF2Vector to this vector
        /// </summary>
        ///
        /// <param name="V">The GF2Vector to add</param>
        ///
        /// <returns>Returns <c>this + V</c></returns>
        public override Vector Add(Vector V)
        {
            if (!(V is GF2Vector))
            {
                throw new ArithmeticException("GF2Vector: Vector is not defined over GF(2)!");
            }

            GF2Vector otherVec = (GF2Vector)V;

            if (Length != otherVec.Length)
            {
                throw new ArithmeticException("GF2Vector: Length mismatch!");
            }

            int[] vec = IntUtils.DeepCopy(((GF2Vector)V)._elements);

            for (int i = vec.Length - 1; i >= 0; i--)
            {
                vec[i] ^= _elements[i];
            }

            return(new GF2Vector(Length, vec));
        }
Пример #9
0
        /// <summary>
        /// Return a new vector consisting of the first <c>K</c> elements of this vector
        /// </summary>
        /// 
        /// <param name="K">The number of elements to extract</param>
        /// 
        /// <returns>Returns a new GF2Vector consisting of the first <c>K</c> elements of this vector</returns>
        public GF2Vector ExtractLeftVector(int K)
        {
            if (K > Length)
                throw new ArithmeticException("invalid length");

            if (K == Length)
                return new GF2Vector(this);

            GF2Vector result = new GF2Vector(K);

            int q = K >> 5;
            int r = K & 0x1f;

            Array.Copy(_elements, 0, result._elements, 0, q);
            if (r != 0)
                result._elements[q] = _elements[q] & ((1 << r) - 1);

            return result;
        }
Пример #10
0
        /// <summary>
        /// Encrypt a plain text message
        /// </summary>
        /// 
        /// <param name="Input">The plain text</param>
        /// 
        /// <returns>The cipher text</returns>
        public byte[] Encrypt(byte[] Input)
        {
            // generate random vector r of length k bits
            GF2Vector r = new GF2Vector(_K, _secRnd);
            // convert r to byte array
            byte[] rBytes = r.GetEncoded();
            // compute (r||input)
            byte[] rm = ByteUtils.Concatenate(rBytes, Input);

            // compute H(r||input)
            _dgtEngine.BlockUpdate(rm, 0, rm.Length);
            byte[] hrm = new byte[_dgtEngine.DigestSize];
            _dgtEngine.DoFinal(hrm, 0);
            // convert H(r||input) to error vector z
            GF2Vector z = CCA2Conversions.Encode(_N, _T, hrm);

            // compute c1 = E(r, z)
            byte[] c1 = CCA2Primitives.Encrypt((MPKCPublicKey)_keyPair.PublicKey, r, z).GetEncoded();
            byte[] c2;

            // get PRNG object
            using (KDF2Drbg sr0 = new KDF2Drbg(GetDigest(_cipherParams.Digest)))
            {
                // seed PRNG with r'
                sr0.Initialize(rBytes);
                // generate random c2
                c2 = new byte[Input.Length];
                sr0.Generate(c2);
            }

            // XOR with input
            for (int i = 0; i < Input.Length; i++)
                c2[i] ^= Input[i];

            // return (c1||c2)
            return ByteUtils.Concatenate(c1, c2);
        }
Пример #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>
        /// Multiply this vector with a permutation
        /// </summary>
        /// 
        /// <param name="P">The permutation</param>
        /// 
        /// <returns>Returns <c>this*p = p*this</c></returns>
        public override Vector Multiply(Permutation P)
        {
            int[] pVec = P.GetVector();
            if (Length != pVec.Length)
                throw new ArithmeticException("GF2Vector: Length mismatch!");

            GF2Vector result = new GF2Vector(Length);

            for (int i = 0; i < pVec.Length; i++)
            {
                int e = _elements[pVec[i] >> 5] & (1 << (pVec[i] & 0x1f));
                if (e != 0)
                    result._elements[i >> 5] |= 1 << (i & 0x1f);
            }

            return result;
        }
Пример #13
0
        /// <summary>
        /// Return a new vector consisting of the elements of this vector with the indices given by the set <c>SetJ</c>
        /// </summary>
        /// 
        /// <param name="SetJ">The set of indices of elements to extract</param>
        /// 
        /// <returns>Return the new GF2Vector <c>[SetJ[0], SetJ[1], ..., SetJ[#SetJ-1]]</c></returns>
        public GF2Vector ExtractVector(int[] SetJ)
        {
            int k = SetJ.Length;
            if (SetJ[k - 1] > Length)
                throw new ArithmeticException("invalid index set");

            GF2Vector result = new GF2Vector(k);

            for (int i = 0; i < k; i++)
            {
                int e = _elements[SetJ[i] >> 5] & (1 << (SetJ[i] & 0x1f));
                if (e != 0)
                    result._elements[i >> 5] |= 1 << (i & 0x1f);
            }

            return result;
        }
Пример #14
0
        /// <summary>
        /// Return a new vector consisting of the last <c>k</c> elements of this vector
        /// </summary>
        /// 
        /// <param name="K">The number of elements to extract</param>
        /// 
        /// <returns>Returns a new GF2Vector consisting of the last <c>K</c> elements of this vector</returns>
        public GF2Vector ExtractRightVector(int K)
        {
            if (K > base.Length)
                throw new ArithmeticException("invalid length");

            if (K == base.Length)
                return new GF2Vector(this);

            GF2Vector result = new GF2Vector(K);

            int q = (base.Length - K) >> 5;
            int r = (base.Length - K) & 0x1f;
            int length = (K + 31) >> 5;
            int ind = q;

            // if words have to be shifted
            if (r != 0)
            {
                // process all but last word
                for (int i = 0; i < length - 1; i++)
                    result._elements[i] = (IntUtils.URShift(_elements[ind++], r)) | (_elements[ind] << (32 - r));
                // process last word
                result._elements[length - 1] = IntUtils.URShift(_elements[ind++], r);
                if (ind < _elements.Length)
                    result._elements[length - 1] |= _elements[ind] << (32 - r);
            }
            else
            {
                // no shift necessary
                Array.Copy(_elements, q, result._elements, 0, length);
            }

            return result;
        }
Пример #15
0
 /// <summary>
 /// Copy constructor
 /// </summary>
 ///
 /// <param name="G">The GF2Vector to copy</param>
 public GF2Vector(GF2Vector G)
 {
     this.Length    = G.Length;
     this._elements = IntUtils.DeepCopy(G._elements);
 }
Пример #16
0
        /// <summary>
        /// Encode a number between 0 and (n|t) (binomial coefficient) into a binary vector of length n with weight t. 
        /// <para>The number is given as a byte array. Only the first s bits are used, where s = floor[log(n|t)].</para>
        /// </summary>
        /// 
        /// <param name="N">The "n" integer</param>
        /// <param name="T">The "t" integer</param>
        /// <param name="M">The message as a byte array</param>
        /// 
        /// <returns>The encoded message as GF2Vector</returns>
        public static GF2Vector Encode(int N, int T, byte[] M)
        {
            if (N < T)
                throw new ArgumentException("n < t");

            // compute the binomial c = (n|t)
            BigInteger c = BigMath.Binomial(N, T);
            // get the number encoded in m
            BigInteger i = new BigInteger(1, M);
            // compare
            if (i.CompareTo(c) >= 0)
                throw new ArgumentException("Encoded number too large.");

            GF2Vector result = new GF2Vector(N);
            int nn = N;
            int tt = T;

            for (int j = 0; j < N; j++)
            {
                c = c.Multiply(BigInteger.ValueOf(nn - tt)).Divide(BigInteger.ValueOf(nn));
                nn--;

                if (c.CompareTo(i) <= 0)
                {
                    result.SetBit(j);
                    i = i.Subtract(c);
                    tt--;

                    if (nn == tt)
                        c = ONE;
                    else
                        c = (c.Multiply(BigInteger.ValueOf(tt + 1))).Divide(BigInteger.ValueOf(nn - tt));
                }
            }

            return result;
        }
Пример #17
0
 /// <summary>
 /// Copy constructor
 /// </summary>
 /// 
 /// <param name="G">The GF2Vector to copy</param>
 public GF2Vector(GF2Vector G)
 {
     this.Length = G.Length;
     this._elements = IntUtils.DeepCopy(G._elements);
 }