Example #1
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(m_elements, 0, result.m_elements, 0, q);
            if (r != 0)
            {
                result.m_elements[q] = m_elements[q] & ((1 << r) - 1);
            }

            return(result);
        }
        /// <summary>
        /// The McEliece encryption primitive
        /// </summary>
        /// 
        /// <param name="PublicKey">The public key</param>
        /// <param name="M">The message vector</param>
        /// <param name="Z">The error vector</param>
        /// 
        /// <returns><c>m*G + z</c></returns>
        public static GF2Vector Encrypt(MPKCPublicKey PublicKey, GF2Vector M, GF2Vector Z)
        {
            GF2Matrix matrixG = PublicKey.G;
            Vector mG = matrixG.LeftMultiplyLeftCompactForm(M);

            return (GF2Vector)mG.Add(Z);
        }
        /// <summary>
        /// The McEliece decryption primitive
        /// </summary>
        /// 
        /// <param name="PrivateKey">The private key</param>
        /// <param name="C">The ciphertext vector <c>c = m*G + z</c></param>
        /// 
        /// <returns>The message vector <c>m</c> and the error vector <c>z</c></returns>
        public static GF2Vector[] Decrypt(MPKCPrivateKey PrivateKey, GF2Vector C)
        {
            // obtain values from private key
            int k = PrivateKey.K;
            Permutation p = PrivateKey.P1;
            GF2mField field = PrivateKey.GF;
            PolynomialGF2mSmallM gp = PrivateKey.GP;
            GF2Matrix h = PrivateKey.H;
            PolynomialGF2mSmallM[] q = PrivateKey.QInv;

            // compute inverse permutation P^-1
            Permutation pInv = p.ComputeInverse();
            // multiply c with permutation P^-1
            GF2Vector cPInv = (GF2Vector)C.Multiply(pInv);
            // compute syndrome of cP^-1
            GF2Vector syndVec = (GF2Vector)h.RightMultiply(cPInv);
            // decode syndrome
            GF2Vector errors = GoppaCode.SyndromeDecode(syndVec, field, gp, q);
            GF2Vector mG = (GF2Vector)cPInv.Add(errors);
            // multiply codeword and error vector with P
            mG = (GF2Vector)mG.Multiply(p);
            errors = (GF2Vector)errors.Multiply(p);
            // extract plaintext vector (last k columns of mG)
            GF2Vector m = mG.ExtractRightVector(k);

            // return vectors
            return new GF2Vector[] { m, errors };
        }
Example #4
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);
        }
Example #5
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.IsEqual(m_elements, otherVec.m_elements))
            {
                return(false);
            }

            return(true);
        }
Example #6
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.m_elements[i] = (IntUtils.URShift(m_elements[ind++], r)) | (m_elements[ind] << (32 - r));
                }
                // process last word
                result.m_elements[length - 1] = IntUtils.URShift(m_elements[ind++], r);
                if (ind < m_elements.Length)
                {
                    result.m_elements[length - 1] |= m_elements[ind] << (32 - r);
                }
            }
            else
            {
                // no shift necessary
                Array.Copy(m_elements, q, result.m_elements, 0, length);
            }

            return(result);
        }
Example #7
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 = m_elements[pVec[i] >> 5] & (1 << (pVec[i] & 0x1f));
                if (e != 0)
                {
                    result.m_elements[i >> 5] |= 1 << (i & 0x1f);
                }
            }

            return(result);
        }
Example #8
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 = m_elements[SetJ[i] >> 5] & (1 << (SetJ[i] & 0x1f));
                if (e != 0)
                {
                    result.m_elements[i >> 5] |= 1 << (i & 0x1f);
                }
            }

            return(result);
        }
Example #9
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).m_elements);

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

            return(new GF2Vector(Length, vec));
        }
        /// <summary>
        /// Encrypt a plain text message
        /// </summary>
        /// 
        /// <param name="Input">The plain text</param>
        /// 
        /// <returns>The cipher text</returns>
        public byte[] Encrypt(byte[] Input)
        {
            if (!_isEncryption)
                throw new CryptoAsymmetricSignException("FujisakiCipher:Encrypt", "The cipher is not initialized for encryption!", new ArgumentException());

            // generate random vector r of length k bits
            GF2Vector r = new GF2Vector(_K, _rndEngine);
            // 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)_asmKey, r, z).GetEncoded();
            byte[] c2;

            // get PRNG object
            using (KDF2Drbg sr0 = new KDF2Drbg(GetDigest(_cprParams.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);
        }
        public byte[] Encrypt(byte[] Input)
        {
            if (!_isEncryption)
                throw new CryptoAsymmetricSignException("PointchevalCipher:Encrypt", "The cipher is not initialized for encryption!", new ArgumentException());

            int kDiv8 = _K >> 3;
            // generate random r of length k div 8 bytes
            byte[] r = new byte[kDiv8];
            _rndEngine.GetBytes(r);
            // generate random vector r' of length k bits
            GF2Vector rPrime = new GF2Vector(_K, _rndEngine);
            // convert r' to byte array
            byte[] rPrimeBytes = rPrime.GetEncoded();
            // compute (input||r)
            byte[] mr = ByteUtils.Concatenate(Input, r);
            // compute H(input||r)
            _dgtEngine.BlockUpdate(mr, 0, mr.Length);
            byte[] hmr = new byte[_dgtEngine.DigestSize];
            _dgtEngine.DoFinal(hmr, 0);

            // convert H(input||r) to error vector z
            GF2Vector z = CCA2Conversions.Encode(_N, _T, hmr);

            // compute c1 = E(rPrime, z)
            byte[] c1 = CCA2Primitives.Encrypt((MPKCPublicKey)_asmKey, rPrime, z).GetEncoded();
            byte[] c2;
            // get PRNG object
            using (KDF2Drbg sr0 = new KDF2Drbg(GetDigest(_cprParams.Digest)))
            {
                // seed PRNG with r'
                sr0.Initialize(rPrimeBytes);
                // generate random c2
                c2 = new byte[Input.Length + kDiv8];
                sr0.Generate(c2);
            }

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

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

            // return (c1||c2)
            return ByteUtils.Concatenate(c1, c2);
        }
Example #12
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;
        }
Example #13
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);
 }
Example #14
0
 /// <summary>
 /// Copy constructor
 /// </summary>
 ///
 /// <param name="G">The GF2Vector to copy</param>
 public GF2Vector(GF2Vector G)
 {
     this.Length     = G.Length;
     this.m_elements = IntUtils.DeepCopy(G.m_elements);
 }
Example #15
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;
        }
Example #16
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;
        }
Example #17
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;
        }
Example #18
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;
        }