6

I'm really not sure what's going on here. My app is encrypting files correctly and without issue, but it's throwing an IndexOutOfRangeException when trying to decrypt the same file...

Here's my code:

Public Sub EncryptDecrypt(ByVal Action As String, ByVal InFile As String, ByVal OutFile As String)
    Try
        Dim Buffer(4096) As Byte
        Dim Stream As CryptoStream
        Dim Rij As New System.Security.Cryptography.RijndaelManaged
        Dim Key(), IV() As Byte

        FSIn = New FileStream(InFile, FileMode.Open, FileAccess.Read)
        FSOut = New FileStream(OutFile, FileMode.OpenOrCreate, FileAccess.Write)
        FSOut.SetLength(0)

        Key = CreateKey("p0Ju423KQY7h4D29Ml536jbX7gS2Q6Rtm87XvRttlKiZ")
        IV = CreateIV("p0Ju423KQY7h4D29Ml536jbX7gS2Q6Rtm87XvRttlKiZ")

        If Action = "E" Then
            Stream = New CryptoStream(FSOut, Rij.CreateEncryptor(Key, IV), CryptoStreamMode.Write)
        Else
            Stream = New CryptoStream(FSOut, Rij.CreateDecryptor(Key, IV), CryptoStreamMode.Write)
        End If

        Stream.Close()
        FSIn.Close()
        FSOut.Close()
    Catch ex As Exception
        MsgBox(ex.ToString)
    End Try
End Sub

The error appears on the Stream.Close() line.
I have applied the same code elsewhere and it doesn't have any issues...

Here's my stack trace:

System.IndexOutOfRangeException was caught Message="Index was outside the bounds of the array."
Source="mscorlib" StackTrace: at System.Security.Cryptography.RijndaelManagedTransform.DecryptData(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount, Byte[]& outputBuffer, Int32 outputOffset, PaddingMode paddingMode, Boolean fLast) at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount) at System.Security.Cryptography.CryptoStream.FlushFinalBlock() at System.Security.Cryptography.CryptoStream.Dispose(Boolean disposing) at System.IO.Stream.Close() at Crypt.EncryptDecrypt(String Action, String InFile, String OutFile) in D:\Development\Projects\Web\WebSite1\App_Code\Crypt.vb:line 34 InnerException:

Any help will be greatly appreciated.

EDIT 1 After aaz's comment, I revised and replaced

Stream = New CryptoStream(FSOut, Rij.CreateDecryptor(Key, IV), CryptoStreamMode.Write)

with

Stream = New CryptoStream(FSIn, Rij.CreateDecryptor(Key, IV), CryptoStreamMode.Write)

Here's the resulting Stack Trace:

System.IndexOutOfRangeException was caught Message="Index was outside the bounds of the array." Source="mscorlib" StackTrace: at System.Security.Cryptography.RijndaelManagedTransform.DecryptData(Byte[] > inputBuffer, Int32 inputOffset, Int32 inputCount, Byte[]& outputBuffer, Int32 > outputOffset, PaddingMode paddingMode, Boolean fLast) at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(Byte[] > inputBuffer, Int32 inputOffset, Int32 inputCount) at System.Security.Cryptography.CryptoStream.FlushFinalBlock() at System.Security.Cryptography.CryptoStream.Dispose(Boolean disposing) at System.IO.Stream.Close() at Crypt.EncryptDecrypt(String Action, String InFile, String OutFile) in > D:\Development\Projects\Web\WebSite1\App_Code\Crypt.vb:line 34 InnerException:

Seems to me that its the same error...

END EDIT 1

Ortund
  • 8,095
  • 18
  • 71
  • 139
  • 1
    Is the code complete? It doesn't actually copy data from `FSIn` to `Stream`. – aaz Feb 16 '11 at 23:16
  • This is what confuses me... It works flawlessly in another application where I've used it. I'm fairly new to encryption though, so I'm just tinkering here and there. – Ortund Feb 16 '11 at 23:41

2 Answers2

1

Well I think there are a couple things that need to be fixed. For one It does not appear that the FSOut is ever actually used now that you have changed the FSOut to FSIn. You seem to be using one or the other but from the structure of the code I would think your intent was to take a file In and encrypt or decrypt the data to another file.

Consider starting from scratch on this one using http://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndael.aspx as a jumping off point and if your intent is for it to read from one file and write to another modify it as you see fit or consider having a helper method that creates a copy of the file in memory, encrypts the file, moves it and replaces the in memory file to the starting location, doing it this way allows u to leverage this code for either case and doesn't really incur much extra overhead.

Gent
  • 2,675
  • 1
  • 24
  • 34
  • You are 100% correct on what I seem to be doing. The idea is that a file will be decrypted when being read or written to, and encrypted when the read/write operation is complete. – Logan Young Feb 17 '11 at 18:07
0

CryptoStream emits PKCS#7-style padding at the end of the data, which may include anywhere from one byte to one complete cipher block but is never zero-length; this ensures both that the encrypted stream is a multiple of the block size in length, and that padding can be unambiguously removed. Is it possible you are attempting to decrypt something that is not valid encrypted data?

Jeffrey Hantin
  • 35,734
  • 7
  • 75
  • 94
  • Not likely since the `Stream = New CryptoStream(FSOut, Rij.CreateEncryptor(Key, IV), CryptoStreamMode.Write)` line that encrypts the original file executes without incident. – Logan Young Feb 17 '11 at 18:06
  • @Logan — It may execute, but how do you know it's working correctly? It looks like it is creating an empty file, which would give an error on decryption for the reason @Jeffrey described. – aaz Feb 17 '11 at 20:18