Пример #1
0
        /// <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 });
        }
Пример #2
0
        /// <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));
        }
Пример #3
0
        /// <summary>
        /// Decrypt a cipher text
        /// </summary>
        ///
        /// <param name="Input">The cipher text</param>
        ///
        /// <returns>The plain text</returns>
        public byte[] Decrypt(byte[] Input)
        {
            if (m_isEncryption)
            {
                throw new CryptoAsymmetricException("FujisakiCipher:Decrypt", "The cipher is not initialized for decryption!", new ArgumentException());
            }

            int c1Len = (m_N + 7) >> 3;
            int c2Len = Input.Length - c1Len;

            // split ciphertext (c1||c2)
            byte[][] c1c2 = ByteUtils.Split(Input, c1Len);
            byte[]   c1   = c1c2[0];
            byte[]   c2   = c1c2[1];

            // decrypt c1 ...
            GF2Vector hrmVec = GF2Vector.OS2VP(m_N, c1);

            GF2Vector[] decC1  = CCA2Primitives.Decrypt((MPKCPrivateKey)m_asmKey, hrmVec);
            byte[]      rBytes = decC1[0].GetEncoded();
            // ... and obtain error vector z
            GF2Vector z = decC1[1];

            byte[] mBytes;
            // get PRNG object..
            using (KDF2 sr0 = new KDF2(GetDigest(m_cprParams.Digest)))
            {
                // seed PRNG with r'
                sr0.Initialize(rBytes);
                // generate random sequence
                mBytes = new byte[c2Len];
                sr0.Generate(mBytes);
            }

            // XOR with c2 to obtain m
            for (int i = 0; i < c2Len; i++)
            {
                mBytes[i] ^= c2[i];
            }

            // compute H(r||m)
            byte[] rmBytes = ByteUtils.Concatenate(rBytes, mBytes);
            byte[] hrm     = new byte[m_dgtEngine.DigestSize];
            m_dgtEngine.BlockUpdate(rmBytes, 0, rmBytes.Length);
            m_dgtEngine.DoFinal(hrm, 0);
            // compute Conv(H(r||m))
            hrmVec = CCA2Conversions.Encode(m_N, m_T, hrm);

            // check that Conv(H(m||r)) = z
            if (!hrmVec.Equals(z))
            {
                throw new CryptoAsymmetricException("FujisakiCipher:Decrypt", "Bad Padding: invalid ciphertext!", new InvalidDataException());
            }

            // return plaintext m
            return(mBytes);
        }
Пример #4
0
        public byte[] Decrypt(byte[] Input)
        {
            int c1Len = (_N + 7) >> 3;
            int c2Len = Input.Length - c1Len;

            // split cipher text (c1||c2)
            byte[][] c1c2 = ByteUtils.Split(Input, c1Len);
            byte[]   c1   = c1c2[0];
            byte[]   c2   = c1c2[1];

            // decrypt c1 ...
            GF2Vector c1Vec = GF2Vector.OS2VP(_N, c1);

            GF2Vector[] c1Dec       = CCA2Primitives.Decrypt((MPKCPrivateKey)_keyPair.PrivateKey, c1Vec);
            byte[]      rPrimeBytes = c1Dec[0].GetEncoded();
            // ... and obtain error vector z
            GF2Vector z = c1Dec[1];

            byte[] mrBytes;
            // get PRNG object
            using (KDF2Drbg sr0 = new KDF2Drbg(GetDigest(_cipherParams.Digest)))
            {
                // seed PRNG with r'
                sr0.Initialize(rPrimeBytes);
                // generate random sequence
                mrBytes = new byte[c2Len];
                sr0.Generate(mrBytes);
            }

            // XOR with c2 to obtain (m||r)
            for (int i = 0; i < c2Len; i++)
            {
                mrBytes[i] ^= c2[i];
            }

            // compute H(m||r)
            _dgtEngine.BlockUpdate(mrBytes, 0, mrBytes.Length);
            byte[] hmr = new byte[_dgtEngine.DigestSize];
            _dgtEngine.DoFinal(hmr, 0);

            // compute Conv(H(m||r))
            c1Vec = CCA2Conversions.Encode(_N, _T, hmr);

            // check that Conv(H(m||r)) = z
            if (!c1Vec.Equals(z))
            {
                throw new Exception("Bad Padding: Invalid ciphertext!");// Note: will throw (sometimes), but only on Pointcheval w/ small m/t?
            }
            // split (m||r) to obtain m
            int kDiv8 = _K >> 3;

            byte[][] mr = ByteUtils.Split(mrBytes, c2Len - kDiv8);

            // return plain text m
            return(mr[0]);
        }
