I have 2 websites: one written in classic asp and another written in ASP.NET (1.1 framework). Both applications use a login mechanism to validate user credentials based on a shared database table. Up to now passwords are stored in a 1-way MD5 hash, meaning people must be given a new generated password if they lose the old one. I now want to change this and make the passwords decryptable.
I found this Rijndael code to use with classic asp:
http://www.frez.co.uk/freecode.htm#rijndael
But I cannot find the same solution for ASP.NET. I tried this, but it gives me different encryption and decryption results between the classic asp and ASP.NET code:
If Not String.IsNullOrEmpty(TextBox1.Text) And Not String.IsNullOrEmpty(TextBox2.Text) Then
Dim password = TextBox1.Text
Dim key = TextBox2.Text
Dim keyGenerator = New Rfc2898DeriveBytes(key, 8)
Dim r = New RijndaelManaged
r.Mode = CipherMode.CBC
r.Padding = PaddingMode.Zeros
r.BlockSize = 256
r.KeySize = 256
r.FeedbackSize = 256
r.IV = keyGenerator.GetBytes(CType(r.BlockSize / 8, Integer))
r.Key = keyGenerator.GetBytes(CType(r.KeySize / 8, Integer))
Dim transform As ICryptoTransform = r.CreateEncryptor()
Dim encoded As Byte() = Encoding.ASCII.GetBytes(password)
Dim target As Byte() = transform.TransformFinalBlock(encoded, 0, encoded.Length)
TextBox3.Text = Encoding.ASCII.GetString(target)
End If
I think I'm doing something wrong with generating the key or iv, but I can't find a solution.
I had a quick look at the classic asp files and it doesn't mention the block mode used, whereas your .net code specifies CBC mode and also the padding. Further the classic implementation states:
' 3-Apr-2001: Functions added to the
bottom for encrypting/decrypting large
' arrays of data. The entire length of
the array is inserted as the first
four ' bytes onto the front of the
first block of the resultant byte
array before ' encryption.
Are you using those functions, if you are then your encrypting the size bytes too.
Be assured the .net encryption works well, I'd guess your problem is in the classic solution you've found. If I were in your position I'd start by simplifying things and just encrypt a single block with each method and then expand from there... good luck
Phil Fresle provides a C# version of this code downloadable here: http://www.frez.co.uk/csharp.aspx. The implementation is still different than the classic version as it takes arguments for an initialization vector as well as the block and key size.
You can use this implementation to match the classic version like so:
// Convert the input values to byte[]'s representing ASCII encoding.
// This is what the classic version does
byte[] dataToEncrypt = ASCIIEncoding.ASCII.GetBytes("Ryno");
byte[] password = ASCIIEncoding.ASCII.GetBytes("Saurus");
// Encrypt the data into an array of types
// Notice the block size is 256 bits and the initialization vector is empty.
byte[] results = Rijndael.EncryptData(
dataToEncrypt,
password,
new byte[] { }, // Initialization vector
Rijndael.BlockSize.Block256, // Typically 128 in most implementations
Rijndael.KeySize.Key256,
Rijndael.EncryptionMode.ModeEBC
);
// Convert bytes into a HEX string representation
StringBuilder hex = new StringBuilder(results.Length * 2);
foreach (byte b in results)
hex.AppendFormat("{0:x2}", b);
// FINAL OUTPUT: This matches output of classic ASP Rijndael encryption
string hexEncodedString= hex.ToString();
Most default implementations will use a key size of 128, 192, or 256 bits. A block size at 128 bits is standard. Although some implementations allow block sizes other than 128 bits, changing the block size will just add another item into the mix to cause confusion when trying to get data encrypted in one implementation to properly decrypt in another.
Hopefully this helps.
Update
Phil's link is no longer available, so I've created a 2 Gists:
- ASP / VB Implementation: https://gist.github.com/ryno1234/2fc83faff281babea7f8
- C# Implementation with helper class for ASP interop: https://gist.github.com/ryno1234/ea34415643d109974b6f
Since ASP classic doesn't have native hash functions, you'll probably need to port your MD5 VBScript code to your .NET language, or to use a common cryptography component, due some error on your legacy code.