Converting VB6 AES Rijndael Block Cipher to C# by

2019-05-10 14:36发布

问题:

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.

回答1:

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