I have an application that uses CryptoStream to encrypt and decrypt
strings and stores and retrieves these values from a SQLServer
database.

When I run the application on my machine I can decrypt all the strings
in the database. When I run from a server I get "Bad Data" errors when
I try to close my CryptoStream.

Here is a sample application that I threw together:

using System;
using System.Collections;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace myTest
{
    class Program
    {
        private static byte[] byteToken;

        static void Main( string[] args )
        {
            Console.WriteLine( "Decoding sample string:" );

            string testtoken = "mGAETZOUuW5tjFR4ihp80D23JQg4Uhtfdq
+UjZlBOE9XIRVvi+FtKg3R7TygdTEOjG+Qj6SLXl24fng+vuubLzK1vX1igECVQV
+9KKDjWpSG82S
+GTVOMsButxrae1bN83XdcFV0TN82iBW3Er4fKFfYSgAwyNEDCtrKO1hbbInLD0Z5ktzNB
+pfU4JVOVKAUbSPjIt4/8Na8HJimxleF6q/0SmRL0EOiyJRMT1xrKSHBK2VY/
rJnMicl053U+J1ZDGcHbUBPY1Z+
+dd0cfgKD79t6N0QJLzyPeuRVjmobT6lxznalAxgp5g0IXQugsMHuWeBR/zl/yey/
+h5dHPoK5XRGs56F+P";

            Console.WriteLine( DecryptDES( testtoken ) );

            Console.WriteLine( "Creating new string:" );

            string tmpToken = EncryptDES( RandomString( 64, 64 ) );

            Console.WriteLine( tmpToken );

            Console.WriteLine( "Decoding new string:" );

            Console.WriteLine( DecryptDES( tmpToken ) );
        }


        #region Encryption Methods
        private static string RandomToken()
        {
            byte[] randombytes = new byte[128];

            RNGCryptoServiceProvider Gen = new RNGCryptoServiceProvider
();
            Gen.GetBytes( randombytes );
            byteToken = randombytes;

            return Encoding.Unicode.GetString( randombytes );
        }

        public static string RandomString( int minLength, int
maxLength )
        {

            string PASSWORD_CHARS_LCASE = "abcdefgijkmnopqrstwxyz";
            string PASSWORD_CHARS_UCASE = "ABCDEFGHJKLMNPQRSTWXYZ";
            string PASSWORD_CHARS_NUMERIC = "123456789";
            string PASSWORD_CHARS_SPECIAL = "*$-+?_&=!{}";

            // Create a local array containing supported password
characters
            // grouped by types. You can remove character groups from
this
            // array, but doing so will weaken the password strength.
            char[][] charGroups = new char[][]
            {
                PASSWORD_CHARS_LCASE.ToCharArray(),
                PASSWORD_CHARS_UCASE.ToCharArray(),
                PASSWORD_CHARS_NUMERIC.ToCharArray(),
                PASSWORD_CHARS_SPECIAL.ToCharArray()
             };

            // Use this array to track the number of unused characters
in each
            // character group.
            int[] charsLeftInGroup = new int[charGroups.Length];

            // Initially, all characters in each group are not used.
            for( int i = 0; i < charsLeftInGroup.Length; i++ )
                charsLeftInGroup[i] = charGroups[i].Length;

            // Use this array to track (iterate through) unused
character groups.
            int[] leftGroupsOrder = new int[charGroups.Length];

            // Initially, all character groups are not used.
            for( int i = 0; i < leftGroupsOrder.Length; i++ )
                leftGroupsOrder[i] = i;

            // Because we cannot use the default randomizer, which is
based on the
            // current time (it will produce the same "random" number
within a
            // second), we will use a random number generator to seed
the
            // randomizer.

            // Use a 4-byte array to fill it with random bytes and
convert it then
            // to an integer value.
            byte[] randomBytes = new byte[4];

            // Generate 4 random bytes.
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider
();
            rng.GetBytes( randomBytes );

            // Convert 4 bytes into a 32-bit integer value.
            int seed = ( randomBytes[0] & 0x7f ) << 24 |
                        randomBytes[1] << 16 |
                        randomBytes[2] << 8 |
                        randomBytes[3];

            // Now, this is real randomization.
            Random random = new Random( seed );
            // This array will hold password characters.
            char[] password = null;
            // Allocate appropriate memory for the password.
            if( minLength < maxLength )
                password = new char[random.Next( minLength, maxLength
+ 1 )];
            else
                password = new char[minLength];

            // Index of the next character to be added to password.
            int nextCharIdx;
            // Index of the next character group to be processed.
            int nextGroupIdx;
            // Index which will be used to track not processed
character groups.
            int nextLeftGroupsOrderIdx;
            // Index of the last non-processed character in a group.
            int lastCharIdx;
            // Index of the last non-processed group.
            int lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;

            // Generate password characters one at a time.
            for( int i = 0; i < password.Length; i++ )
            {
                // If only one character group remained unprocessed,
process it;
                // otherwise, pick a random character group from the
unprocessed
                // group list. To allow a special character to appear
in the
                // first position, increment the second parameter of
the Next
                // function call by one, i.e. lastLeftGroupsOrderIdx +
1.
                if( lastLeftGroupsOrderIdx == 0 )
                    nextLeftGroupsOrderIdx = 0;
                else
                    nextLeftGroupsOrderIdx = random.Next( 0,
lastLeftGroupsOrderIdx );

                // Get the actual index of the character group, from
which we will
                // pick the next character.
                nextGroupIdx = leftGroupsOrder
[nextLeftGroupsOrderIdx];
                // Get the index of the last unprocessed characters in
this group.
                lastCharIdx = charsLeftInGroup[nextGroupIdx] - 1;
                // If only one unprocessed character is left, pick it;
otherwise,
                // get a random character from the unused character
list.
                if( lastCharIdx == 0 )
                    nextCharIdx = 0;
                else
                    nextCharIdx = random.Next( 0, lastCharIdx + 1 );

                // Add this character to the password.
                password[i] = charGroups[nextGroupIdx][nextCharIdx];

                // If we processed the last character in this group,
start over.
                if( lastCharIdx == 0 )
                    charsLeftInGroup[nextGroupIdx] = charGroups
[nextGroupIdx].Length;
                // There are more unprocessed characters left.
                else
                {
                    // Swap processed character with the last
unprocessed character
                    // so that we don't pick it until we process all
characters in
                    // this group.
                    if( lastCharIdx != nextCharIdx )
                    {
                        char temp = charGroups[nextGroupIdx]
[lastCharIdx];
                        charGroups[nextGroupIdx][lastCharIdx] =
charGroups[nextGroupIdx][nextCharIdx];
                        charGroups[nextGroupIdx][nextCharIdx] = temp;
                    }
                    // Decrement the number of unprocessed characters
in
                    // this group.
                    charsLeftInGroup[nextGroupIdx]--;
                }

                // If we processed the last group, start all over.
                if( lastLeftGroupsOrderIdx == 0 )
                    lastLeftGroupsOrderIdx = leftGroupsOrder.Length -
1;
                // There are more unprocessed groups left.
                else
                {
                    // Swap processed group with the last unprocessed
group
                    // so that we don't pick it until we process all
groups.
                    if( lastLeftGroupsOrderIdx !=
nextLeftGroupsOrderIdx )
                    {
                        int temp = leftGroupsOrder
[lastLeftGroupsOrderIdx];
                        leftGroupsOrder[lastLeftGroupsOrderIdx] =
leftGroupsOrder[nextLeftGroupsOrderIdx];
                        leftGroupsOrder[nextLeftGroupsOrderIdx] =
temp;
                    }
                    // Decrement the number of unprocessed groups.
                    lastLeftGroupsOrderIdx--;
                }
            }
            // Convert password characters into a string and return
the result.
            return new string( password );

        }

        public static byte[] EncryptDES( byte[] clearData, byte[] Key,
byte[] IV )
        {

            MemoryStream ms = new MemoryStream();

            TripleDES tripDES = TripleDES.Create();

            tripDES.Key = Key;
            tripDES.IV = IV;

            CryptoStream cs = new CryptoStream( ms,
tripDES.CreateEncryptor(), CryptoStreamMode.Write );

            cs.Write( clearData, 0, clearData.Length );

            cs.Close();
            ms.Close();

            byte[] encryptedData = ms.ToArray();

            byte[] testbyte = new byte[byteToken.Length +
encryptedData.Length];
            byteToken.CopyTo( testbyte, 0 );
            encryptedData.CopyTo( testbyte, byteToken.Length );


            return testbyte;
        }

        public static string EncryptDES( string clearText )
        {

            byte[] clearBytes = Encoding.Unicode.GetBytes
( clearText );

            Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes
( RandomToken(),
                new byte[] { 0xe3, 0xe4, 0xed, 0x43, 0x6e, 0x74, 0x72,
0x61, 0x2e, 0x6d, 0x65, 0x6c,
                               0x4c, 0x6f, 0x6e, 0x62, 0x41, 0x4e,
0x6b, 0x2e, 0x43,
                               0x6f, 0x6d, 0x5c, 0x52, 0x50, 0x4e,
0x73, 0x53, 0xe3, 0xe4, 0xed} );

            byte[] encryptedData = EncryptDES( clearBytes, pdb.GetBytes
( 24 ), pdb.GetBytes( 8 ) );

            return Convert.ToBase64String( encryptedData );
        }
        #endregion


        #region Decryption Methods

        private static byte[] DecryptDES( byte[] cipherData, byte[]
Key, byte[] IV )
        {
            MemoryStream ms = new MemoryStream();

            TripleDES tripDES = TripleDES.Create();

            tripDES.Key = Key;
            tripDES.IV = IV;

            CryptoStream cs = new CryptoStream( ms,
tripDES.CreateDecryptor(), CryptoStreamMode.Write );
            cs.Write( cipherData, 0, cipherData.Length );
            cs.FlushFinalBlock();
            cs.Close();
            ms.Flush();
            ms.Close();

            byte[] decryptedData = ms.ToArray();
            return decryptedData;
        }

        public static string DecryptDES( string cipherText )
        {
            //string ErrorText = "Error: ";
            byte[] cipherBytes;
            try
            {
                try
                {
                    cipherBytes = Convert.FromBase64String
( cipherText );
                }
                catch
                {
                    throw new FormatException();
                }
                byte[] rmk = new byte[128];
                byte[] cipher = new byte[cipherBytes.Length - 128];

                int i = 0;
                for( i = 0; i < 128; i++ )
                {
                    rmk[i] = cipherBytes[i];
                }

                int j = 0;
                for( i = 0; i < ( cipherBytes.Length - 128 ); i++ )
                {
                    cipher[j] = cipherBytes[i + 128];
                    j++;
                }

                Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes
( System.Text.Encoding.Unicode.GetString( rmk ),
                    new byte[] { 0xe3, 0xe4, 0xed, 0x43, 0x6e, 0x74,
0x72, 0x61, 0x2e, 0x6d, 0x65, 0x6c,
                               0x4c, 0x6f, 0x6e, 0x62, 0x41, 0x4e,
0x6b, 0x2e, 0x43,
                               0x6f, 0x6d, 0x5c, 0x52, 0x50, 0x4e,
0x73, 0x53, 0xe3, 0xe4, 0xed} );

                byte[] decryptedData = DecryptDES( cipher, pdb.GetBytes
( 24 ), pdb.GetBytes( 8 ) );

                return Encoding.Unicode.GetString( decryptedData );
            }
            catch( Exception e )
            {
                throw new Exception( e.ToString() );
            }
        }
        #endregion

    }
}



Any help would be appreciated. Thanks.

Reply via email to