none
Simple encryption/decryption problem: length of data to decrypt invalid RRS feed

  • Question

  • I have an application which writes an encrypted string into a .xml file, then later attempts to read it back.

    It seems to work for most strings, but for some reason I have found it will not decrypt the encrypted string of "7".

    There was an encryption/decryption tutorial on msdn, and using it I got the encrypted byte array for 7 as:

    85
    1
    239
    238
    234
    109
    12
    13

    When writing the encrypted string in my application to the .xml I got the same thing.
    However, when reading it back there was an additional byte appended: a 10.  When trying to decrypt I got a "length of the data to decrypt is invalid" message.

    If it helps, the encrypted string from the tutorial was: Uïîêm
    The encrypted string to be written to the xml was: Uïîêm
    How the encrypted string appeared in the xml with the IE browser: Uïîêm
    Lastly the encrypted string in the xml read with visual studio: Uïîêm

    It seems the string is the same... except for the  character at the end.  What is this, and why is it being appended?  Is this just something inherent to xml?
    Any help would be greatly appreciated.
    Tuesday, August 12, 2008 6:53 PM

Answers

  • Right, I see you're using Encoding.Default there in the conversion from byte[] to string. That's simply wrong, since not all byte arrays represent a valid ANSI encoded string (not to mention the fact that the default ANSI code page can differ from one system to the other).

    If you can change your algorihtm at this point, I suggest you replace

    string retString = Encoding.Default.GetString(buffer);  

    with 

    string 
    retString = Convert.ToBase64String(buffer);


    and similarly use FromBase64String instead of Encoding.Default.GetBytes in the decryption method.


    Mattias, C# MVP
    • Marked as answer by S.R.H_ Wednesday, August 13, 2008 2:58 PM
    • Marked as answer by S.R.H_ Wednesday, August 13, 2008 2:58 PM
    • Marked as answer by S.R.H_ Wednesday, August 13, 2008 2:58 PM
    Wednesday, August 13, 2008 2:13 PM
    Moderator

All replies

  • Can you show us your code for converting the byte array to a string (and back)? I'd recommend doing it by Base64-encoding the array, but I'm guessing you're using some kind of Encoding class.


    Mattias, C# MVP
    Wednesday, August 13, 2008 7:51 AM
    Moderator
  • public static string encryptString(string PlainText, string sKey)  
    {  
         // Create a memory stream.  
         MemoryStream ms = new MemoryStream();  
     
         // Create a CryptoStream using the memory stream and the   
         // CSP DES key.    
         DESCryptoServiceProvider DES = new DESCryptoServiceProvider();  
         DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);  
         DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);  
     
         ICryptoTransform desencrypt = DES.CreateEncryptor();  
         CryptoStream encStream = new CryptoStream(ms, desencrypt,CryptoStreamMode.Write);  
         // Create a StreamWriter to write a string  
         // to the stream.  
         StreamWriter sw = new StreamWriter(encStream);  
     
         // Write the plaintext to the stream.  
         sw.WriteLine(PlainText);  
     
         // Close the StreamWriter and CryptoStream.  
         sw.Close();  
         encStream.Close();  
         byte[] buffer = ms.ToArray();  
         string retString = Encoding.Default.GetString(buffer);  
     
         // Close the memory stream.  
         ms.Close();  
     
         // Return the encrypted string.  
         return retString;  

    public static string decryptString(string CypherText, string sKey)  
    {  
          MemoryStream ms = new MemoryStream(Encoding.Default.GetBytes(CypherText));  
     
          DESCryptoServiceProvider DES = new DESCryptoServiceProvider();  
          DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);  
          DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);  
     
          // Create a CryptoStream using the memory stream and the   
          // CSP DES key.   
          ICryptoTransform desdecrypt = DES.CreateDecryptor();  
          CryptoStream encStream = new CryptoStream(ms,desdecrypt,CryptoStreamMode.Read);  
     
          // Create a StreamReader for reading the stream.  
          StreamReader sr = new StreamReader(encStream);  
                  
          // Read the stream as a string.  
          string val = sr.ReadLine();  
     
          // Close the streams.  
          sr.Close();  
          encStream.Close();  
          ms.Close();  
     
          return val;  

    As I said, most of this code was taken from an example I found on msdn.  This is where the encrypt method is used:

    writeStream = new StreamWriter(lastReportName);  
    XmlWriterSettings settings = new XmlWriterSettings();  
    settings.CheckCharacters = false;  
    settings.Indent = true;  
    writer = XmlWriter.Create(writeStream,settings);  
    //.....  
    //.....  
    //7 is problem text  
    writer.WriteValue(FileEncryption.encryptString("Text",ENCRYPTIONKEY));   
     

    This is where it is decrypted:

    XmlTextReader reader = new XmlTextReader(textBoxEncryptedReportInput.Text);  
    XmlDocument report = new XmlDocument();  
    report.Load(reader);  
     
    //....  
    //....  
     
    nodeOfInterest.InnerText = FileEncryption.decryptString(nodeOfInterest.InnerText, ENCRYPTIONKEY); 
    Wednesday, August 13, 2008 1:58 PM
  • Right, I see you're using Encoding.Default there in the conversion from byte[] to string. That's simply wrong, since not all byte arrays represent a valid ANSI encoded string (not to mention the fact that the default ANSI code page can differ from one system to the other).

    If you can change your algorihtm at this point, I suggest you replace

    string retString = Encoding.Default.GetString(buffer);  

    with 

    string 
    retString = Convert.ToBase64String(buffer);


    and similarly use FromBase64String instead of Encoding.Default.GetBytes in the decryption method.


    Mattias, C# MVP
    • Marked as answer by S.R.H_ Wednesday, August 13, 2008 2:58 PM
    • Marked as answer by S.R.H_ Wednesday, August 13, 2008 2:58 PM
    • Marked as answer by S.R.H_ Wednesday, August 13, 2008 2:58 PM
    Wednesday, August 13, 2008 2:13 PM
    Moderator
  • Ah, that did it.  Can I be sure then that this will work for every potential value?

    I had tried each of the different Encodings available, and each one had given me errors before, and changing it to Encoding.Default had managed to work for that case.  Strange that it didn't like that particular value.

    Thanks.
    Wednesday, August 13, 2008 3:00 PM