Пример #5
0
        public byte[] Encrypt(byte[] Input)
        {
            if (!m_isEncryption)
            {
                throw new CryptoAsymmetricException("PointchevalCipher:Encrypt", "The cipher is not initialized for encryption!", new ArgumentException());
            }

            int kDiv8 = m_K >> 3;

            // generate random r of length k div 8 bytes
            byte[] r = new byte[kDiv8];
            m_rndEngine.GetBytes(r);
            // generate random vector r' of length k bits
            GF2Vector rPrime = new GF2Vector(m_K, m_rndEngine);

            // convert r' to byte array
            byte[] rPrimeBytes = rPrime.GetEncoded();
            // compute (input||r)
            byte[] mr = ByteUtils.Concatenate(Input, r);
            // compute H(input||r)
            m_dgtEngine.BlockUpdate(mr, 0, mr.Length);
            byte[] hmr = new byte[m_dgtEngine.DigestSize];
            m_dgtEngine.DoFinal(hmr, 0);

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

            // compute c1 = E(rPrime, z)
            byte[] c1 = CCA2Primitives.Encrypt((MPKCPublicKey)m_asmKey, rPrime, z).GetEncoded();
            byte[] c2;
            // get PRNG object
            using (KDF2 sr0 = new KDF2(GetDigest(m_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));
        }
Пример #6
0
        /// <summary>
        /// Decrypt a cipher text
        /// </summary>
        ///
        /// <param name="Input">The cipher text</param>
        ///
        /// <returns>The plain text</returns>
        public byte[] Decrypt(byte[] Input)
        {
            int c1Len = (_N + 7) >> 3;
            int c2Len = Input.Length - c1Len;

            // split ciphertext (c1||c2)
            byte[][] c1c2 = ByteUtils.Split(Input, c1Len);
            byte[]   c1   = c1c2[0];
            byte[]   c2   = c1c2[1];

            // decrypt c1 ...
            GF2Vector hrmVec = GF2Vector.OS2VP(_N, c1);

            GF2Vector[] decC1  = CCA2Primitives.Decrypt((MPKCPrivateKey)_keyPair.PrivateKey, hrmVec);
            byte[]      rBytes = decC1[0].GetEncoded();
            // ... and obtain error vector z
            GF2Vector z = decC1[1];

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

            // XOR with c2 to obtain m
            for (int i = 0; i < c2Len; i++)
            {
                mBytes[i] ^= c2[i];
            }

            // compute H(r||m)
            byte[] rmBytes = ByteUtils.Concatenate(rBytes, mBytes);
            byte[] hrm     = new byte[_dgtEngine.DigestSize];
            _dgtEngine.BlockUpdate(rmBytes, 0, rmBytes.Length);
            _dgtEngine.DoFinal(hrm, 0);
            // compute Conv(H(r||m))
            hrmVec = CCA2Conversions.Encode(_N, _T, hrm);

            // check that Conv(H(m||r)) = z
            if (!hrmVec.Equals(z))
            {
                throw new Exception("Bad Padding: invalid ciphertext!");
            }

            // return plaintext m
            return(mBytes);
        }
Пример #7
0
        public byte[] Encrypt(byte[] Input)
        {
            int kDiv8 = _K >> 3;

            // generate random r of length k div 8 bytes
            byte[] r = new byte[kDiv8];
            _secRnd.GetBytes(r);
            // generate random vector r' of length k bits
            GF2Vector rPrime = new GF2Vector(_K, _secRnd);

            // 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)_keyPair.PublicKey, rPrime, z).GetEncoded();
            byte[] c2;
            // get PRNG object
            using (KDF2Drbg sr0 = new KDF2Drbg(GetDigest(_cipherParams.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));
        }
Пример #8
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);
        }
Пример #9
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)
        {
            if (!m_isEncryption)
            {
                throw new CryptoAsymmetricException("FujisakiCipher:Encrypt", "The cipher is not initialized for encryption!", new ArgumentException());
            }

            // generate random vector r of length k bits
            GF2Vector r = new GF2Vector(m_K, m_rndEngine);

            // convert r to byte array
            byte[] rBytes = r.GetEncoded();
            // compute (r||input)
            byte[] rm = ByteUtils.Concatenate(rBytes, Input);

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

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

            // get PRNG object
            using (KDF2 sr0 = new KDF2(GetDigest(m_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));
        }
Пример #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>
        /// 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));
        }
