Question Encrypt a part of a file

czeslaw1

Member
Joined
May 18, 2009
Messages
18
Programming Experience
Beginner
Hi! I need your help! This is breaking my head! I'm new in Visual Basic 2005... I used to programme in VB6 and this is very different.. well...
I need to encrypt only a part of a file (a binary file), the first 140 kb for example... I'm trying but the resulting file (encrypted) has 16 bytes more,
This is what I want...

I have a file with text for ex. (but I want to do this with binary files, zip, exe, pdf...):

....here the 140byte
123456789012345678901234567890 (...) 01234567890123456789012345678...
After de encryption....here the 140byte
FJSDK04934983FM43LF3093F303F43 (...) DJLFKF44301234567890123456789...
I've tried with this code, I used some code I found to encrypt 100% a file, but I cant adapte it ;(

VB.NET:
  Private Sub EncryptOrDecryptFile(ByVal strInputFile As String, _
                                     ByVal strOutputFile As String, _
                                     ByVal bytKey() As Byte, _
                                     ByVal bytIV() As Byte, _
                                     ByVal Direction As CryptoAction)
       
       
           fsInput = New System.IO.FileStream(strInputFile, FileMode.Open, _
                                           FileAccess.Read)
        fsOutput = New System.IO.FileStream(strOutputFile, FileMode.OpenOrCreate, _
                                            FileAccess.Write)
        fsOutput.SetLength(0) 'make sure fsOutput is empty
 
        'Declare variables for encrypt/decrypt process.
        Dim bytBuffer(4096) As Byte 'holds a block of bytes for processing
        Dim lngBytesProcessed As Long = 0 'running count of bytes processed
        Dim lngFileLength As Long = fsInput.Length 'the input file's length
        Dim intBytesInCurrentBlock As Integer 'current bytes being processed
        Dim csCryptoStream As CryptoStream
        'Declare your CryptoServiceProvider.
        Dim cspRijndael As New System.Security.Cryptography.RijndaelManaged
        'Setup Progress Bar
        pbStatus.Value = 0
        pbStatus.Maximum = 100
         'Determine if ecryption or decryption and setup CryptoStream.
        Select Case Direction
            Case CryptoAction.ActionEncrypt
                csCryptoStream = New CryptoStream(fsOutput, _
                cspRijndael.CreateEncryptor(bytKey, bytIV), _
                CryptoStreamMode.Write)
             Case CryptoAction.ActionDecrypt
                csCryptoStream = New CryptoStream(fsOutput, _
                cspRijndael.CreateDecryptor(bytKey, bytIV), _
                CryptoStreamMode.Write)
        End Select
         'Use While to loop until all of the file is processed.
        Dim pfinish As Boolean
        pfinish = False
        Dim pcounter As Integer
        pcounter = 0
        While (lngBytesProcessed < lngFileLength) And (pfinish = False)
            'Read file with the input filestream.
            intBytesInCurrentBlock = fsInput.Read(bytBuffer, 0, 4096)
             'Write output file with the cryptostream.
            If (pcounter < 33) Then 'With this I only encrypt the first 33*4096 bytes.. near 140 bytes...
