Decryption results in Bad Data

Hi Guys,

I need some help here.

I have a routine/code which encrypts a file based on a key and decrypts the file using the same key. Now I have had this routine for quite sometime now and it has worked flawlessly so far. Today while trying to decrypt a file an error occured. The file is similar to the other files I encrypt. Somehow I am unable to decrypt a particular file no matter what.

I am attaching two similar files, one which encrypts & decrypts fine and the other which encrypts ok but does not decrypt properly. I am stunned to be honest.

CODE : ENCRYPT

'create an 8-byte long array to hold the key 
    Private TheKey(7) As Byte ' it was public earlier
    'Stuff some random values into the vector: 
    Private Vector() As Byte = {&H12, &H44, &H16, &HEE, &H88, &H15, &HDD, &H41}

    Friend Sub Encrypt(ByVal inName As String, ByVal outName As String, ByVal key As String)
        Try
            CreateKey(key)
            Dim storage(4096) As Byte   'create buffer 
            Dim totalBytesWritten As Long = 8  'Keeps track of bytes written. 

            Dim packageSize As Integer   'Specifies the number of bytes written at one time. 

            'Declare the file streams. 
            Dim fin As New FileStream(inName, FileMode.Open, FileAccess.Read)
            Dim fout As New FileStream(outName, FileMode.OpenOrCreate, FileAccess.Write)
            fout.SetLength(0)

            Dim totalFileLength As Long = fin.Length  'Specifies the size of the source file. 

            'create the Crypto object 
            Dim des As New DESCryptoServiceProvider()

            Dim crStream As New CryptoStream(fout, des.CreateEncryptor(TheKey, Vector), CryptoStreamMode.Write)

            'flow the streams 
            While totalBytesWritten < totalFileLength
                packageSize = fin.Read(storage, 0, 4096)
                crStream.Write(storage, 0, packageSize)
                totalBytesWritten = Convert.ToInt32(totalBytesWritten + packageSize / des.BlockSize * des.BlockSize)
            End While

            crStream.Close()
            fin.Close()
            fout.Close()
        Catch e As Exception
            MsgBox(e.Message, MsgBoxStyle.Critical)
        End Try

    End Sub

Open in new window


CODE: DECRYPT

Friend Sub Decrypt(ByVal inName As String, ByVal outName As String, ByVal key As String, ByRef IsErr As Boolean)
        CreateKey(key)
        Dim storage(4096) As Byte
        Dim totalBytesWritten As Long = 8
        Dim packageSize As Integer
        Dim fin As New FileStream(inName, FileMode.Open, FileAccess.Read)
        Dim fout As New FileStream(outName, FileMode.OpenOrCreate, FileAccess.Write)
        fout.SetLength(0)
        Dim totalFileLength As Long = fin.Length
        Dim des As New DESCryptoServiceProvider()
        Dim crStream As New CryptoStream(fout, des.CreateDecryptor(TheKey, Vector), CryptoStreamMode.Write)

        Try
            While totalBytesWritten < totalFileLength
                packageSize = fin.Read(storage, 0, 4096)
                crStream.Write(storage, 0, packageSize)
                totalBytesWritten = Convert.ToInt32(totalBytesWritten + packageSize / des.BlockSize * des.BlockSize)
              End While
             
            crStream.FlushFinalBlock()  ' added lately  
            crStream.Close()
            fin.Close()
            fout.Close()
        Catch e As Exception
            IsErr = True
            fin.Close()
            fout.Close()
        End Try

    End Sub

Open in new window


COMMON FUNCTION CODE:

Private Sub CreateKey(ByVal strKey As String)

        ' Byte array to hold key 
        Dim arrByte(7) As Byte

        Dim AscEncod As New System.Text.ASCIIEncoding()
        Dim i As Integer = 0
        AscEncod.GetBytes(strKey, i, strKey.Length, arrByte, i)

        'Get the hash value of the password 
        Dim hashSha As New SHA1CryptoServiceProvider()
        Dim arrHash() As Byte = hashSha.ComputeHash(arrByte)

        'put the hash value into the key 
        For i = 0 To 7
            TheKey(i) = arrHash(i)
        Next i

    End Sub

Open in new window


You can call the functions to encrypt & decrypt a file like this:

 Call Encrypt("C:\fileOk.txt", "C:\FileOkEnc.dat", "key")
 Call Decrypt("C:\FileOKEnc.dat", "C:\fileOKdec.txt", "key", IsErr)

Open in new window


Try to encrypt and decrypt two very similar files. One is okay and in second one an error occurs while decrypting. I am unable to figure out why. This code has works well so far.

I did add flushfinalblock() after reading about it on the web but it didnt help either.

FileOK.txt & FileProblem.txt have been attached.

Thanks a lot,

Cheers,
Saurabh
FileOK.txt
FileProblem.txt
SukhaniAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Den_HBRCommented:
Why does totalBytesWritten starts at 8?

If I let them start at 0 it seems to work just fine.
SukhaniAuthor Commented:
Den_HBR : You are right. When I set it to zero it works okay. To be honest I had found this code on the web and it was 8 all along.
The problem is i have several files scattered which are encrypted using this routine with
totalBytesWritten= 8. Now if i change it to 0 I may have a problem decrypting those files properly.
TotalBytesWritten is 8 on both encrypt and decrypt. is this really the problem. I have so many files encrypted and decrypted with this, I never faced an issue until this file.
What should I do ?
Den_HBRCommented:
It is normal that your second file crashes if you start with totalBytesWritten = 8

The file is 12296 bytes long.

In your While loop your are checking

      8 < 12296 (= yes, so continue while)
4104 < 12296 (= yes, so continue while)
8200 <  12296 (= yes, so continue while)
12296 <  12296 (=NO! exit while)

While you should by doing

      0 < 12296 (= yes, so continue while)
4096< 12296 (= yes, so continue while)
8192 <  12296 (= yes, so continue while)
12288 <  12296 (= yes, so continue while)
12296 <  12296 (=NO! exit while)


You see the difference?
If you start at 8, an entire block is skipped!
If you start at 8 your program will always crash if totalFileLength MOD 8 < 8

Den_HBRCommented:
Sorry, I meant
If you start at 8 your program will always crash if totalFileLength MOD 4096 < 8

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
SukhaniAuthor Commented:
Right. Thanks a lot Den_HBR. I will change the routine.
I appreciate your help.
 
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.