Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1239
  • Last Modified:

URGENT Plzzz... Decrypted string is not same as original string.

Hello Friends,

Can you please help me fix the problem with the following code, I am using for encryption and decryption of free text?
After the string is encrypted, I am storing the encrypted string in the database, but when I am sending this information back to the user after the decryption, the decrypted string is not same as original text.

Example: I encrypted the original string "yagya" and stored the encrypted string in the database. But when I retrieve the string from the database and decrypt the string, the result comes to be "yag??". Which is not the original string (yagya). I am using the following code to do this..You may use your own password key to test the code.

Please let me know where exactly this is the problem. I am expecting a fully functional code to encrypt the string of any length.

Thanks for the assistance!
Run2004


using System;
using System.IO;
using System.Text;
using System.Security;
using System.Security.Cryptography;
using System.Web.Services;

namespace FE_SymmetricNamespace
{
public class FE_Symmetric
{
      static private Byte[] m_Key = new Byte[8];
      static private Byte[] m_IV = new Byte[8];
      
      //////////////////////////
      //Function to encrypt data
      public string EncryptData(String strKey, String strData)
      {
            string strResult;            //Return Result

            //1. String Length cannot exceed 90Kb. Otherwise, buffer will overflow. See point 3 for reasons
            if (strData.Length > 92160)
            {
                  strResult="Error. Data String too large. Keep within 90Kb.";
                  return strResult;
            }
      
            //2. Generate the Keys
            if (!InitKey(strKey))
            {
                  strResult="Error. Fail to generate key for encryption";
                  return strResult;
            }

            //3. Prepare the String
            //      The first 5 character of the string is formatted to store the actual length of the data.
            //      This is the simplest way to remember to original length of the data, without resorting to complicated computations.
            //      If anyone figure a good way to 'remember' the original length to facilite the decryption without having to use additional function parameters, pls let me know.
            strData = String.Format("{0,5:00000}"+strData, strData.Length);


            //4. Encrypt the Data
            byte[] rbData = new byte[strData.Length];
            ASCIIEncoding aEnc = new ASCIIEncoding();
            aEnc.GetBytes(strData, 0, strData.Length, rbData, 0);
            
            DESCryptoServiceProvider descsp = new DESCryptoServiceProvider();
            
            ICryptoTransform desEncrypt = descsp.CreateEncryptor(m_Key, m_IV);


            //5. Perpare the streams:
            //      mOut is the output stream.
            //      mStream is the input stream.
            //      cs is the transformation stream.
            MemoryStream mStream = new MemoryStream(rbData);
            CryptoStream cs = new CryptoStream(mStream, desEncrypt, CryptoStreamMode.Read);        
            MemoryStream mOut = new MemoryStream();
            
            //6. Start performing the encryption
            int bytesRead;
            byte[] output = new byte[1024];
            do
            {
                  bytesRead = cs.Read(output,0,1024);
                  if (bytesRead != 0)
                        mOut.Write(output,0,bytesRead);
            } while (bytesRead > 0);
            
            //7. Returns the encrypted result after it is base64 encoded
            //      In this case, the actual result is converted to base64 so that it can be transported over the HTTP protocol without deformation.
            if (mOut.Length == 0)            
                  strResult = "";
            else
                  strResult = Convert.ToBase64String(mOut.GetBuffer(), 0, (int)mOut.Length);
      
            return strResult;
      }

      //////////////////////////
      //Function to decrypt data
      public string DecryptData(String strKey, String strData)
      {
            string strResult;

            //1. Generate the Key used for decrypting
            if (!InitKey(strKey))
            {
                  strResult="Error. Fail to generate key for decryption";
                  return strResult;
            }

            //2. Initialize the service provider
            int nReturn = 0;
            DESCryptoServiceProvider descsp = new DESCryptoServiceProvider();
            ICryptoTransform desDecrypt = descsp.CreateDecryptor(m_Key, m_IV);
            
            //3. Prepare the streams:
            //      mOut is the output stream.
            //      cs is the transformation stream.
            MemoryStream mOut = new MemoryStream();
            CryptoStream cs = new CryptoStream(mOut, desDecrypt, CryptoStreamMode.Write);        
            
            //4. Remember to revert the base64 encoding into a byte array to restore the original encrypted data stream
            byte[] bPlain = new byte[strData.Length];
            try
            {
                  bPlain = Convert.FromBase64CharArray(strData.ToCharArray(), 0, strData.Length);
            }
            catch (Exception)
            {
                  strResult = "Error. Input Data is not base64 encoded.";
                  return strResult;
            }
            
            long lRead = 0;
            long lTotal = strData.Length;
            
            try
            {
                  //5. Perform the actual decryption
                  while (lTotal >= lRead)
                  {
                      cs.Write(bPlain,0,(int)bPlain.Length);
                      //descsp.BlockSize=64
                      lRead = mOut.Length + Convert.ToUInt32(((bPlain.Length / descsp.BlockSize) * descsp.BlockSize));
                  };
                  
                  ASCIIEncoding aEnc = new ASCIIEncoding();
                  strResult = aEnc.GetString(mOut.GetBuffer(), 0, (int)mOut.Length);
                  
                  //6. Trim the string to return only the meaningful data
                  //      Remember that in the encrypt function, the first 5 character holds the length of the actual data
                  //      This is the simplest way to remember to original length of the data, without resorting to complicated computations.
                  String strLen = strResult.Substring(0,5);
                  int nLen = Convert.ToInt32(strLen);
                  strResult = strResult.Substring(5, nLen);
                  nReturn = (int)mOut.Length;
                  
                  return strResult;
            }
            catch (Exception)
            {
                  strResult = "Error. Decryption Failed. Possibly due to incorrect Key or corrputed data";
                  return strResult;
            }
      }

