Same encryption codes cannot decrypt password from .NET 1.0 to 2.0

H

hohans

Hi all,

I have an encryption class that encrypts and decrypts password using
TripleDESCryptoServiceProvider. It was written originally in framework
1.0 and been working fine. And those passwords are stored in my SQL
server.

Now I need to migrate my application to framework 2.0. I use this same
class with framework 2.0 library to decrypt the passwords from database
(of course, they were encrypted in 1.0) but getting "Bad Data"
exception. The wierd thing is that, in 2.0 environment, it can encrypt
a new password and decrypt it back without any problem. It just cannot
decrypt the ones which were encrypted in 1.0.

Anyone experienced this problem before? Any ideas will be very
appreciated!!

Hans

I am also attaching the class as follows:


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

namespace test
{
/// <summary>
/// Summary description for EncryptionManager.
/// </summary>
public class EncryptionManager
{
public const int Encryption = 0;
public const int Decryption = 1;

private EncryptionManager()
{
}

public static string Encrypt(string toEncrypt, string key)
{
UnicodeEncoding encoder = new UnicodeEncoding();
return encoder.GetString(ParseBytes(encoder.GetBytes(toEncrypt),
key, Encryption));
}

public static string Decrypt(string toDecrypt, string key)
{
UnicodeEncoding encoder = new UnicodeEncoding();
return encoder.GetString(ParseBytes(encoder.GetBytes(toDecrypt),
key, Decryption));
}


private static byte[] ParseBytes (byte[] data, string key, int
direction)
{
TripleDES des = new TripleDESCryptoServiceProvider() ;
des.IV = new byte[8];

//init stream to write / read data
MemoryStream memStream = new MemoryStream();

PasswordDeriveBytes derivedBytes = new PasswordDeriveBytes(key, new
byte[0]);
des.Key = derivedBytes.CryptDeriveKey("RC2", "MD5", 128, new
byte[8]);

//set transform according to direction
ICryptoTransform transform;

if (direction == Encryption)
{
transform = des.CreateEncryptor();
}
else
{
transform = des.CreateDecryptor();
}

CryptoStream cryptoStream = new CryptoStream (memStream,
transform,
CryptoStreamMode.Write);

cryptoStream.Write (data, 0, data.Length);
cryptoStream.FlushFinalBlock();

//get the length of the encrypted data...
byte[] encodedResult = new byte[memStream.Length];
memStream.Position = 0;
memStream.Read(encodedResult, 0, encodedResult.Length);

memStream.Close();
cryptoStream.Close();

return encodedResult;
}

public static string GenerateKey()
{
UnicodeEncoding encoder = new UnicodeEncoding();
TripleDES des = new TripleDESCryptoServiceProvider();
return encoder.GetString(des.Key);
}
}



}
 
J

Jon Skeet [C# MVP]

I have an encryption class that encrypts and decrypts password using
TripleDESCryptoServiceProvider. It was written originally in framework
1.0 and been working fine. And those passwords are stored in my SQL
server.

Now I need to migrate my application to framework 2.0. I use this same
class with framework 2.0 library to decrypt the passwords from database
(of course, they were encrypted in 1.0) but getting "Bad Data"
exception. The wierd thing is that, in 2.0 environment, it can encrypt
a new password and decrypt it back without any problem. It just cannot
decrypt the ones which were encrypted in 1.0.

Anyone experienced this problem before? Any ideas will be very
appreciated!!

<snip>

I've seen the same problem, but haven't investigated it much - I'll try
to look into it further soon...
 
H

hohans

Jon,

Thanks for taking time looking into this. Let me know if you find out
anything.

Hans
 
J

Jon Skeet [C# MVP]

I have an encryption class that encrypts and decrypts password using
TripleDESCryptoServiceProvider. It was written originally in framework
1.0 and been working fine. And those passwords are stored in my SQL
server.

<snip>

Looking at it to start with - you really shouldn't be assuming that the
bytes which come back from encryption are a valid Unicode string. I
would suggest base64 encoding/decoding to convert between byte arrays
and "normal" text. It's unrelated to the problem you're seeing (I
believe) but is something to watch out for.

It's also worth using a "using" statement to close streams, so they end
up being closed even if an exception occurs.

Finally, don't use Stream.Read without checking the return value -
there's no guarantee it will read everything you want it to. See
http://www.pobox.com/~skeet/csharp/readbinary.html for more details.
When you're using a MemoryStream, however, you can just call ToArray to
get the bytes.

I'll post an "improved" version of your code when I've modified the
current version. As I say, it won't solve the problem, but it should
make it more obvious that there *is* a problem unrelated to the above
:)
 
J

Jon Skeet [C# MVP]

<snip>

Hmm. I've modified your code appropriately, but I can't get either your
original code or the modified code to fail (encrypting with 1.1 and
decrypting with 2.0). Could you provide some sample data which it fails
with?


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

public class EncryptionManager
{
SymmetricAlgorithm provider;

public EncryptionManager()
{
provider = new TripleDESCryptoServiceProvider();
provider.IV = new byte[8];
byte[] key = new byte[provider.KeySize/8];
for (int i=0; i < key.Length; i++)
{
key = (byte) i;
}
provider.Key = key;
}

public string Encrypt(string toEncrypt)
{
byte[] rawInput = Encoding.UTF8.GetBytes(toEncrypt);
byte[] rawOutput = Encrypt (rawInput);
return Convert.ToBase64String(rawOutput);
}

public string Decrypt(string toDecrypt)
{
byte[] rawInput = Convert.FromBase64String(toDecrypt);
byte[] rawOutput = Decrypt (rawInput);
return Encoding.UTF8.GetString(rawOutput);
}

public byte[] Encrypt (byte[] toEncrypt)
{
return Transform(provider.CreateEncryptor(), toEncrypt);
}

public byte[] Decrypt (byte[] toDecrypt)
{
return Transform(provider.CreateDecryptor(), toDecrypt);
}

byte[] Transform (ICryptoTransform transform, byte[] data)
{
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream
(memoryStream, transform, CryptoStreamMode.Write))
{
cryptoStream.Write(data, 0, data.Length);
cryptoStream.FlushFinalBlock();
}
return memoryStream.ToArray();
}
}

static void Main(string[] args)
{
EncryptionManager manager = new EncryptionManager();

if (args.Length==1)
{
Console.WriteLine (manager.Decrypt(args[0]));
}
else
{
Console.WriteLine (manager.Encrypt ("Test"));
}
}
}
 

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