"Length of the data to decrypt is invalid." when trying to decrypt TripleDes algorithm

D

Dica

i've used the sample code from msdn to create an encyption/decryption
assembly as found here:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/SecNetHT10.asp

i'm able to encrypt and then decrypt data okay as in the following code:
// encrypt the data //

Encryptor enc = new Encryptor(EncryptionAlgorithm.TripleDes);

byte[] key = Encoding.ASCII.GetBytes("0123456789012345");




byte[] btUserName = Encoding.ASCII.GetBytes(sUserName);

byte[] btUserNameCiphered = enc.Encrypt(btUserName, key);

System.Console.WriteLine("Unencoded userName: " +
Convert.ToBase64String(btUserName) + ". Ciphered userName: " +
Convert.ToBase64String(btUserNameCiphered));

// decrypt the data //

Decryptor dec = new Decryptor(EncryptionAlgorithm.TripleDes);

dec.IV = enc.IV;

byte[] btUserNameDecrypted = dec.Decrypt(btUserNameCiphered,key);

System.Console.WriteLine("Decrypted userName: " +
Encoding.ASCII.GetString(btUserNameDecrypted));



but, after saving the encrypted data to an XML node as follows:

oXmlWriter.WriteStartElement("", "userName", "");

oXmlWriter.WriteString(Convert.ToBase64String(btUserNameCiphered));

oXmlWriter.WriteEndElement();



i get an error when trying to read in the userName from XML and decrypt
later:

oXmlReader = new XmlTextReader (STR_FILE_NAME);

sUserName = oXmlReader.ReadString();

// decrypt the data //

Encryptor enc = new Encryptor(EncryptionAlgorithm.TripleDes);

Decryptor dec = new Decryptor(EncryptionAlgorithm.TripleDes);

byte[] key = Encoding.ASCII.GetBytes("0123456789012345");

dec.IV = enc.IV;

byte[] btUserNameCiphered = Encoding.ASCII.GetBytes(sUserName);

byte[] btUserNameDecrypted = dec.Decrypt(btUserNameCiphered,key); // this
line generates the error.



i suspect this is something to do with the way i've read the XML userName
value,but what and how to fix?

tks to anybody willing to take a shot at this.
 
O

Ollie Riches

bug in your code... :)

it is because you are not calling from Convert.FromBase64String when you
read the username from the xml file, what you are currently doing is getting
the value and coverting to byte array using the Encoding.ASCII.GetBytes
method.

HTH

Ollie Riches
 
D

Dica

Ollie Riches said:
bug in your code... :)

it is because you are not calling from Convert.FromBase64String when you
read the username from the xml file, what you are currently doing is getting
the value and coverting to byte array using the Encoding.ASCII.GetBytes
method.

thanks ollie, but now i've got a new problem. based on your response, i've
modified the code where i read back the encrypted XML node as follows and
then attempt to decrypt as follows:

sUserName = oXmlReader.ReadString();

byte[] btUserNameCiphered = Convert.FromBase64String(sUserName);

byte[] btUserNameDecrypted = dec.Decrypt(btUserNameCiphered,key); // craps
out here //

this decrypt class is throwing a "Bad Data" error.

any ideas?



HTH

Ollie Riches


Dica said:
i've used the sample code from msdn to create an encyption/decryption
assembly as found here:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/SecNetHT10.asp

i'm able to encrypt and then decrypt data okay as in the following code:
// encrypt the data //

Encryptor enc = new Encryptor(EncryptionAlgorithm.TripleDes);

byte[] key = Encoding.ASCII.GetBytes("0123456789012345");




byte[] btUserName = Encoding.ASCII.GetBytes(sUserName);

byte[] btUserNameCiphered = enc.Encrypt(btUserName, key);

System.Console.WriteLine("Unencoded userName: " +
Convert.ToBase64String(btUserName) + ". Ciphered userName: " +
Convert.ToBase64String(btUserNameCiphered));

// decrypt the data //

Decryptor dec = new Decryptor(EncryptionAlgorithm.TripleDes);

dec.IV = enc.IV;

byte[] btUserNameDecrypted = dec.Decrypt(btUserNameCiphered,key);

System.Console.WriteLine("Decrypted userName: " +
Encoding.ASCII.GetString(btUserNameDecrypted));



but, after saving the encrypted data to an XML node as follows:

oXmlWriter.WriteStartElement("", "userName", "");

oXmlWriter.WriteString(Convert.ToBase64String(btUserNameCiphered));

oXmlWriter.WriteEndElement();



i get an error when trying to read in the userName from XML and decrypt
later:

oXmlReader = new XmlTextReader (STR_FILE_NAME);

sUserName = oXmlReader.ReadString();

// decrypt the data //

Encryptor enc = new Encryptor(EncryptionAlgorithm.TripleDes);

