예제 #1
0
        private RC4 getRC4(byte[] key, int keyLength)
        {
            if (_rc4 == null)
            {
                _rc4 = new RC4(key, keyLength);
                return(_rc4);
            }

            _rc4.SetKey(key);
            return(_rc4);
        }
예제 #2
0
        // algorithm 3.7, step 1-2
        private string calculateUserPasswordFromOwnerPassword(string ownerPassword)
        {
            // Step 1: Computer an encryption key from the supplied password string,
            // as described in steps 1 to 4 of algorithm 3.3.
            byte[] encryptionKey = calculateOwnerHash(ownerPassword, "", true);

            // Step 2: start decryption of O
            byte[] ownerHash = null;
            if (_revision == 2)
            {
                // Step 2 (R == 2):  decrypt the value of the encryption dictionary
                // O entry, using an RC4 encryption function with the encryption
                // key computed in step 1.
                RC4 rc4 = new RC4(encryptionKey, encryptionKey.Length);
                ownerHash = rc4.CryptBuffer(_ownerHash, 0, _ownerHash.Length);
            }
            else
            {
                // Step 2 (R == 3): Do the following 19 times: Take the output from the previous
                // invocation of the RC4 function and pass it as input to a new
                // invocation of the function; use an encryption key generated by taking
                // each byte of the encryption key in step 4 and performing an XOR
                // operation between that byte and the single-byte value of the
                // iteration counter
                byte[] indexedKey = new byte[encryptionKey.Length];
                ownerHash = (byte[])_ownerHash.Clone();

                for (int i = 19; i >= 0; i--)
                {
                    for (int j = 0; j < indexedKey.Length; j++)
                    {
                        indexedKey[j] = (byte)(encryptionKey[j] ^ (byte)i);
                    }

                    RC4 rc4 = new RC4(indexedKey, indexedKey.Length);
                    ownerHash = rc4.CryptBuffer(ownerHash, 0, ownerHash.Length);
                }
            }


            int    index             = findIndex(ownerHash);
            string localUserPassword = System.Text.Encoding.Default.GetString(ownerHash, 0, index);

            return(localUserPassword);
        }
예제 #3
0
        public void Encrypt(byte[] inputData, int offset, int length, Stream output, DataType dataType)
        {
            switch (getFilter(dataType))
            {
            case CryptFilter.Identity:
                output.Write(inputData, offset, length);
                return;

            case CryptFilter.V2:
                RC4 rc4 = getRC4(_curObjectKey, _curObjectKey.Length);
                rc4.Crypt(inputData, offset, length, output);
                return;

            case CryptFilter.AESV3:
            case CryptFilter.AESV2:
                AES aes = getAES(_curObjectKey);
                aes.Encrypt(inputData, offset, length, output);
                return;
            }
        }
예제 #4
0
        public void Decrypt(Stream input, int length, Stream output, DataType dataType)
        {
            switch (getFilter(dataType))
            {
            case CryptFilter.Identity:
                for (int i = 0; i < length; ++i)
                {
                    output.WriteByte((byte)input.ReadByte());
                }
                return;

            case CryptFilter.V2:
                RC4 rc4 = getRC4(_curObjectKey, _curObjectKey.Length);
                rc4.Crypt(input, length, output);
                return;

            case CryptFilter.AESV2:
            case CryptFilter.AESV3:
                AES aes = getAES(_curObjectKey);
                aes.Decrypt(input, length, output);
                return;
            }
        }
