【问题标题】:AES cryptography in vb6 and c#vb6 和 c# 中的 AES 加密
【发布时间】:2012-12-22 23:40:34
【问题描述】:

我需要一个 .NET (理想情况下是 C#) 算法,它会产生与我用来加密的 vb6decrypt 二进制文件相同的结果。我已经尝试寻找代码一周了,但收效甚微。

我从How to encrypt a string in VB6 decrypt VB.NET 开始,但这只是一个半解决方案,它使用RC2 而不是AES。经过一番摆弄,我得到了我的vb6 代码在AES 中工作,但我找不到让c# 产生相同结果的方法。我认为这与我制作KeyIV 的方式有关。我一直在讨论Cryptographic Services 我的尝试可以分为两种基本类型。我尝试过PasswordDeriveBytes.CryptDeriveKey 并尝试使其与aes 一起工作的地方。根本没有成功。并尝试我试图模仿它的行为。下面我将发布我的vb6 代码和我最接近的c# 尝试。我不能 100% 肯定地说 vb6 是完美的,所以如果需要在那里进行更改,我愿意接受。我知道有一种方法可以使用 p 调用,并且我知道有一种方法可以让 .net dll 被我的vb apps 调用。我宁愿不走那条路。

VB6 函数

Public Function Crypt_File(PathToSourceFile As String, PathToDestFile As String, Password As String, HowTo As CryptMethod) As Boolean
Const FName As String = "mdlCryptography.Encrypt_file"
Dim CryptoContext As Long
Dim strProvider As String
Dim HashHnd As Long
Dim CrypKey As Long
Dim Step As Integer
Dim CryptBuff As String
Dim InFileNum As Long, OutFileNum As Long
Dim BytesRemaining As Long, CurrentBufferSize  As Long
Dim MAX_BUFFER_SIZE As Long
Dim DoCryptFinalise As Long
Dim Buff As String
On Error GoTo Trap:
    Step = 10
    Crypt_File = False
    If PathToSourceFile = PathToDestFile Then '
        Err.Raise 334, FName, "Sourse and Dest Path are the same"
    End If
    MAX_BUFFER_SIZE = (2 ^ 20) * 100 '100 MB
    Buff = vbNullChar
    strProvider = MS_ENH_RSA_AES_PROV_A & vbNullChar
    If Not CBool(CryptAcquireContext(CryptoContext, ByVal Buff, ByVal strProvider, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) Then
        Err.Raise 33410, FName, "Unable to Acquire Context: " & MS_ENH_RSA_AES_PROV_A
    End If

    If Not CBool(CryptCreateHash(CryptoContext, CALG_SHA_256, ByVal 0&, ByVal 0&, HashHnd)) Then
        Err.Raise 33420, FName, "Unable to Create a hash object. " & MS_ENH_RSA_AES_PROV_A
    End If

    If Not CBool(CryptHashData(HashHnd, Password, Len(Password), ByVal 0&)) Then
        Err.Raise 33430, FName, "Unable to Hash password. "
    End If

    If Not CBool(CryptDeriveKey(CryptoContext, CALG_AES_256, HashHnd, ByVal CRYPT_NO_SALT, CrypKey)) Then
        Err.Raise 33440, FName, "Unable to Derive Key. "
    End If
    'Clear HashHnd
    If HashHnd <> 0 Then
        Call CryptDestroyHash(HashHnd)
    End If
    HashHnd = 0

    'Prep Data For encryption
    DoCryptFinalise = 0
    InFileNum = FreeFile
    Step = 20
    Open PathToSourceFile For Binary Access Read As #InFileNum
    If LenB(Dir$(PathToDestFile)) > 0 Then
        Kill PathToDestFile
    End If
    OutFileNum = FreeFile
    Step = 25
    Open PathToDestFile For Binary Access Write As #OutFileNum

    BytesRemaining = LOF(InFileNum)
    'Loop through File Chunks
    Do While BytesRemaining > 0

        If BytesRemaining >= MAX_BUFFER_SIZE Then
            CurrentBufferSize = MAX_BUFFER_SIZE
        Else
            CurrentBufferSize = BytesRemaining
            DoCryptFinalise = 1
        End If

        Buff = String$(CurrentBufferSize, vbNullChar)
        Get #InFileNum, , Buff
            If HowTo = CryptMethod.Encrypt Then
                CryptBuff = EncryptBuffer(CrypKey, DoCryptFinalise, Buff)
            Else
                CryptBuff = DecryptBuffer(CrypKey, DoCryptFinalise, Buff)
            End If
        Put #OutFileNum, , CryptBuff

        BytesRemaining = BytesRemaining - CurrentBufferSize
    Loop
    Close #InFileNum
    Close #OutFileNum
    Crypt_File = True

GoTo Fin
Trap:
    Crypt_File = False
    If Step = 20 Then
        Close #InFileNum
    End If
    If Step = 25 Then
        Close #InFileNum
        Close #OutFileNum
    End If
    Err.Raise Err.Number, Err.source, Err.Description
Fin:

    If CrypKey <> 0 Then
        Call CryptDestroyKey(CrypKey)
    End If
    If HashHnd <> 0 Then
        Call CryptDestroyHash(HashHnd)
    End If
End Function

Private Function EncryptBuffer(CrypKey As Long, DoCryptFinalise As Long, Buff As String) As String
Dim EncDataLength As Long, EnctBuffLen As Long
Dim CryptBuff As String

    EncDataLength = Len(Buff)
    EnctBuffLen = EncDataLength + AES_BLOCK_SIZE
    CryptBuff = String$(EnctBuffLen, vbNullChar)
    LSet CryptBuff = Buff
    If Not CBool(CryptEncrypt(CrypKey, ByVal 0&, ByVal DoCryptFinalise, ByVal 0&, CryptBuff, EncDataLength, EnctBuffLen)) Then
'        Close #InFileNum
'        Close #OutFileNum
        Err.Raise 33450, "mdlCryptography.EncryptBuffer", "Encryption Error"
    End If
    EncryptBuffer = Left$(CryptBuff, EncDataLength)
End Function


Private Function DecryptBuffer(CrypKey As Long, DoCryptFinalise As Long, Buff As String) As String
Dim EncDataLength As Long
Dim CryptBuff As String

    EncDataLength = Len(Buff)
    CryptBuff = String$(EncDataLength, vbNullChar)
    LSet CryptBuff = Buff
    If Not CBool(CryptDecrypt(CrypKey, ByVal 0&, ByVal DoCryptFinalise, ByVal 0&, CryptBuff, EncDataLength)) Then
'        Close #InFileNum
'        Close #OutFileNum
        Err.Raise 33450, "mdlCryptography.DecryptBuffer", "Decryption Error"
    End If
    DecryptBuffer = Left$(CryptBuff, EncDataLength)
End Function

c# 非常不精致

private void Crypt(bool DoEn)
{
    int Rfc2898KeygenIterations = 100;
    int AesKeySizeInBits = 128;
    byte[] rawPlaintext ;//= System.Text.Encoding.Unicode.GetBytes("This is all clear now!");
    byte[] cipherText = null;
    byte[] plainText = null;

    using (Aes aes = new AesManaged())
    {

        int KeyStrengthInBytes = aes.KeySize / 8;

        SHA256 MySHA = new SHA256Cng();
        MySHA.Initialize();
        plainText = Encoding.ASCII.GetBytes(txtPassword.Text);
        aes.Key = MySHA.ComputeHash(plainText );
        aes.IV =  Encoding.ASCII.GetBytes("0000000000000000");
        if (DoEn)
        {
            //using (FileStream fs = new FileStream(txtOut.Text,FileMode.CreateNew ))
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    //using (StreamReader myFile = new StreamReader(txtIn.Text))
                    //{
                    //    rawPlaintext = System.Text.Encoding.ASCII.GetBytes(myFile.ReadToEnd());
                        rawPlaintext = File.ReadAllBytes(txtIn.Text);
                        cs.Write(rawPlaintext, 0, rawPlaintext.Length);

                    //}
                }
                cipherText = ms.ToArray();
                File.WriteAllBytes(txtOut.Text, cipherText);
            }
        }
        else
        {
            //using (FileStream fs = new FileStream(txtIn.Text, FileMode.CreateNew))
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
                {
                    //using (StreamReader myFile = new StreamReader(txtOut.Text))
                    //{
                        //string s = myFile.r.ReadToEnd();
                        rawPlaintext = File.ReadAllBytes(txtOut.Text); //System.Text.Encoding.ASCII.GetBytes(s);
                        //cipherText = new int[rawPlaintext.Length];
                        cs.Write(rawPlaintext, 0, rawPlaintext.Length);
                        //cs.Write(cipherText, 0, cipherText.Length);
                    //}
                }
                cipherText = ms.ToArray();
                File.WriteAllBytes(txtIn.Text, cipherText);
            }
        }
    }
    //string s = System.Text.Encoding.ASCII.GetString(plainText);
    //Console.WriteLine(s);
}

