如何使Rijndael CBC模式在vb.net中工作

如何使Rijndael CBC模式在vb.net中工作,vb.net,aes,rijndael,Vb.net,Aes,Rijndael,我想让rijndael在CBC模式下工作。我不确定该怎么做。我认为我当前代码中的问题是,流在每次加密开始时都被初始化,因此不会发生雪崩效应(相同的数据被加密两次,并且这两次加密的输出是相同的,而不应该是相同的) 我只尝试初始化加密流一次,但是我的代码崩溃了,因为加密流的canwrite属性在第一次写入加密流后变为false 以下是我现在拥有的代码: Sub Main() Dim rij As New RijndaelManaged Dim iv(15) As

我想让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
试试这个:

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

奇索,这并没有回答我的问题。如果我使用您的代码并执行“往返(明文1,密钥)”两次,加密文本是相同的,因为它是CBC模式,没有雪崩效应。(我用rijndael保护通讯)那么,我误解了这个问题。如果我理解你在评论中所说的话,你的假设是不正确的。您似乎认为在同一个应用程序中两次使用Rijndael将导致链接。这是不对的。这个应用程序中加密文本相同的原因是:您使用的是相同的IV、相同的密钥和相同的明文。要检查链接,需要使用相同的CryptoStream实例连续加密明文两次。即,初始化一次,然后对文本加密两次。第一个周期的加密文本将不同于第二个周期的加密文本。在pseudo中,它将如下所示:crypto object.init(key,iv)->encrypt(“hello”,crypto object)->encrypt(“hello”,crypto object)=>将产生不同的加密输出。(我不知道你是不是这个意思。)我就是做不到,如果我在代码中注释掉第二个cstream初始化,它就会崩溃为“stream不支持写入”错误。这是我试图解决的问题。我想你对.NET类的工作原理有误解。正如我上面所说的,您可以通过使用相同的加密流连续两次加密相同的明文来实现您想要的。你试过了吗?当我这样做时,我会得到不同的加密文本。根据设计,用两个独特的加密流实例加密相同的明文将产生相同的密文。如果它产生不同的密文,那将是非常糟糕的。我知道,我也尝试过:)是的,我知道加密流的两个独特实例将产生相同的密文。问题是我不知道如何使用相同的加密流两次。你能告诉我怎么做才能解决我的问题吗?你添加的最新代码不正确。
Using
子句对正在使用的对象调用Dispose()。调用Dispose()后无法重新使用该对象。要正确使用
Using
,请参阅下面我发布的代码。好的,如果我想重用cryptostream,实际上我不应该使用Using子句。我需要再次写入同一个加密流以获得链接效果,而using子句将处理坏的对象。
        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