예제 #5
0
        // Computing the encryption dictionary’s U (user password)
        private byte[] calculateUserHash(String userPassword)
        {
            // Step 1: Create an encryption key based on the user password String,
            // as described in Algorithm 3.2
            byte[] encryptionKey = computeEncryptionKey(userPassword, _length);

            // Algorithm 3.4 steps, 2 - 3
            if (_revision == 2)
            {
                // Step 2: Encrypt the 32-byte padding string show in step 1, using
                // an RC4 encryption function with the encryption key from the
                // preceding step
                byte[] paddedUserPassword = (byte[])_paddingString.Clone();
                byte[] finalData          = null;
                RC4    rc4 = new RC4(encryptionKey, encryptionKey.Length);
                finalData = rc4.CryptBuffer(paddedUserPassword, 0, paddedUserPassword.Length);

                // Step 3: return the result of step 2 as the value of the U entry
                return(finalData);
            }
            // algorithm 3.5 steps, 2 - 6
            else
            {
                // Step 2: Initialize the MD5 hash function and pass the 32-byte
                // padding string shown in step 1 of Algorithm 3.2 as input to
                // this function
                byte[] tmp = new byte[32];
                byte[] paddedUserPassword = (byte[])_paddingString.Clone();
                MD5    md5 = MD5.Create();

                if (!_isDocIDEmpty)
                {
                    md5.TransformBlock(paddedUserPassword, 0, paddedUserPassword.Length, tmp, 0);
                }
                else
                {
                    md5.TransformFinalBlock(paddedUserPassword, 0, paddedUserPassword.Length);
                }

                // Step 3: Pass the first element of the files identify array to the
                // hash function and finish the hash.
                if (!_isDocIDEmpty)
                {
                    md5.TransformFinalBlock(_docID, 0, _docID.Length);
                }
                byte[] encryptData = (byte[])md5.Hash.Clone();

                // Step 4: Encrypt the 16 byte result of the hash, using an RC4
                // encryption function with the encryption key from step 1
                RC4 rc4 = new RC4(encryptionKey, encryptionKey.Length);
                encryptData = rc4.CryptBuffer(encryptData, 0, encryptData.Length);

                // Step 5: Do the following 19 times: Take the output from the previous
                // invocation of the RC4 function and pass it as input to a new
                // invocation of the function; use an encryption key generated by taking
                // each byte of the encryption key in step 4 and performing an XOR
                // operation between that byte and the single-byte value of the
                // iteration counter

                byte[] indexedKey = new byte[encryptionKey.Length];
                for (int i = 1; i <= 19; i++)
                {
                    for (int j = 0; j < encryptionKey.Length; j++)
                    {
                        indexedKey[j] = (byte)(encryptionKey[j] ^ (byte)i);
                    }
                    rc4         = new RC4(indexedKey, indexedKey.Length);
                    encryptData = rc4.CryptBuffer(encryptData, 0, encryptData.Length);
                }

                // Step 6: Append 16 bytes of arbitrary padding to the output from
                // the final invocation of the RC4 function and return the 32-byte
                // result as the value of the U entry.
                byte[] finalData = new byte[32];
                Array.Copy(encryptData, finalData, 16);
                Array.Copy(_paddingString, 0, finalData, 16, 16);
                return(finalData);
            }
        }
예제 #6
0
        // Computing Owner password value, Algorithm 3.3.
        private byte[] calculateOwnerHash(string ownerPassword, string userPassword, bool isAuthentication)
        {
            // Step 1:  padd the owner password, use the userPassword if empty.
            if ("".Equals(ownerPassword) && !"".Equals(userPassword))
            {
                ownerPassword = userPassword;
            }
            byte[] paddedOwnerPassword = padPassword(ownerPassword);

            // Step 2: Initialize the MD5 hash function and pass in step 2.
            MD5 md5 = MD5.Create();

            paddedOwnerPassword = md5.ComputeHash(paddedOwnerPassword);

            // Step 3: Do the following 50 times: take the output from the previous
            // MD5 hash and pass it as input into a new MD5 hash;
            // only for R = 3
            if (_revision >= 3)
            {
                for (int i = 0; i < 50; ++i)
                {
                    paddedOwnerPassword = md5.ComputeHash(paddedOwnerPassword, 0, _length / 8);
                }
            }

            // Step 4: Create an RC4 encryption key using the first n bytes of the
            // final MD5 hash, where n is always 5 for revision 2 and the value
            // of the encryption dictionary's Length entry for revision 3.
            int dataSize = 5;

            if (_revision >= 3)
            {
                dataSize = _length / 8;
            }

            byte[] encryptionKey = new byte[dataSize];
            Array.Copy(paddedOwnerPassword, encryptionKey, dataSize);

            // Key is needed by algorithm 3.7, Authenticating owner password
            if (isAuthentication)
            {
                return(encryptionKey);
            }

            // Step 5: Pad or truncate the user password string
            byte[] paddedUserPassword = padPassword(userPassword);

            // Step 6: Encrypt the result of step 4, using the RC4 encryption
            // function with the encryption key obtained in step 4
            RC4 rc4 = new RC4(encryptionKey, dataSize);

            byte[] finalData = rc4.CryptBuffer(paddedUserPassword, 0, paddedUserPassword.Length);

            // Step 7: Do the following 19 times: Take the output from the previous
            // invocation of the RC4 function and pass it as input to a new
            // invocation of the function; use an encryption key generated by taking
            // each byte of the encryption key in step 4 and performing an XOR
            // operation between that byte and the single-byte value of the
            // iteration counter
            if (_revision >= 3)
            {
                byte[] indexedKey = new byte[encryptionKey.Length];
                for (int i = 1; i <= 19; i++)
                {
                    for (int j = 0; j < encryptionKey.Length; j++)
                    {
                        indexedKey[j] = (byte)(encryptionKey[j] ^ i);
                    }

                    rc4       = new RC4(indexedKey, indexedKey.Length);
                    finalData = rc4.CryptBuffer(finalData, 0, finalData.Length);
                }
            }
            return(finalData);
        }