【问题讨论】:

  • msdn 有一个简单的示例:msdn.microsoft.com/en-us/library/…
  • 您希望我们阅读大量代码。
  • 以防万一其他人发现这很有用,vb 代码没有更改。我使用@HABO's post@Jon Skeet's post 让我的c# 可以处理大文件。
  • 在 Pre vista OS 上发现了另一个问题。如果您使用 SHA256,您需要使用“Microsoft Enhanced RSA and AES Cryptographic Provider”但是在 xp 上该提供程序不存在。您需要使用“Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)”并达到 SP3。 More Here

标签: c# vb6 cryptography encryption-symmetric


【解决方案1】:

您在此处的向量将产生与您预期不同的结果:

aes.IV = Encoding.ASCII.GetBytes("0000000000000000");

这将返回一个由 48 组成的字节数组,而不是 0。

您可以像这样简单地初始化一个字节数组:

aes.IV = new byte() {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

【讨论】:

  • 感谢语法。我不是 C# 程序员,它让我不必查找它。赞赏!
【解决方案2】:

在我看来,在 VB6 示例中,您指定了 CRYPT_NO_SALT,我相信这会导致未使用初始化向量。大概这都是零,但我不确定。

但是在 C# 代码中,您获取的 ASCII 文本“0000000000000000”的字节与数字零 { 0, 0, 0, 0, ... 0 } 作为字符的字节数组不同 ' 0' 等于 ASCII 中的数字 48(请参阅:http://www.asciitable.com/)。我认为这很可能是您的问题的根源。

【讨论】:

  • 对不起,我没有看到你的答案@Lummo。 +1 先回答。
  • 这有点尴尬。我想有时很难看到简单的错误。非常感谢!这就是问题所在。
猜你喜欢
  • 1970-01-01
  • 2011-07-14
  • 1970-01-01
  • 1970-01-01
  • 2023-01-31
  • 2013-07-25
  • 2020-12-03
  • 2014-03-20
相关资源
最近更新 更多