예제 #1
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]);
        }
예제 #2
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);
        }
예제 #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)
        {
            int nDiv8 = _N >> 3;

            if (Input.Length < nDiv8)
            {
                throw new Exception("Bad Padding: Ciphertext too short.");
            }

            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)_keyPair.PrivateKey, 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(_cipherParams.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 Exception("Bad Padding: invalid ciphertext");
            }

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

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

            return(mr);
        }