I am converting a classic asp application to C#, and would like to be able to decrypt strings in c# that were originally encrypted in classic asp. the classic asp code is here, and the c# code is here. The problem that i am facing is that the signatures of the Encrypt and Decrypt methods in asp vs C# are different. here is my asp code for decrypting, which wraps the decrypt code.
Function AESDecrypt(sCypher)
if sCypher <> "" then
Dim bytIn()
Dim bytOut
Dim bytPassword()
Dim lCount
Dim lLength
Dim sTemp
Dim sPassword
sPassword = "My_Password"
lLength = Len(sCypher)
ReDim bytIn(lLength/2-1)
For lCount = 0 To lLength/2-1
bytIn(lCount) = CByte("&H" & Mid(sCypher,lCount*2+1,2))
Next
lLength = Len(sPassword)
ReDim bytPassword(lLength-1)
For lCount = 1 To lLength
bytPassword(lCount-1) = CByte(AscB(Mid(sPassword,lCount,1)))
Next
bytOut = DecryptData(bytIn, bytPassword) //' this is the problem child
lLength = UBound(bytOut) + 1
sTemp = ""
For lCount = 0 To lLength - 1
sTemp = sTemp & Chr(bytOut(lCount))
Next
AESDecrypt = sTemp
End if
End Function
However, in c# i am struggling to convert this function because the c# equivalent of DecryptData has more params
public static byte[] DecryptData(byte[] message, byte[] password,
byte[] initialisationVector, BlockSize blockSize,
KeySize keySize, EncryptionMode cryptMode)
{...}
what values can i use for initialisationVector, blockSize, keySize, cryptMode so as to be able to decrypt the same way the classic asp code does.
Using Phil Fresle's C# Rijndael implementation, you can use the following code to have successfully decrypt a value that was encrypted with Phil's ASP/VBScript version.
You can read my answer about encrypting here: Password encryption/decryption between classic asp and ASP.NET
public string DecryptData(string encryptedMessage, string password)
{
if (encryptedMessage.Length % 2 == 1)
throw new Exception("The binary key cannot have an odd number of digits");
byte[] byteArr = new byte[encryptedMessage.Length / 2];
for (int index = 0; index < byteArr.Length; index++)
{
string byteValue = encryptedMessage.Substring(index * 2, 2);
byteArr[index] = byte.Parse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
}
byte[] result = Rijndael.DecryptData(
byteArr,
Encoding.ASCII.GetBytes(password),
new byte[] { }, // Initialization vector
Rijndael.BlockSize.Block256, // Typically 128 in most implementations
Rijndael.KeySize.Key256,
Rijndael.EncryptionMode.ModeECB // Rijndael.EncryptionMode.ModeCBC
);
return ASCIIEncoding.ASCII.GetString(result);
}
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.
UPDATE
Turns out I was wrong about one piece here; the EncryptionMode
should be set as EncryptionMode.ModeECB
, not EncryptionMode.ModeCBC
. "ECB" is less secure (https://crypto.stackexchange.com/questions/225/should-i-use-ecb-or-cbc-encryption-mode-for-my-block-cipher) because it doesn't cycle like CBC does, but that is how it was implemented in the VB version of the encryption.
Interestingly enough, using CBC on an ECB encrypted value WILL work for the first handful of bytes up until a certain point (i'd imagine this has to do with the block size) at which point the remainder of the value is mangled. You can see this particularly clearly when encrypting a long-ish string in the VB version and decrypting it with the code I posted above with a mode of EncryptionMode.ModeECB