如何让Rijndael CBC模式在vb.net中运行

时间:2011-02-23 21:35:59

标签: vb.net aes rijndael

我正在尝试让rijndael在CBC模式下工作。我不确定我该怎么做。我认为当前代码中的问题是每次在加密开始时都会初始化流,因此不会发生雪崩效应(相同的数据加密两次,这两种加密的输出是不相同的)。 / p>

我尝试初始化一次cryptostream但是我的编码崩溃了,因为cryptostream的canwrite属性在第一次写入cryptostream之后变为false。

以下是我现在的代码:


Sub Main()

        Dim rij As New RijndaelManaged
        Dim iv(15) As Byte
        Dim key(15) As Byte
        Dim secret() As Byte = {59, 60, 61}

        Dim cs As ICryptoTransform
        Dim cstream As CryptoStream

        Dim out() As Byte
        Dim NewRandom As New RNGCryptoServiceProvider()

        NewRandom.GetBytes(iv)
        NewRandom.GetBytes(key)

        rij = New RijndaelManaged()

        rij.KeySize = 128
        rij.Padding = PaddingMode.PKCS7

        rij.Mode = CipherMode.CBC

        rij.IV = iv
        rij.Key = key
        cs = rij.CreateEncryptor()

        Dim ms_in As New MemoryStream
        cstream = New CryptoStream(ms_in, cs, CryptoStreamMode.Write)


        Using cstream
            cstream.Write(secret, 0, 3)
        End Using

        out = ms_in.ToArray
        Console.WriteLine(ArrayToString(out, out.Length))
        Erase out

        ms_in = New MemoryStream
        cstream = New CryptoStream(ms_in, cs, CryptoStreamMode.Write)


        Using cstream
            cstream.Write(secret, 0, 3)
        End Using

        out = ms_in.ToArray
        Console.WriteLine(ArrayToString(out, out.Length))

    End Sub

以及将数组转换为字符串

的转换函数

 Public Function ArrayToString(ByVal bytes() As Byte, ByVal length As Integer) As String

        If bytes.Length = 0 Then Return String.Empty
        Dim sb As New System.Text.StringBuilder(length)

        Dim k As Integer = length - 1
        Dim i As Integer

        For i = 0 To k
            sb.Append(Chr(bytes(i)))
        Next


        Return sb.ToString()

    End Function

这就是我需要的:

    cs = rij.CreateEncryptor()
    Dim ms_in As New MemoryStream
    cstream = New CryptoStream(ms_in, cs, CryptoStreamMode.Write)

    Using cstream
        cstream.Write(secret, 0, 3) 'encrypt
    End Using

    out = ms_in.ToArray
    Console.WriteLine(ArrayToString(out, out.Length)) 'see the encrypted message
    Erase out

    Using cstream
        cstream.Write(secret, 0, 3) 'encrypt, this will crash here and this is the problem I'm trying to solve
    End Using

    out = ms_in.ToArray
    Console.WriteLine(ArrayToString(out, out.Length)) 'see the encrypted message this should not be the same as the first one

1 个答案:

答案 0 :(得分:0)

试试这个:

Public Sub Run()
    Dim key() As Byte = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}

    Dim plaintext1 As Byte() = {59, 60, 61}

    Dim plaintext2 As Byte() = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, _
                             0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, _
                             0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, _
                             0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 _
                             }

    Roundtrip(plaintext1, key)
    System.Console.WriteLine()
    Roundtrip(plaintext2, key)

End Sub


Public Sub Roundtrip(ByRef plaintext As Byte(), ByRef key As Byte())

    Dim rij As New RijndaelManaged
    Dim iv(15) As Byte

    Dim encryptor As ICryptoTransform
    Dim decryptor As ICryptoTransform

    Dim out() As Byte

    'Dim NewRandom As New RNGCryptoServiceProvider()
    'NewRandom.GetBytes(iv)
    'NewRandom.GetBytes(key)

    Console.WriteLine("Original:")
    Console.WriteLine(ArrayToString(plaintext))
    System.Console.WriteLine()

    rij = New RijndaelManaged()
    rij.KeySize = key.Length * 8  ' 16 byte key == 128 bits
    rij.Padding = PaddingMode.PKCS7
    rij.Mode = CipherMode.CBC
    rij.IV = iv
    rij.Key = key
    encryptor = rij.CreateEncryptor()

    Using msIn = New MemoryStream

        Using cstream = New CryptoStream(msIn, encryptor, CryptoStreamMode.Write)
            cstream.Write(plaintext, 0, plaintext.Length)
        End Using

        out = msIn.ToArray
        Console.WriteLine("Encrypted:")
        Console.WriteLine("{0}", ArrayToString(out))
        System.Console.WriteLine()

    End Using

    decryptor = rij.CreateDecryptor()
    Using msIn = New MemoryStream

        Using cstream = New CryptoStream(msIn, decryptor, CryptoStreamMode.Write)
            cstream.Write(out, 0, out.Length)
        End Using

        out = msIn.ToArray
        Console.WriteLine("Decrypted:  ")
        Console.WriteLine("{0}", ArrayToString(out))
        System.Console.WriteLine()

    End Using

End Sub


Public Shared Function ArrayToString(ByVal bytes As Byte()) As String

    Dim sb As New System.Text.StringBuilder()

    Dim i As Integer
    For i = 0 To bytes.Length-1
        if (i <> 0 AND i mod 16 = 0) Then
            sb.Append(Environment.NewLine)
        End If
        sb.Append(System.String.Format("{0:X2} ", bytes(i)))
    Next

    Return sb.ToString().Trim()

End Function

我做了这些基本的改动,让它发挥作用:

  • 创建一个Decryptor
  • 正确管理缓冲区和流(请参阅我添加的Using子句)

我也重新组织了一点,并稍微修改了你的代码以使用常量IV(全零)并使用常量键。这样您就可以从一次运行到下一次运行获得可重复的结果。在真实应用程序中,您将使用随机IV并使用密码派生密钥。 (见Rfc2898DeriveBytes


好的,这允许代码编译。我想你想看到链接的影响。这不是那么容易,但也许这样的事情会告诉你你想看到什么:

        For i As Integer = 1 To 2
            Using ms = New MemoryStream
                Using cstream = New CryptoStream(ms, encryptor, CryptoStreamMode.Write)
                    For j As Integer = 1 To i
                        cstream.Write(plaintext, 0, plaintext.Length)
                    Next j
                End Using
                out = ms.ToArray
                Console.WriteLine("Encrypted (cycle {0}):", i)
                Console.WriteLine("{0}", ArrayToString(out))
                System.Console.WriteLine()

            End Using
        Next i