' it doesn't matter if its the 140 first bytes, or 100, but I mean the first bytes, to make useless the file...
                csCryptoStream.Write(bytBuffer, 0, intBytesInCurrentBlock)

            Else
                csCryptoStream.Close()
                fsInput.Close()
                fsOutput.Close()

                Dim leo As New System.IO.FileStream(strInputFile, FileMode.Open)

                Dim matriz(CInt(lngFileLength)) As Byte
                Dim matriz2(CInt(lngFileLength)) As Byte
                leo.Read(matriz, 0, CInt(lngFileLength))
                Dim algo As New System.IO.FileStream(strOutputFile, FileMode.Append)
                algo.Write(matriz, 0, CInt(lngFileLength) - (33 * 4096))
                pfinish = True
            End If
            'Update lngBytesProcessed
            lngBytesProcessed = lngBytesProcessed + CLng(intBytesInCurrentBlock)
            'Update Progress Bar
            pbStatus.Value = CInt((lngBytesProcessed / lngFileLength) * 100)
            contador = contador + 1

        End While

        'Close FileStreams and CryptoStream.
        csCryptoStream.Close()
        fsInput.Close()
        fsOutput.Close()

        'If encrypting then delete the original unencrypted file.
        If Direction = CryptoAction.ActionEncrypt Then
            Dim fileOriginal As New FileInfo(strFileToEncrypt)
            fileOriginal.Delete()
        End If

        'If decrypting then delete the encrypted file.
        If Direction = CryptoAction.ActionDecrypt Then
            Dim fileEncrypted As New FileInfo(strFileToDecrypt)
            fileEncrypted.Delete()
        End If

        'Update the user when the file is done.
        Dim Wrap As String = Chr(13) + Chr(10)
        If Direction = CryptoAction.ActionEncrypt Then
            MsgBox("Encryption Complete" + Wrap + Wrap + _
                    "Total bytes processed = " + _
                    lngBytesProcessed.ToString, _
                    MsgBoxStyle.Information, "Done")

            'Update the progress bar and textboxes.
            pbStatus.Value = 0
            txtFileToEncrypt.Text = "Click Browse to load file."
            txtPassEncrypt.Text = ""
            txtConPassEncrypt.Text = ""
            txtDestinationEncrypt.Text = ""
            btnChangeEncrypt.Enabled = False
            btnEncrypt.Enabled = False

        Else
            'Update the user when the file is done.
            MsgBox("Decryption Complete" + Wrap + Wrap + _
                   "Total bytes processed = " + _
                    lngBytesProcessed.ToString, _
                    MsgBoxStyle.Information, "Done")

            'Update the progress bar and textboxes.
            pbStatus.Value = 0
            txtFileToDecrypt.Text = "Click Browse to load file."
            txtPassDecrypt.Text = ""
            txtConPassDecrypt.Text = ""
            txtDestinationDecrypt.Text = ""
            btnChangeDecrypt.Enabled = False
            btnDecrypt.Enabled = False
        End If


        'Catch file not found error.
        '   Catch When Err.Number = 53 'if file not found
        'MsgBox("Please check to make sure the path and filename" + _
        '       "are correct and if the file exists.", _
        '        MsgBoxStyle.Exclamation, "Invalid Path or Filename")

        'Catch all other errors. And delete partial files.
        '  Catch
        fsInput.Close()
        fsOutput.Close()

        If Direction = CryptoAction.ActionDecrypt Then
            Dim fileDelete As New FileInfo(txtDestinationDecrypt.Text)
            fileDelete.Delete()
            pbStatus.Value = 0
            txtPassDecrypt.Text = ""
            txtConPassDecrypt.Text = ""

            MsgBox("Please check to make sure that you entered the correct" + _
                    "password.", MsgBoxStyle.Exclamation, "Invalid Password")
        Else
            Dim fileDelete As New FileInfo(txtDestinationEncrypt.Text)
            fileDelete.Delete()

            pbStatus.Value = 0
            txtPassEncrypt.Text = ""
            txtConPassEncrypt.Text = ""
            MsgBox(Err.Description)
            MsgBox("This file cannot be encrypted.", _
                    MsgBoxStyle.Exclamation, "Invalid File")

        End If

        '   End Try
    End Sub


Thank you very much!!!!
 
Last edited by a moderator:
Hi, please edit your post and put the code in code tags
VB.NET:
[code ]Your code goes here[/code ]
Without the spaces before the ]
Its difficult to read in its current form, which means people are less likely to help you.
 
Umm... Ok I don't think you needed to repost it, the new post you did was fine.
I'm just going through the code at the moment, although I have to admit at the moment nothings jumping out at me.

Although one quick note you appear to try and close the two FileStreams three times (that wont cause an error but its unnecessary code).
 
Try changing the loop to this;
VB.NET:
        While (lngBytesProcessed < lngFileLength)
            'Read file with the input filestream.
            intBytesInCurrentBlock = fsInput.Read(bytBuffer, 0, 4096)
            'Write output file with the cryptostream.
            If (contador < 33) Then 'with this IF, I only encrypt the 4096 * 33 first bytes, but it doesn't matter if its exactly 
                'that amount, I mean that I need to make useless the file fastly, so I encrypt the first bytes only...
                csCryptoStream.Write(bytBuffer, 0, intBytesInCurrentBlock)
            Else
                fsOutput.Write(bytBuffer, 0, intBytesInCurrentBlock)
            End If
            'Update lngBytesProcessed
            lngBytesProcessed = lngBytesProcessed + CLng(intBytesInCurrentBlock)
            'Update Progress Bar
            pbStatus.Value = CInt((lngBytesProcessed / lngFileLength) * 100)
            contador = contador + 1
        End While

