将VB6 AES Rijndael块密码转换为C#的方法(作者:Phil Fresle)

4
我正在将一个经典ASP应用程序转换为C#,希望能够在C#中解密最初在经典ASP中加密的字符串。经典ASP代码在这里,而C#代码在这里。我面临的问题是ASP和C#中Encrypt和Decrypt方法的签名不同。这是我的解密ASP代码,它包装了解密代码。
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

然而,在C#中,我很难转换这个函数,因为DecryptData的C#等效函数有更多的参数。

public static byte[] DecryptData(byte[] message, byte[] password, 
            byte[] initialisationVector, BlockSize blockSize, 
            KeySize keySize, EncryptionMode cryptMode)
        {...}

我希望您能够提供初始向量、块大小、密钥大小和加密模式的合适取值,以便能够像经典的ASP代码一样进行解密。


这完全取决于DecryptData()函数的作用。但是,您可能正在使用不安全的ECB模式。 - SLaks
谢谢,DecryptData函数在经典ASP和C#版本的代码中都存在,我可以将其粘贴在这里,但它是一段相当长的代码,可以在我发布的链接中找到。我的最大挑战是DecryptData函数具有不同的签名,但却是同一作者编写的。我想从经典ASP迁移到C#,并希望逐步淘汰ASP代码,因此加密必须在C#中产生与ASP相同的结果。 - sawe
所以你要我们告诉你函数使用的模式,却没有给出函数的代码? - SLaks
1
在这里找到了加密解决方案,https://dev59.com/EErSa4cB1Zd3GeqPTybF#14674957。 - sawe
1
看起来像是VBScript,而不是VB6。 - Bob77
1个回答

3
使用Phil Fresle的C# Rijndael实现,您可以使用以下代码成功解密使用Phil的ASP/VBScript版本加密的值。
您可以在此处阅读有关加密的答案: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);
    }

大多数默认实现将使用密钥长度为128192256比特。块大小设为128位是标准的。尽管某些实现允许块大小不等于128位,但更改块大小只会在试图使一个实现中加密的数据在另一个实现中正确解密时增加混淆因素。

更新

事实证明,我在这里错了一个地方;EncryptionMode 应该设置为 EncryptionMode.ModeECB 而不是 EncryptionMode.ModeCBC。"ECB" 不够安全 (https://crypto.stackexchange.com/questions/225/should-i-use-ecb-or-cbc-encryption-mode-for-my-block-cipher),因为它不像 CBC 那样循环,但这就是 VB 版本加密的实现方式。

有趣的是,在 ECB 加密值上使用 CBC 会在前几个字节之后(我想这与块大小有关)正常工作,直到某个点(其余的值被损坏)。您可以在使用 EncryptionMode.ModeECB 模式的上面代码解密 VB 版本中的较长字符串时清晰地看到这一点。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接