      /////////////////////////////////////////////////////////////
      //Private function to generate the keys into member variables
      static private bool InitKey(String strKey)
      {
            try
            {
                  // Convert Key to byte array
                  byte[] bp = new byte[strKey.Length];
                  ASCIIEncoding aEnc = new ASCIIEncoding();
                  aEnc.GetBytes(strKey, 0, strKey.Length, bp, 0);
                  
                  //Hash the key using SHA1
                  SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider();
                  byte[] bpHash = sha.ComputeHash(bp);
                  
                  int i;
                  // use the low 64-bits for the key value
                  for (i=0; i<8; i++)
                        m_Key[i] = bpHash[i];
                        
                  for (i=8; i<16; i++)
                        m_IV[i-8] = bpHash[i];
                  
                  return true;
            }
            catch (Exception)
            {
                  //Error Performing Operations
                  return false;
            }
      }
}
}

0
run2004
Asked:
run2004
3 Solutions
 
Daniel Van Der WerkenIndependent ConsultantCommented:
I tested your encryption as follows and it works.  If you're missing the last two characters of the decrypted text, maybe it's not coming back from the database correctly?

Make sure the cyphertext you send to the dB is the same that comes out.

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

namespace ConsoleApplication1
{
    class Cypher
    {
        public Byte[] m_Key = new Byte[8];
        public Byte[] m_IV = new Byte[8];

        public string EncryptData(String strKey, String strData)
        {
            string strResult;          //Return Result

            //1. String Length cannot exceed 90Kb. Otherwise, buffer will overflow. See point 3 for reasons
            if (strData.Length > 92160)
            {
                strResult = "Error. Data String too large. Keep within 90Kb.";
                return strResult;
            }

            //2. Generate the Keys
            if (!InitKey(strKey))
            {
                strResult = "Error. Fail to generate key for encryption";
                return strResult;
            }

            //3. Prepare the String
            //     The first 5 character of the string is formatted to store the actual length of the data.
            //     This is the simplest way to remember to original length of the data, without resorting to complicated computations.
            //     If anyone figure a good way to 'remember' the original length to facilite the decryption without having to use additional function parameters, pls let me know.
            strData = String.Format("{0,5:00000}" + strData, strData.Length);


            //4. Encrypt the Data
            byte[] rbData = new byte[strData.Length];
            ASCIIEncoding aEnc = new ASCIIEncoding();
            aEnc.GetBytes(strData, 0, strData.Length, rbData, 0);

            DESCryptoServiceProvider descsp = new DESCryptoServiceProvider();

            ICryptoTransform desEncrypt = descsp.CreateEncryptor(m_Key, m_IV);


            //5. Perpare the streams:
            //     mOut is the output stream.
            //     mStream is the input stream.
            //     cs is the transformation stream.
            MemoryStream mStream = new MemoryStream(rbData);
            CryptoStream cs = new CryptoStream(mStream, desEncrypt, CryptoStreamMode.Read);
            MemoryStream mOut = new MemoryStream();

            //6. Start performing the encryption
            int bytesRead;
            byte[] output = new byte[1024];
            do
            {
                bytesRead = cs.Read(output, 0, 1024);
                if (bytesRead != 0)
                    mOut.Write(output, 0, bytesRead);
            } while (bytesRead > 0);

            //7. Returns the encrypted result after it is base64 encoded
            //     In this case, the actual result is converted to base64 so that it can be transported over the HTTP protocol without deformation.
            if (mOut.Length == 0)
                strResult = "";
            else
                strResult = Convert.ToBase64String(mOut.GetBuffer(), 0, (int)mOut.Length);

            return strResult;
        }