It looked like you was trying to write out the input file a second time, instead of just adding the rest of the file to the end unencrypted.

Let me know if this works.
 
After encryption output length probably will be different to input length, so you should encrypt that to memory and note the final length, perhaps prepend that info to output file. When decrypting you can extract the encrypted part, which you now know the length of, decrypt it, and prepend to unencrypted part. Here's some sample code:
VB.NET:
Sub EncryptPart(ByVal sourcepath As String, ByVal targetpath As String, ByVal pass As String)
    Using source As New IO.FileStream(sourcepath, FileMode.Open, FileAccess.Read)
        'encrypt part
        Dim b((1024 * 33) - 1) As Byte
        Dim read As Integer = source.Read(b, 0, b.Length)
        Dim r As RijndaelManaged = GetRijndael(pass)
        Using enc As ICryptoTransform = r.CreateEncryptor
            b = enc.TransformFinalBlock(b, 0, read)
        End Using
        r.Clear()
        ' write contents to target (encrypted length + encrypted + non-encrypted)
        Using target As New IO.FileStream(targetpath, FileMode.Create, FileAccess.Write)
            Dim bLength() As Byte = BitConverter.GetBytes(b.Length)
            target.Write(bLength, 0, 4)
            target.Write(b, 0, b.Length)
            CopyStream(source, target)
        End Using
    End Using
End Sub
VB.NET:
Sub DecryptPart(ByVal sourcepath As String, ByVal targetpath As String, ByVal pass As String)
    Using source As New IO.FileStream(sourcepath, FileMode.Open, FileAccess.Read)
        'get encrypted length
        Dim b(3) As Byte
        source.Read(b, 0, 4)
        Dim encryptedLength As Integer = BitConverter.ToInt32(b, 0)
        'decrypt part
        ReDim b(encryptedLength - 1)
        source.Read(b, 0, b.Length)
        Dim r As RijndaelManaged = GetRijndael(pass)
        Using enc As ICryptoTransform = r.CreateDecryptor
            b = enc.TransformFinalBlock(b, 0, b.Length)
        End Using
        r.Clear()
        'write contents to target (decrypted + non-encrypted)
        Using target As New IO.FileStream(targetpath, FileMode.Create, FileAccess.Write)
            target.Write(b, 0, b.Length)
            CopyStream(source, target)
        End Using
    End Using
VB.NET:
Function GetRijndael(ByVal pass As String) As RijndaelManaged
    Dim r As New RijndaelManaged
    Dim der As New Rfc2898DeriveBytes(pass, System.Text.Encoding.Unicode.GetBytes(pass))
    r.Key = der.GetBytes(r.KeySize \ 8)
    r.IV = der.GetBytes(r.BlockSize \ 8)
    Return r
End Function

Sub CopyStream(ByVal source As IO.Stream, ByVal target As IO.Stream)
    Dim b(4095) As Byte, read As Integer = -1
    Do Until read = 0
        read = source.Read(b, 0, b.Length)
        target.Write(b, 0, read)
    Loop
End Sub
usage sample:
VB.NET:
EncryptPart("calc.exe", "calcenc.exe", "pass")
IO.File.Delete("calc.exe")
DecryptPart("calcenc.exe", "calc.exe", "pass")
IO.File.Delete("calcenc.exe")
 
Satal Keto! I tried your code, it seems good,, but in the part of the "IF 33" the algorithm eats 16 bytes, and also 16 bytes appear at the end...
For example
1........2........3........4........5........6........789... 30 31 32 33 34 35 36....100 101
ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKL...CDEFGHIJKBCDEFGHIJK....ABCDEFG#$%&/(?&%$%&¬/&%<--16 EXTRA BYTES
..................................................................................#UP AREN'T THE 16 LOST BYTES (HIJKB
I'VE TRIED, BUT I CANT MAKE IT WORK...
 
Back
Top