加密和解密序列化对象

时间:2015-04-12 23:26:31

标签: vb.net git encryption cryptography

好的,所以我正在尝试创建一个系统,我将字典序列化,然后对其进行加密,然后对其进行解密,然后恢复字典。

它还包括一些基于设置的选择语句,用户可以设置是否始终,从不或提示加密。

我一直在尝试跟随CryptoStream类文档,但由于某些原因,这不起作用。我认为加密可能有效,但文件比没有加密的.ser等级要小得多,所以我不知道。解密生成"尝试反序列化空流。"错误,这是非常自我解释,但我无法解决如何解决它。

备份和恢复无需加密即可正常工作。

以下是相关的子程序(以及GIT链接,如果它更容易),任何帮助将非常感谢!这是一个A Level计算项目,所以我不太关心加密的实际强度(真的不想开始使用散列和盐析),只是它有效。

加密备份:

Private Sub encryptBackup()
    Dim key As Byte()
    Dim IV As Byte() = New Byte() {}

    Using MD5 As New MD5CryptoServiceProvider
        Dim tmp = System.Text.Encoding.UTF8.GetBytes(InputBox("Please insert password:", "Password Input") & "This is most definitely not an obtuse amount of salt")
        key = MD5.ComputeHash(tmp)
        IV = MD5.ComputeHash(key)
    End Using
    Using cryptoRijndael = Rijndael.Create()

        Dim cryptoCryptor As ICryptoTransform = cryptoRijndael.CreateEncryptor(key, IV)
        Using fStream As New FileStream(fldBackupJobs & "\Backup Files\" & Strings.Replace(Strings.Replace(Now, ":", "_"), "/", ".") & ".bin", FileMode.OpenOrCreate), cStream As New CryptoStream(fStream, cryptoCryptor, CryptoStreamMode.Write)
            Dim Formatter As New BinaryFormatter
            Formatter.Serialize(cStream, photoJobs)
            MsgBox("Written to file")
        End Using
    End Using
End Sub

解密备份:

Private Sub decryptBackup(pathsStr As String)
    photoJobs = Nothing
    Dim key As Byte()
    Dim IV As Byte() = New Byte() {}
    Using MD5 As New MD5CryptoServiceProvider
        Dim tmp = System.Text.Encoding.UTF8.GetBytes(InputBox("Please insert password:", "Password Input") & "This is most definitely not an obtuse amount of salt")
        key = MD5.ComputeHash(tmp)
        IV = MD5.ComputeHash(key)
    End Using
    Using cryptoRijndael = Rijndael.Create()
        Dim cryptoCryptor As ICryptoTransform = cryptoRijndael.CreateEncryptor(key, IV)
        pathstr = OpenFileDialog.FileName
        Using fStream As New FileStream(pathstr, FileMode.Open), cStream As New CryptoStream(fStream, cryptoCryptor, CryptoStreamMode.Read)
            Dim Formatter As New BinaryFormatter
            photoJobs = CType(Formatter.Deserialize(cStream), Dictionary(Of String, PhotoJob))
            MsgBox("Backup Restored")
        End Using
    End Using
End Sub

GIT链接:https://github.com/hughesjs/Photo-Gift-Manager

提前致谢!!

1 个答案:

答案 0 :(得分:1)

代码的第一部分让我暂停,因为(超出GoTo)看起来密码方法依赖于文件扩展名。由于用户可以通过资源管理器进行更改,因此非常脆弱。并且不要让用户选择:如果需要加密,那就去做;如果没有,不要。当然,加密方法不应该由他们决定(我们为他们做出决定会花大价钱)。

使用我恰好有用的BindingList(of Animal)进行加密:

Dim key As Byte()
Dim iv As Byte() = New Byte() {}

' see notes below
Using MD5 As New MD5CryptoServiceProvider
    ' UTF8 not unicode; convert password to Byte()
    Dim tmp = Encoding.UTF8.GetBytes(password & "$*^!#" & password)
    ' hash the PW to get the crypto Key
    key = MD5.ComputeHash(tmp)
    ' hash the Key to get the IV
    iv = MD5.ComputeHash(key)
End Using

Using rijAlg = Rijndael.Create()

    ' Create cryptor using the Key and IV
    Dim cryptor As ICryptoTransform = rijAlg.CreateEncryptor(key, IV)

    ' Open a filestream for the output file, wrap it with
    ' a CryptoStream created with the cryptor in WRITE (output) mode
    Using fs As New FileStream("C:\Temp\crypto.bin", FileMode.OpenOrCreate),
       cs As New CryptoStream(fs, cryptor, CryptoStreamMode.Write)

        ' serialize collection to CryptoStream (to disk)
        Dim bf As New BinaryFormatter
        bf.Serialize(cs, mcol)
    End Using

End Using

要解密,请使用相同的密钥和IV:

mcol = Nothing

' the comments above pertain, just in reverse
Using rijAlg = Rijndael.Create()
    Dim cryptor As ICryptoTransform = rijAlg.CreateDecryptor(key, iv)
    Using fs As New FileStream("C:\Temp\crypto.bin", FileMode.Open),
       cs As New CryptoStream(fs, cryptor, CryptoStreamMode.Read)

        Dim bf As New BinaryFormatter
        ' Convert object to type
        mcol = CType(bf.Deserialize(cs), BindingList(Of Animal))
    End Using
End Using

' test:
For Each a As Animal In mcol
    Console.WriteLine(a.Name)
Next

我的所有动物都在旅途中幸存下来:

  

流动站
  小玩意儿
  Ziggy

主要的事情似乎是您使用了太多的流。在你的解密器中,你试图从一个与读取文件的cryptostream无关的memstream反序列化。事实上,它刚刚创建了这条线。 cryptostream基本上只包含你正在使用的“真实”流。

此外,此行显示您未使用Option Strict

photoJobs = formatter.Deserialize(memStreamSerial)

Deserialize返回一个对象,而photoJobs是来自过去帖子的某种集合IIRC。请注意,我的代码使用CType转换为BindingList(Of Animal)

使用Option Strict比'Hello,World`更复杂。总是。


加密注释/注意事项

从密码中导出(哈希)IV是一个坏主意:这些应该是独立的数据。对于每个数据(对于重用PW而言不是这种情况)和唯一的IV,IV应该是唯一的。我在PW中添加了一些任意文本,以便MD5哈希不是直接 PW派生的,但它仍然不是最理想的。

其次,MD5已经过时了。

创建随机IV

Private Const MinSize = 7
Public Shared Function GetRandomBytes(size As Integer) As Byte()
    ' dont allow less than a sensible min
    Dim data(If(size < MinSize, MinSize, size)) As Byte

    Using rng As New RNGCryptoServiceProvider
        ' fill the array 
        rng.GetNonZeroBytes(data)
    End Using
    Return data

End Function

将它放在加密工具库中,因为你将它用于IV以及Salt用于哈希。例如:

 myIV = CryptoUtils.GetRandomBytes(15)

如果IV每次都是唯一的,那么诀窍就是如何保存它,因此可以在解密中使用相同的值。 IV不必是秘密的,因此可以在将其传递给FileStream构造函数之前将其保存到CryptoStream。 Decrypt方法正好相反。

这些也可以制成方法,因此每次都使用相同的过程。


最后,如果问题更加简洁,您的问题将得到更好的接受。该错误清楚地表明了加密问题,因此前两个块的噪声或多或少。