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

发布于 2024-10-19 05:07:06 字数 2518 浏览 1 评论 0原文

我正在尝试让 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

I'm trying to make rijndael work in CBC mode. I'm not exactly sure how should I do it. I think problem in my current code is that the stream is initialized every time in the beginning of encryption, so no avalanche effect occurs (same data is encrypted twice and the output of those two encryption is the same which it should not be).

I tried to initialize the cryptostream only once but then my coded crashed because the canwrite property of cryptostream goes to false after the first write to the cryptostream.

Here is the code what I have now:


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

and the conversion function to convert an array to string


 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

This is what I need:

    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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

无需解释 2024-10-26 05:07:06

试试这个:

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

Try this:

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

I made these basic changes to get it to work:

  • create a Decryptor
  • properly manage buffers and streams (see the Using clauses I added)

I also re-organized a little, and modified your code slightly to use a constant IV (all zeros) and use a constant key. This is so that you can get repeatable results from one run to the next. In a real app you would use a randomized IV and use a password-derived key. (See Rfc2898DeriveBytes)


ok, that allows the code to compile. I think you want to see the effect of chaining. That is not so easy, but maybe something like this will show you what you want to see:

        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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文