        public string DecryptData(String strKey, String strData)
        {
            string strResult;

            //1. Generate the Key used for decrypting
            if (!InitKey(strKey))
            {
                strResult = "Error. Fail to generate key for decryption";
                return strResult;
            }

            //2. Initialize the service provider
            int nReturn = 0;
            DESCryptoServiceProvider descsp = new DESCryptoServiceProvider();
            ICryptoTransform desDecrypt = descsp.CreateDecryptor(m_Key, m_IV);

            //3. Prepare the streams:
            //     mOut is the output stream.
            //     cs is the transformation stream.
            MemoryStream mOut = new MemoryStream();
            CryptoStream cs = new CryptoStream(mOut, desDecrypt, CryptoStreamMode.Write);

            //4. Remember to revert the base64 encoding into a byte array to restore the original encrypted data stream
            byte[] bPlain = new byte[strData.Length];
            try
            {
                bPlain = Convert.FromBase64CharArray(strData.ToCharArray(), 0, strData.Length);
            }
            catch (Exception)
            {
                strResult = "Error. Input Data is not base64 encoded.";
                return strResult;
            }

            long lRead = 0;
            long lTotal = strData.Length;

            try
            {
                //5. Perform the actual decryption
                while (lTotal >= lRead)
                {
                    cs.Write(bPlain, 0, (int)bPlain.Length);
                    //descsp.BlockSize=64
                    lRead = mOut.Length + Convert.ToUInt32(((bPlain.Length / descsp.BlockSize) * descsp.BlockSize));
                };

                ASCIIEncoding aEnc = new ASCIIEncoding();
                strResult = aEnc.GetString(mOut.GetBuffer(), 0, (int)mOut.Length);

                //6. Trim the string to return only the meaningful data
                //     Remember that in the encrypt function, the first 5 character holds the length of the actual data
                //     This is the simplest way to remember to original length of the data, without resorting to complicated computations.
                String strLen = strResult.Substring(0, 5);
                int nLen = Convert.ToInt32(strLen);
                strResult = strResult.Substring(5, nLen);
                nReturn = (int)mOut.Length;

                return strResult;
            }
            catch (Exception)
            {
                strResult = "Error. Decryption Failed. Possibly due to incorrect Key or corrputed data";
                return strResult;
            }
        }

        private bool InitKey(String strKey)
        {
            try
            {
                // Convert Key to byte array
                byte[] bp = new byte[strKey.Length];
                ASCIIEncoding aEnc = new ASCIIEncoding();
                aEnc.GetBytes(strKey, 0, strKey.Length, bp, 0);

                //Hash the key using SHA1
                SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider();
                byte[] bpHash = sha.ComputeHash(bp);

                int i;
                // use the low 64-bits for the key value
                for (i = 0; i < 8; i++)
                    m_Key[i] = bpHash[i];

                for (i = 8; i < 16; i++)
                    m_IV[i - 8] = bpHash[i];

                return true;
            }
            catch (Exception)
            {
                //Error Performing Operations
                return false;
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Cypher c = new Cypher();
            string TextString = "yagya";
            string ClearText = String.Empty;
            string CypherText = String.Empty;
            string key = "ABC";

            CypherText = c.EncryptData(key, TextString);
            ClearText = c.DecryptData(key, CypherText);

            Console.Write("Hello There\n");
        }
    }
}
0
 
ozymandiasCommented:
Your code works fine for me.

FE_Symmetric f = new FE_Symmetric();
string key = "keystring";
string text = "mary had a little lamb";
string s1 = f.EncryptData(key, text);
string s2 = f.DecryptData(key, s1);
Console.WriteLine(text);
Console.WriteLine(s1);
Console.WriteLine(s2);
Console.ReadLine();

produces this output :

mary had a little lamb
07OSXsP/ES0FNsZwDqTu/QZ+gJojItd6IThmZksUp/Q=
mary had a little lamb

So the encryption and decryption work fine.
It maybe that when you store the encrypted string in the database and then retrieve it something happens to it.
0
 
NightmanCTOCommented:
What database engine - I am assuming SQL.
What is the datatype in the database?
What length is the datatype in the database? (e.g. if varchar, is it varchar(20), etc).
What collation is the column in the database?
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
run2004Author Commented:
Nightman,

The database is SQL Server 2005. The field length is verchar(100). So this is my understanding that inserting the record should not be a problem.

I did observe one thing that the encrypted string ends with ==. So does this mean anything to SQL server(Equality).

I am blank on this. Let me know if you have any clue on this.

Thanks!
Run2004
0
 
run2004Author Commented:
Forgot to add one more thing. When I am inserting the record in the database, the last four characters are being lost. Now I see why I am not getting the original string after the decryption.

Thanks ozymandias  and Dan7el for pointing this out.
0
 
NightmanCTOCommented:
Try changing the column datatype to nvarchar(100)
0
 
run2004Author Commented:
I tried this by changing the field to nvarchar(100). The problem is still there.
0
 
run2004Author Commented:
I found out the cause of the problem. My code was referring the old assembly that had parameter defined for 20 characters.

It's working fine now.

Thanks for all your support.
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Tackle projects and never again get stuck behind a technical roadblock.
Join Now