Пример #12
0
        public byte[] Decrypt(byte[] Input)
        {
            if (m_isEncryption)
            {
                throw new CryptoAsymmetricException("PointchevalCipher:Decrypt", "The cipher is not initialized for decryption!", new ArgumentException());
            }

            int c1Len = (m_N + 7) >> 3;
            int c2Len = Input.Length - c1Len;

            // split cipher text (c1||c2)
            byte[][] c1c2 = ByteUtils.Split(Input, c1Len);
            byte[]   c1   = c1c2[0];
            byte[]   c2   = c1c2[1];

            // decrypt c1 ...
            GF2Vector c1Vec = GF2Vector.OS2VP(m_N, c1);

            GF2Vector[] c1Dec       = CCA2Primitives.Decrypt((MPKCPrivateKey)m_asmKey, c1Vec);
            byte[]      rPrimeBytes = c1Dec[0].GetEncoded();
            // ... and obtain error vector z
            GF2Vector z = c1Dec[1];

            byte[] mrBytes;
            // get PRNG object
            using (KDF2 sr0 = new KDF2(GetDigest(m_cprParams.Digest)))
            {
                // seed PRNG with r'
                sr0.Initialize(rPrimeBytes);
                // generate random sequence
                mrBytes = new byte[c2Len];
                sr0.Generate(mrBytes);
            }

            // XOR with c2 to obtain (m||r)
            for (int i = 0; i < c2Len; i++)
            {
                mrBytes[i] ^= c2[i];
            }

            // compute H(m||r)
            m_dgtEngine.BlockUpdate(mrBytes, 0, mrBytes.Length);
            byte[] hmr = new byte[m_dgtEngine.DigestSize];
            m_dgtEngine.DoFinal(hmr, 0);

            // compute Conv(H(m||r))
            c1Vec = CCA2Conversions.Encode(m_N, m_T, hmr);

            // check that Conv(H(m||r)) = z
            if (!c1Vec.Equals(z))
            {
                throw new CryptoAsymmetricException("PointchevalCipher:Decrypt", "Bad Padding: Invalid ciphertext!", new ArgumentException());
            }

            // split (m||r) to obtain m
            int kDiv8 = m_K >> 3;

            byte[][] mr = ByteUtils.Split(mrBytes, c2Len - kDiv8);

            // return plain text m
            return(mr[0]);
        }
Пример #13
0
        /// <summary>
        /// Decrypt a cipher text
        /// </summary>
        ///
        /// <param name="Input">The cipher text</param>
        ///
        /// <returns>The plain text</returns>
        public byte[] Decrypt(byte[] Input)
        {
            if (_isEncryption)
            {
                throw new CryptoAsymmetricSignException("KobaraImaiCipher:Decrypt", "The cipher is not initialized for decryption!", new ArgumentException());
            }

            int nDiv8 = _N >> 3;

            if (Input.Length < nDiv8)
            {
                throw new CryptoAsymmetricSignException("KobaraImaiCipher:Decrypt", "Bad Padding: Ciphertext too short!", new ArgumentException());
            }

            int c2Len = _dgtEngine.DigestSize;
            int c4Len = _K >> 3;
            int c6Len = Input.Length - nDiv8;

            // split cipher text (c6||encC4), where c6 may be empty
            byte[] c6, encC4;
            if (c6Len > 0)
            {
                byte[][] c6EncC4 = ByteUtils.Split(Input, c6Len);
                c6    = c6EncC4[0];
                encC4 = c6EncC4[1];
            }
            else
            {
                c6    = new byte[0];
                encC4 = Input;
            }

            // convert encC4 into vector over GF(2)
            GF2Vector encC4Vec = GF2Vector.OS2VP(_N, encC4);

            // decrypt encC4Vec to obtain c4 and error vector z
            GF2Vector[] c4z = CCA2Primitives.Decrypt((MPKCPrivateKey)_asmKey, encC4Vec);
            byte[]      c4  = c4z[0].GetEncoded();
            GF2Vector   z   = c4z[1];

            // if length of c4 is greater than c4Len (because of padding), truncate the padding bytes
            if (c4.Length > c4Len)
            {
                c4 = ByteUtils.SubArray(c4, 0, c4Len);
            }

            // compute c5 = Conv^-1(z)
            byte[] c5 = CCA2Conversions.Decode(_N, _T, z);
            // compute (c6||c5||c4)
            byte[] c6c5c4 = ByteUtils.Concatenate(c6, c5);
            c6c5c4 = ByteUtils.Concatenate(c6c5c4, c4);

            // split (c6||c5||c4) into (c2||c1), where c2Len = mdLen and c1Len = input.length-c2Len bytes.
            int c1Len = c6c5c4.Length - c2Len;

            byte[][] c2c1 = ByteUtils.Split(c6c5c4, c2Len);
            byte[]   c2   = c2c1[0];
            byte[]   c1   = c2c1[1];

            // compute H(c1) ...
            byte[] rPrime = new byte[_dgtEngine.DigestSize];
            _dgtEngine.BlockUpdate(c1, 0, c1.Length);
            _dgtEngine.DoFinal(rPrime, 0);

            // ... and XOR with c2 to obtain r'
            for (int i = c2Len - 1; i >= 0; i--)
            {
                rPrime[i] ^= c2[i];
            }

            byte[] mConstPrime;
            // get PRNG object
            using (KDF2Drbg sr0 = new KDF2Drbg(GetDigest(_cprParams.Digest)))
            {
                // seed PRNG with r'
                sr0.Initialize(rPrime);
                // generate random sequence R(r') ...
                mConstPrime = new byte[c1Len];
                sr0.Generate(mConstPrime);
            }

            // ... and XOR with c1 to obtain (m||const')
            for (int i = c1Len - 1; i >= 0; i--)
            {
                mConstPrime[i] ^= c1[i];
            }

            if (mConstPrime.Length < c1Len)
            {
                throw new CryptoAsymmetricSignException("KobaraImaiCipher:Decrypt", "Bad Padding: invalid ciphertext!", new ArgumentException());
            }

            byte[][] temp       = ByteUtils.Split(mConstPrime, c1Len - MPKCINFO.Length);
            byte[]   mr         = temp[0];
            byte[]   constPrime = temp[1];

            if (!ByteUtils.Equals(constPrime, MPKCINFO))
            {
                throw new CryptoAsymmetricSignException("KobaraImaiCipher:Decrypt", "Bad Padding: invalid ciphertext!", new ArgumentException());
            }

            return(mr);
        }
