Encriptar y descifrar un object serializado

De acuerdo, entonces estoy intentando crear un sistema mediante el cual serializo un dictionary, luego lo encripto y luego puedo descifrarlo y luego restaurar el dictionary.

También incluye algunas declaraciones de selección basadas en una configuration en la que el usuario establece si desea siempre, nunca o solicitar el encryption.

He intentado seguir la documentation de CryptoStream Class, pero por alguna razón esto no funciona. Creo que el encryption podría estar funcionando, pero el file es mucho más pequeño que el equivalente de .ser no encriptado, así que no lo sé. El desencryption genera un "bash de deserializar una secuencia vacía". error, que es bastante explicativo, pero no puedo encontrar la manera de solucionarlo.

La copy de security y restauración funciona bien sin encryption.

Aquí están las subrutinas relevantes (y el enlace GIT si es más fácil) y cualquier ayuda sería muy apreciada. Esto es para un proyecto de computación de nivel A, por lo que no estoy demasiado preocupado acerca de la fortaleza real de la encriptación (realmente no quiero empezar a dar vueltas con el hashing Y el salazón), solo que funciona.

Encrypt Backup:

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 

Descifrar copy de security:

 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 Restonetworking") End Using End Using End Sub 

Y el enlace GIT: https://github.com/hughesjs/Photo-Gift-Manager

¡¡Gracias por adelantado!!

La primera parte del código me da pausa porque (más allá de GoTo ) parece que el método de encryption depende de la extensión del file. Dado que el usuario podría cambiar esto a través de Explorer, es muy frágil. Y no deje que el usuario elija: si es necesario encriptarlo, hágalo; si no, no. Ciertamente, el método de encriptación no debería depender de ellos (tenemos mucho dinero para tomar esas decisiones por ellos).

Cifrado usando aa BindingList(of Animal) que tengo a mano:

 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 

Para descifrar, use la misma key y 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 

Todos mis animales sobrevivieron al viaje:

Vagabundo
Gizmo
Ziggy

Lo principal parece ser que tienes demasiadas secuencias en uso. En su desencriptador está tratando de deserializar de un flujo de memory que no tiene nada que ver con la criptostream que lee el file. De hecho, se acaba de crear la línea anterior. Un cryptostream básicamente simplemente envuelve la stream "real" que está utilizando.

Además, esta línea muestra que no está utilizando Option Strict :

 photoJobs = formatter.Deserialize(memStreamSerial) 

Deserialize devuelve un object y photoJobs es una especie de colección IIRC de publicaciones anteriores. Tenga en count que mi código usa CType para convertir a BindingList(Of Animal) .

Use Option Strict para cualquier cosa más compleja que 'Hello, World`. Siempre.


Crypto Notes / Precauciones

Derivar (hash) la IV de la contraseña es una mala idea: estos deberían ser datos independientes. El IV debe ser único para cada dato (lo que no será el caso cuando se reutiliza un PW) y único. Agregué un text arbitrario al PW para que el hash MD5 no se derive directamente de él PW, pero aún es subóptimo.

En segundo lugar, MD5 está desactualizado.

Para crear un IV aleatorio

 Private Const MinSize = 7 Public Shanetworking 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 

Pon esto en una lib de herramientas de encryption porque lo usarás para IV así como para hashes de Sal. Ejemplo:

  myIV = CryptoUtils.GetRandomBytes(15) 

Si el IV es único cada vez, el truco es cómo savelo para que se puedan usar los mismos valores en el desencryption. El IV no necesita ser secreto, por lo que se puede save en FileStream antes de pasarlo al constructor de CryptoStream . El método Decrypt hace lo contrario.

Estos también se pueden convertir en methods, por lo que se usa el mismo process cada vez.


Finalmente, sus preguntas obtendrán una mejor recepción si fueran más concisas. El error indica claramente un problema de encryption, por lo que esos primeros 2 bloques son más o less ruidosos.