1

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

我尝试只初始化一次加密流,但随后我的编码崩溃了,因为加密流的 canwrite 属性在第一次写入加密流后变为 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
4

1 回答 1

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

我进行了这些基本更改以使其正常工作:

  • 创建一个解密器
  • 正确管理缓冲区和流(请参阅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
于 2011-02-26T01:19:44.240 回答