Пример #14
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)
        {
            if (!_isEncryption)
            {
                throw new CryptoAsymmetricSignException("KobaraImaiCipher:Encrypt", "The cipher is not initialized for encryption!", new ArgumentException());
            }

            int c2Len = _dgtEngine.DigestSize;
            int c4Len = _K >> 3;
            int c5Len = (BigMath.Binomial(_N, _T).BitLength - 1) >> 3;
            int mLen  = c4Len + c5Len - c2Len - MPKCINFO.Length;

            if (Input.Length > mLen)
            {
                mLen = Input.Length;
            }

            int c1Len = mLen + MPKCINFO.Length;
            int c6Len = c1Len + c2Len - c4Len - c5Len;

            // compute (m||const)
            byte[] mConst = new byte[c1Len];
            Array.Copy(Input, 0, mConst, 0, Input.Length);
            Array.Copy(MPKCINFO, 0, mConst, mLen, MPKCINFO.Length);

            // generate random r of length c2Len bytes
            byte[] r = new byte[c2Len];
            _rndEngine.GetBytes(r);

            byte[] c1;
            // get PRNG object ToDo:
            //DigestRandomGenerator sr0 = new DigestRandomGenerator(new SHA1Digest()); //why bc, why?
            using (KDF2Drbg sr0 = new KDF2Drbg(GetDigest(_cprParams.Digest)))
            {
                // seed PRNG with r'
                sr0.Initialize(r);
                // generate random sequence ...
                c1 = new byte[c1Len];
                sr0.Generate(c1);
            }

            // ... and XOR with (m||const) to obtain c1
            for (int i = c1Len - 1; i >= 0; i--)
            {
                c1[i] ^= mConst[i];
            }

            // compute H(c1) ...
            byte[] c2 = new byte[_dgtEngine.DigestSize];
            _dgtEngine.BlockUpdate(c1, 0, c1.Length);
            _dgtEngine.DoFinal(c2, 0);

            // ... and XOR with r
            for (int i = c2Len - 1; i >= 0; i--)
            {
                c2[i] ^= r[i];
            }

            // compute (c2||c1)
            byte[] c2c1 = ByteUtils.Concatenate(c2, c1);

            // split (c2||c1) into (c6||c5||c4), where c4Len is k/8 bytes, c5Len is
            // floor[log(n|t)]/8 bytes, and c6Len is c1Len+c2Len-c4Len-c5Len (may be 0).
            byte[] c6 = new byte[0];
            if (c6Len > 0)
            {
                c6 = new byte[c6Len];
                Array.Copy(c2c1, 0, c6, 0, c6Len);
            }

            byte[] c5 = new byte[c5Len];
            Array.Copy(c2c1, c6Len, c5, 0, c5Len);
            byte[] c4 = new byte[c4Len];
            Array.Copy(c2c1, c6Len + c5Len, c4, 0, c4Len);
            // convert c4 to vector over GF(2)
            GF2Vector c4Vec = GF2Vector.OS2VP(_K, c4);
            // convert c5 to error vector z
            GF2Vector z = CCA2Conversions.Encode(_N, _T, c5);

            // compute encC4 = E(c4, z)
            byte[] encC4 = CCA2Primitives.Encrypt((MPKCPublicKey)_asmKey, c4Vec, z).GetEncoded();

            // if c6Len > 0 return (c6||encC4)
            if (c6Len > 0)
            {
                return(ByteUtils.Concatenate(c6, encC4));
            }

            // else, return encC4
            return(encC4);
        }