Decryptor dec = new Decryptor(EncryptionAlgorithm.TripleDes);

byte[] key = Encoding.ASCII.GetBytes("0123456789012345");

dec.IV = enc.IV;

byte[] btUserNameCiphered = Encoding.ASCII.GetBytes(sUserName);

byte[] btUserNameDecrypted = dec.Decrypt(btUserNameCiphered,key); // this
line generates the error.



i suspect this is something to do with the way i've read the XML userName
value,but what and how to fix?

tks to anybody willing to take a shot at this.
 
J

Jon Skeet [C# MVP]

Dica said:
thanks ollie, but now i've got a new problem. based on your response, i've
modified the code where i read back the encrypted XML node as follows and
then attempt to decrypt as follows:

sUserName = oXmlReader.ReadString();

byte[] btUserNameCiphered = Convert.FromBase64String(sUserName);

byte[] btUserNameDecrypted = dec.Decrypt(btUserNameCiphered,key); // craps
out here //

this decrypt class is throwing a "Bad Data" error.

Could you post a short but complete program which demonstrates the
problem?

See http://www.pobox.com/~skeet/csharp/complete.html for details of
what I mean by that.
 
D

Dica

Jon Skeet said:
Dica said:
thanks ollie, but now i've got a new problem. based on your response, i've
modified the code where i read back the encrypted XML node as follows and
then attempt to decrypt as follows:

sUserName = oXmlReader.ReadString();

byte[] btUserNameCiphered = Convert.FromBase64String(sUserName);

byte[] btUserNameDecrypted = dec.Decrypt(btUserNameCiphered,key); // craps
out here //

this decrypt class is throwing a "Bad Data" error.

Could you post a short but complete program which demonstrates the
problem?

okay, you asked for it. i can't include the entire encryption assembly, but
will post the code that calls it. it's important to note that the decoder
class in the missing assembly does appear to be working fine since i'm able
to encode and then decode again as i've previously mentioned. the problem
appears to be when reading the encoded value in from XML. here's the code
and i'll include a snippet from the decode class where the error is getting
generated below.

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Xml;
using System.IO;
using Encryption;
using System.Text;
using Microsoft.Win32;

namespace timeTracker
{
public class userSettings : System.Windows.Forms.Form
{
private System.Windows.Forms.Button cmdSave;
private System.Windows.Forms.TextBox tbUserName;
private System.Windows.Forms.Label lblUserName;
private System.Windows.Forms.Label lblPassword;
private System.Windows.Forms.TextBox tbPassword;
private System.Windows.Forms.Button cmdCancel;
private System.Data.SqlClient.SqlConnection oSqlConnection;
private System.Data.SqlClient.SqlCommand oSqlSelectCommand;
private System.Data.SqlClient.SqlDataReader oReader;
private String STR_FILE_NAME = Application.UserAppDataPath +
"\\timeSheetConfig.xml";
private System.ComponentModel.Container components = null;

public userSettings()
{
InitializeComponent();
getDefaults();
}

protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code
private void InitializeComponent()
{
System.Resources.ResourceManager resources = new
System.Resources.ResourceManager(typeof(userSettings));
this.cmdSave = new System.Windows.Forms.Button();
this.tbUserName = new System.Windows.Forms.TextBox();
this.lblUserName = new System.Windows.Forms.Label();
this.lblPassword = new System.Windows.Forms.Label();
this.tbPassword = new System.Windows.Forms.TextBox();
this.cmdCancel = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// cmdSave
//
this.cmdSave.Location = new System.Drawing.Point(80, 72);
this.cmdSave.Name = "cmdSave";
this.cmdSave.TabIndex = 0;
this.cmdSave.Text = "Save";
this.cmdSave.Click += new System.EventHandler(this.cmdSave_Click);
//
// tbUserName
//
this.tbUserName.Location = new System.Drawing.Point(80, 16);
this.tbUserName.Name = "tbUserName";
this.tbUserName.Size = new System.Drawing.Size(160, 20);
this.tbUserName.TabIndex = 1;
this.tbUserName.Text = "";
//
// lblUserName
//
this.lblUserName.BackColor = System.Drawing.Color.Transparent;
this.lblUserName.Location = new System.Drawing.Point(8, 16);
this.lblUserName.Name = "lblUserName";
this.lblUserName.Size = new System.Drawing.Size(64, 23);
this.lblUserName.TabIndex = 2;
this.lblUserName.Text = "User Name";
//
// lblPassword
//
this.lblPassword.BackColor = System.Drawing.Color.Transparent;
this.lblPassword.Location = new System.Drawing.Point(8, 48);
this.lblPassword.Name = "lblPassword";
this.lblPassword.Size = new System.Drawing.Size(64, 23);
this.lblPassword.TabIndex = 3;
this.lblPassword.Text = "Password";
//
// tbPassword
//
this.tbPassword.Location = new System.Drawing.Point(80, 40);
this.tbPassword.Name = "tbPassword";
this.tbPassword.PasswordChar = '*';
this.tbPassword.Size = new System.Drawing.Size(160, 20);
this.tbPassword.TabIndex = 4;
this.tbPassword.Text = "";
//
// cmdCancel
//
this.cmdCancel.Location = new System.Drawing.Point(155, 72);
this.cmdCancel.Name = "cmdCancel";
this.cmdCancel.TabIndex = 5;
this.cmdCancel.Text = "Cancel";
this.cmdCancel.Click += new System.EventHandler(this.cmdCancel_Click);
//
// userSettings
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.BackgroundImage =
((System.Drawing.Image)(resources.GetObject("$this.BackgroundImage")));
this.ClientSize = new System.Drawing.Size(280, 133);
this.Controls.Add(this.cmdCancel);
this.Controls.Add(this.tbPassword);
this.Controls.Add(this.lblPassword);
this.Controls.Add(this.lblUserName);
this.Controls.Add(this.tbUserName);
this.Controls.Add(this.cmdSave);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "userSettings";
this.Text = "User Settings";
this.Load += new System.EventHandler(this.userSettings_Load);
this.ResumeLayout(false);

}
#endregion

private void cmdCancel_Click(object sender, System.EventArgs e)
{
this.Dispose();
}

public void getDefaults()
{
String sUserName = "";
String sPassword = "";

FileInfo oFileInfo = new FileInfo(STR_FILE_NAME);
bool bFileExists = oFileInfo.Exists;
if (bFileExists) // config file exists - read the user details values //
{
XmlTextReader oXmlReader = null;
oXmlReader = new XmlTextReader (STR_FILE_NAME);
try
{
while (oXmlReader.Read())
{
if(oXmlReader.NodeType == XmlNodeType.Element)
{
if (oXmlReader.LocalName.Equals("userName"))
{
sUserName = oXmlReader.ReadString();
}
}
}
}
catch(System.Xml.XmlException xmlErr)
{
MessageBox.Show("Error reading configuration file! Error is " + xmlErr,
"Configuration File Error");
}
finally
{
oXmlReader.Close();
}
}

// decrypt the data //
Encryptor enc = new Encryptor(EncryptionAlgorithm.TripleDes);
Decryptor dec = new Decryptor(EncryptionAlgorithm.TripleDes);
byte[] key = Encoding.ASCII.GetBytes("0123456789012345");
dec.IV = enc.IV;

byte[] btUserNameCiphered = Convert.FromBase64String(sUserName);
byte[] btUserNameDecrypted = dec.Decrypt(btUserNameCiphered,key);
System.Console.WriteLine("Converted back from XML: " +
Encoding.ASCII.GetString(btUserNameDecrypted));

enc = null;
dec = null;

tbUserName.Text = sDecryptedUserName;
}

private void cmdSave_Click(object sender, System.EventArgs e)
{
String sUserName = tbUserName.Text;
if (sUserName.Length < 1)
{
MessageBox.Show("Username cannot be blank");
}
else // okay so far - now test the login before saving //
{
oSqlConnection = new System.Data.SqlClient.SqlConnection();
oSqlSelectCommand = new System.Data.SqlClient.SqlCommand();
oSqlConnection.ConnectionString = "neverYouMind";
oSqlConnection.Open();

String sSql = "select id, firstName, lastName from [user] where userName
= '" + sUserName.Replace("'", "''") + "' and password = '" +
sPassword.Replace("'", "''") + "'";
oSqlSelectCommand.CommandText = sSql;
oSqlSelectCommand.CommandType = System.Data.CommandType.Text;
oSqlSelectCommand.Connection = oSqlConnection;

oReader = oSqlSelectCommand.ExecuteReader();
if (oReader.HasRows){ // login okay - save the info //

// encrypt the data //
Encryptor enc = new Encryptor(EncryptionAlgorithm.TripleDes);
byte[] key = Encoding.ASCII.GetBytes("0123456789012345");

byte[] btUserName = Encoding.ASCII.GetBytes(sUserName);
byte[] btUserNameCiphered = enc.Encrypt(btUserName, key);
System.Console.WriteLine("Unencoded userName: " +
Convert.ToBase64String(btUserName) + ". Ciphered userName: " +
Convert.ToBase64String(btUserNameCiphered));

// decrypt the data - i don't normally need to do this here but want to
see if my decoder class is working okay //
Decryptor dec = new Decryptor(EncryptionAlgorithm.TripleDes);
dec.IV = enc.IV;
byte[] btUserNameDecrypted = dec.Decrypt(btUserNameCiphered,key);
System.Console.WriteLine("Decrypted userName: " +
Encoding.ASCII.GetString(btUserNameDecrypted));

enc = null;
dec = null;

// now save info to xml user settings file //
FileInfo oFileInfo = new FileInfo(STR_FILE_NAME);
XmlTextWriter oXmlWriter = null;

using (FileStream stream = oFileInfo.Open(FileMode.OpenOrCreate,
FileAccess.Write))
{
oXmlWriter = new XmlTextWriter(stream, null);
try
{
oXmlWriter.Formatting = Formatting.Indented;
oXmlWriter.Indentation= 6;
oXmlWriter.Namespaces = false;

oXmlWriter.WriteStartDocument();

oXmlWriter.WriteStartElement("", "userDetails", "");

oXmlWriter.WriteStartElement("", "userName", "");
oXmlWriter.WriteString(Convert.ToBase64String(btUserNameCiphered));
oXmlWriter.WriteEndElement();

oXmlWriter.WriteEndElement();
oXmlWriter.Flush();
}
catch(Exception err)
{
Console.WriteLine("Exception: {0}", err.ToString());
}
finally
{
if (oXmlWriter != null)
{
oXmlWriter.Close();
stream.Close();
}
}
}
Form1.bReInitializeLogin = true;
MessageBox.Show("User details saved.", "Success");
this.Dispose();
}
else{
MessageBox.Show("Invalid login. Record not saved. Please try again.",
"Failure");
}

}
}

}
}


here's a snippet from the decoder class where the "Bad Data" message shows
up:

public byte[] Decrypt(byte[] bytesData, byte[] bytesKey)
{
//Set up the memory stream for the decrypted data.
MemoryStream memStreamDecryptedData = new MemoryStream();

//Pass in the initialization vector.
transformer.IV = initVec;
ICryptoTransform transform =
transformer.GetCryptoServiceProvider(bytesKey);
CryptoStream decStream = new CryptoStream(memStreamDecryptedData,
transform,
CryptoStreamMode.Write);
try
{
decStream.Write(bytesData, 0, bytesData.Length);
}
catch(Exception ex)
{
throw new Exception("Error while writing encrypted data to the stream: \n"
+ ex.Message);
}
decStream.FlushFinalBlock();
decStream.Close(); // attempts to call this method and decrypt the XML
data crap out on this line //
// Send the data back.
return memStreamDecryptedData.ToArray();
} //end Decrypt

tks
 
J

Jon Skeet [C# MVP]

Dica said:
okay, you asked for it. i can't include the entire encryption assembly, but
will post the code that calls it.

I asked for a short but complete example - and I'm afraid yours is
neither. Did you read the page I linked to?

The GUI is not important in the encryption/decryption.
The SQL is not important in the encryption/decryption.
The XML *probably* isn't important in the encryption/decryption.

All you need to post is a console app which encrypts a sample string,
decrypts it, and checks whether the results are correct. Write that app
taking the appropriate bits of code from your real code.

If it works, you'll be able to plug the same sample string into your
real code, see what comes out in the XML, and work out whether it's the
encryption which is failing or the decryption.

If it doesn't work, we'll have something we can actually work on and
fix.
 
D

Dica

Jon Skeet said:
I asked for a short but complete example - and I'm afraid yours is
neither. Did you read the page I linked to?

The GUI is not important in the encryption/decryption.
The SQL is not important in the encryption/decryption.
The XML *probably* isn't important in the encryption/decryption.

it's the only thing that is.
All you need to post is a console app which encrypts a sample string,
decrypts it, and checks whether the results are correct. Write that app
taking the appropriate bits of code from your real code.

if you read my original post, you'll see that i have already been able to
successfully encrypt and decrypt the data. writing a srtripped down console
app to verify what i already know and have already shared with anybody
reading this thread seems gratuitous and a waste of time. i've already
narrowed down where the app is failing.
If it works, you'll be able to plug the same sample string into your
real code, see what comes out in the XML, and work out whether it's the
encryption which is failing or the decryption.

again, i've already done this. as i stated in my original post:
"i get an error when trying to read in the userName from XML and decrypt
later:"
 
J

Jon Skeet [C# MVP]

Dica said:
it's the only thing that is.

In that case, you only need to have the XML part - no GUI, no SQL, no
encryption.
if you read my original post, you'll see that i have already been able to
successfully encrypt and decrypt the data. writing a srtripped down console
app to verify what i already know and have already shared with anybody
reading this thread seems gratuitous and a waste of time. i've already
narrowed down where the app is failing.

Not in your previous post you haven't. If you had, you wouldn't have
*four* elements involved.
again, i've already done this. as i stated in my original post:
"i get an error when trying to read in the userName from XML and decrypt
later:"

Which suggests that the problem is either in the reading from the XML
or the decryption. You should be able to narrow down which it is - and
post a short but complete program which demonstrates *that* problem.

You haven't given us anything we can run, and what you *have* given us
has a load of irrelevant stuff (such as a UI).

Jon
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top