I have a library I wrote a while back that uses the same logic as the class code below, but when it decrypts a file, it decrypts it onto the disc, and give an option to delete the encrypted version or not. I'm trying to add an option to decrypt the file into memory so I can capture the file as a byte() and send the bytes to a service. I can obviously decrypt the file onto disc, read the file stream, convert it to byte(), delete the decrypted version (because I have to keep the files on disc encrypted).... creating a deleting files over and over again, can cause disc fragmentation, among other things, so I would like to just decrypt the file into memory. Anways, this successfully decrypts the file into the memorystream variable, but when I dumb the bytes into the file viewer, it tells me the file format is not recognized. Does anyone know what I'm doing wrong here?
Here's the code I have so far:
Public Class EncryptionFactory
Private Shared fsInput As FileStream
Public Shared Function GetDecryptedFile(ByVal password As String, ByVal encryptedFilePath As String) As Byte()
Return DecryptFile(encryptedFilePath, Key(password), IV(password))
End Function
Private Shared Function DecryptFile(ByVal strInputFile As String, ByVal bytKey As Byte(), ByVal bytIV As Byte()) As Byte()
fsInput = New FileStream(strInputFile, FileMode.Open, FileAccess.Read)
Dim memoryStream As MemoryStream
memoryStream = New MemoryStream()
Dim array As Byte() = New Byte(&H1001 - 1) {}
Dim num2 As Long = 0
Dim length As Long = fsInput.Length
Dim managed As New RijndaelManaged
Dim stream As New CryptoStream(memoryStream, managed.CreateDecryptor(bytKey, bytIV), CryptoStreamMode.Write)
Do While (num2 < length)
Dim count As Integer = fsInput.Read(array, 0, &H1000)
stream.Write(array, 0, count)
num2 = (num2 + count)
Loop
Dim data As Byte() = memoryStream.ToByte()
fsInput.Close()
fsInput.Dispose()
memoryStream.Close()
memoryStream.Dispose()
Return data
End Function
Private Shared Function Key(ByVal strPassword As String) As Byte()
Dim num5 As Integer
Dim chArray As Char() = strPassword.ToCharArray
Dim buffer As Byte() = New Byte((chArray.GetUpperBound(0) + 1) - 1) {}
Dim upperBound As Integer = chArray.GetUpperBound(0)
Dim i As Integer = 0
Do While (i <= upperBound)
buffer(i) = CByte(Strings.Asc(chArray(i)))
i += 1
Loop
Dim buffer3 As Byte() = New SHA512Managed().ComputeHash(buffer)
Dim buffer2 As Byte() = New Byte(&H20 - 1) {}
Dim index As Integer = 0
Do
buffer2(index) = buffer3(index)
index += 1
num5 = &H1F
Loop While (index <= num5)
Return buffer2
End Function
Private Shared Function IV(ByVal strPassword As String) As Byte()
Dim num5 As Integer
Dim chArray As Char() = strPassword.ToCharArray
Dim buffer As Byte() = New Byte((chArray.GetUpperBound(0) + 1) - 1) {}
Dim upperBound As Integer = chArray.GetUpperBound(0)
Dim i As Integer = 0
Do While (i <= upperBound)
buffer(i) = CByte(Strings.Asc(chArray(i)))
i += 1
Loop
Dim buffer3 As Byte() = New SHA512Managed().ComputeHash(buffer)
Dim buffer2 As Byte() = New Byte(&H10 - 1) {}
Dim index As Integer = &H20
Do
buffer2((index - &H20)) = buffer3(index)
index += 1
num5 = &H2F
Loop While (index <= num5)
Return buffer2
End Function
End Class
UPDATE:
I added the cryptostream.FlushFinalBlock()
this is still not working... I feel like it's just not reading the stream all the way to the end.
Private Shared Function DecryptFile(ByVal strInputFile As String, ByVal bytKey As Byte(), ByVal bytIV As Byte()) As Byte()
fsInput = New FileStream(strInputFile, FileMode.Open, FileAccess.Read)
Dim memoryStream As MemoryStream
memoryStream = New MemoryStream()
Dim array As Byte() = New Byte(&H1001 - 1) {}
Dim num2 As Long = 0
Dim length As Long = fsInput.Length
Dim managed As New RijndaelManaged
Dim stream As New CryptoStream(memoryStream, managed.CreateDecryptor(bytKey, bytIV), CryptoStreamMode.Write)
Do While (num2 < length)
Dim count As Integer = fsInput.Read(array, 0, &H1000)
stream.Write(array, 0, count)
num2 = (num2 + count)
Loop
stream.FlushFinalBlock()
Dim data As Byte() = memoryStream.ToByte()
fsInput.Close()
fsInput.Dispose()
memoryStream.Close()
memoryStream.Dispose()
Return data
End Function
UPDATE:
Here's in my "Encrypt" Method, using the same IV, and Key methods as the decrypt...
Friend Sub EncryptFile(ByVal strInputFile As String, ByVal strOutputFile As String, ByVal bytKey As Byte(), ByVal bytIV As Byte(), ByVal deleteOrig As Boolean)
Me.fsInput = New FileStream(strInputFile, FileMode.Open, FileAccess.Read)
Me.fsOutput = New FileStream(strOutputFile, FileMode.OpenOrCreate, FileAccess.Write)
Me.fsOutput.SetLength(0)
Dim array As Byte() = New Byte(&H1001 - 1) {}
Dim num2 As Long = 0
Dim length As Long = Me.fsInput.Length
Dim managed As New RijndaelManaged
Dim stream As New CryptoStream(Me.fsOutput, managed.CreateEncryptor(bytKey, bytIV), CryptoStreamMode.Write)
Do While (num2 < length)
Dim count As Integer = Me.fsInput.Read(array, 0, &H1000)
stream.Write(array, 0, count)
num2 = (num2 + count)
Loop
stream.Close
Me.fsInput.Close
Me.fsOutput.Close
If deleteOrig Then
Dim info As New FileInfo(strInputFile)
If ((info.Attributes And FileAttributes.ReadOnly) > 0) Then
info.Attributes = (info.Attributes Xor FileAttributes.ReadOnly)
File.Delete(strInputFile)
Else
info.Delete
End If
End If
End Sub
Final UPDATE:
Here's the decrypt file to memory code that was successful:
Private Shared Function DecryptFile(ByVal strInputFile As String, ByVal bytKey As Byte(), ByVal bytIV As Byte()) As Byte()
fsInput = New FileStream(strInputFile, FileMode.Open, FileAccess.Read)
Dim memoryStream As MemoryStream
memoryStream = New MemoryStream()
Dim array As Byte() = New Byte(&H1001 - 1) {}
Dim num2 As Long = 0
Dim length As Long = fsInput.Length
Dim managed As New RijndaelManaged
Dim stream As New CryptoStream(memoryStream, managed.CreateDecryptor(bytKey, bytIV), CryptoStreamMode.Write)
Do While (num2 < length)
Dim count As Integer = fsInput.Read(array, 0, &H1000)
stream.Write(array, 0, count)
num2 = (num2 + count)
Loop
stream.FlushFinalBlock()
stream.Dispose()
Dim data As Byte() = memoryStream.ToArray()
fsInput.Close()
fsInput.Dispose()
memoryStream.Close()
memoryStream.Dispose()
Return data
End Function
After you have finished writing all of the blocks, you need to call cryptoStream.FlushFinalBlock();
Off Topic: Here is an example of using to get the key and IV for your algorithm
private void SetAlgorithmKey(SymmetricAlgorithm algorithm, string password, string salt, int iterationCount)
{
byte[] saltBytes = string.IsNullOrEmpty(salt) ? new byte[0] : Encoding.ASCII.GetBytes(salt);
// The salt size must be 8 bytes or larger.
if (saltBytes.Length < 8)
{
byte[] newSaltBytes = new byte[8];
Array.Copy(saltBytes, newSaltBytes, saltBytes.Length);
for (int i = saltBytes.Length; i < 8; i++)
{
newSaltBytes[i] = 0; // pad with zeros?
}
saltBytes = newSaltBytes;
}
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(password, saltBytes, iterationCount);
algorithm.Key = pdb.GetBytes(algorithm.KeySize / 8);
algorithm.IV = pdb.GetBytes(algorithm.BlockSize / 8);
}