decrypting a batch of files

ram_son

Newcomer
Joined
Aug 7, 2007
Messages
13
I have been trying my hand at encrypting and decrypting files using vb.net and kind of succeded in encrypting and decrypting one file at a time. But I am having hard time decrypting 4 files that I need done before the form loads in an app. I am using a snippet that uses base64 that worked when I used
vb6; but I am new to vb.net and have not been able to do it. In the program I am only interested in decoding the files. So let's say I have four files that I encoded using base64 with the password "abc" and now have four files a.enc, b.enc, c.enc,and d.enc that are in the prg dir. I would like to decode them back to text files to a temp directory (C:\temp) and use them till the program is stopped.What parts of the code do I need in the program and do I get all four files decoded. It's not like I haven't tried but the best I did was end up with four files with different names but same content. Any assistance will be appreciated.
 
Without seeing the code you have so far it is hard to say exactly what changes you should be making ;)

Just out of interest are the files encrypted and then converted to Base64 as Base64 itself isn't a form of encryption - it is just a means of encoding binary files in an ASCII form.
 
This is what I am using right now.Like I said I am not sure if what I am doing is remotely the correct way to do this. The files are already encoded using a utility that uses the same code snippet. So I have the DecodeToByte and DecodeFile functions in the form like this:
Function DecodeToByte(ByVal enc As String) As Byte()
Dim bt() As Byte

bt = System.Convert.FromBase64String(enc)

Return bt

End Function

Sub DecodeFile(ByVal srcFile As String, ByVal destFile As String)
Dim src As String
Dim sr As New IO.StreamReader(srcFile)

src = sr.ReadToEnd

sr.Close()

Dim bt64 As Byte() = DecodeToByte(src)

If IO.File.Exists(destFile) Then
IO.File.Delete(destFile)
End If

Dim sw As New IO.FileStream(destFile, IO.FileMode.CreateNew)

sw.Write(bt64, 0, bt64.Length)

sw.Close()

End Sub

Then I want to decode the files to text files and have them displayed as the text in 4 labels; so I am trying this:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Dim destfile1 As String = "c:\temp\a1.txt"

Dim srcfile1 As String = "F:\a1.enc"


Dim src1 As String = "a1.enc"
Dim sr1 As New IO.StreamReader(srcfile3)

src1 = sr1.ReadToEnd

sr1.Close()

DecodeToByte(src1)
64 = DecodeToByte(src1)
Dim bt64 As Byte() = DecodeToByte(src1)

If IO.File.Exists(destfile1) Then
IO.File.Delete(destfile1)
End If

Dim sw1 As New IO.FileStream(destfile1, IO.FileMode.CreateNew)

sw1.Write(bt64, 0, bt64.Length)

sw1.Close()

FileClose()
I repeat this four times for the four different files by changing everywhere there is the figure 1 to 2 ,then 3 and 4, so that it is pointing to the second file "a2.enc", "a2.txt" and "srcFile2" and "destFile2" and so on.What I get is 4 files in C:\temp (a1.txt thru a4.txt) but their contents are the same as the first.
So how do they all end up with the same content? I hope this makes it easier to understand what I am trying to do. Needless to say any help would be greatly appreciated.
 
I was working on the encryption outside of the project and have messed it up since then.. I'll definitely see if I can get it back where it was and then post and attach the files. In the meantime do you see anything wrong with the code above that would make the contents of the files be the same even though they are totally different originally. Is this code actually giving the instructions to write "a1.txt" and when done stop and start writing a new file named "a2.txt"; or is it writing and then overwriting with the contents of the first file? It might take a little while to get these files ready but I'll definitely post again ... Thanks
 
I tried to duplicate what happens in these files I am uploading.However, now I cannot even get the text to be displayed in the labels, but you can see how the four *.enc files are all decoded with the same content inside the application directory. I encoded them with a utility that doesn't even ask for a password which I have to also fix. Please take a look at this and let me know how much of a mess it is.
 

Attachments

Last edited by a moderator:
Base64 is not encryption

Why don't you use your DecodeFile method? It clearly works:

Visual Basic:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    DecodeFile("a1.enc", "a1.txt")
    DecodeFile("a2.enc", "a2.txt")
    DecodeFile("a3.enc", "a3.txt")
    DecodeFile("a4.enc", "a4.txt")

    'Load labels here
End Sub

As for the label loading part, you could put that into its own method as well, to avoid all the repeated code.

I encoded them with a utility that doesn't even ask for a password which I have to also fix.

As PlausiblyDamp mentioned above, Base64 is an encoding scheme, not an encryption scheme, so cannot be made to use a password. If you want the files to be encrypted you should use classes in the System.Security.Cryptography namespace. Also, decrypting files and storing their contents in an unencrypted file is a gaping security hole and makes the whole encryption process pointless. Once the contents of the files has been decrypted I suggest it is stored in program variables. Finally, if you do password-protect your encrypted files, I suggest you do not place the password plainly in the code as this is easy to discover just by opening the program in a text editor or a disassembler.

Good luck :)
 
Re: Base64 is not encryption

Thanks MrPaul.. I knew it would have to be something that simple. I actually got the same results by creating a module with the decode procedure and then calling it during form load similar to what you have suggested. I still don't know what was making the four files get decoded with the same content though. Obvously, I am just a beginner when it comes to programming, especially wth vb.net, and have to ask you how could I do that when it comes to using classes.

I would actually much rather have he files encrypted with a password but when the program runs it needs to access the files as text in order to display the content in the labels. Is there a way of doing that without decrypting or decoding the files. Could the files be stored in memory as text and accessed there instead of in temporary files or would that slow down the process considerably.
Thanks again for your help.
 
Not writing to file

I still don't know what was making the four files get decoded with the same content though.

Sorry for not explaining that. The problem was that you were not assigning the decoded data to the variable before you wrote it to the file:

Visual Basic:
'For file 1
Dim bt64 As Byte() = DecodeToByte(src1)
'...
sw1.Write(bt64, 0, bt64.Length)

'For file 2
DecodeToByte(src2)
'...
sw2.Write(bt64, 0, bt64.Length)

Notice the difference? With the first file the decoded data is assigned to variable bt64 which is then written to the file, but with the second file it is not assigned, so the bt64 variable still contains the data from the first file, which is then written again - same with the third and fourth files. The solution is therefore to assign the return value of DecodeToByte to the variable bt64:

Visual Basic:
bt64 = DecodeToByte(src2)
'...
bt64 = DecodeToByte(src3)
'...
bt64 = DecodeToByte(src4)

Could the files be stored in memory as text and accessed there instead of in temporary files or would that slow down the process considerably.

Yes they could, and with files this size there is barely any overhead at all - it certainly wouldn't slow anything down. After using DecodeToByte to obtain the file contents, you would then convert the byte data to a string which can be manipulated as needed:

Visual Basic:
'Decode file from base64
Dim bt64 As Byte() = DecodeToByte(src1)

'Convert byte data into a string
Dim fileData As String = Encoding.Default.GetString(bt64)

'Split string into individual lines
Dim fileLines As String() = fileData.Split(ControlChars.CrLf)

'Set label text to appropriate line
Label1.Text = fileLines(index1)

Good luck :cool:
 
Re: Not writing to file

Now I understand where the problem was...Thanks for explaining that . As far as storing the files into memory I'm going to try that and see how it works since the actual files are quite a bit larger than the sample files-- they run around 1400 lines each.. I'll see if I can get it working and will post the results. Please keep checking as I might need some more help. I really appreciate your help and patience.
 
Re: Not writing to file

I tried the code for storing the files into memory and had partial success.I worked first with the sample files and after some trouble succeeded in getting the lablels to display the number "10" in each which is the index number in each file.Then I replaced the sample files with the actual files to be used and got the index numer of "1400" in the labels. Judging by the speed of the files being decoded and loaded it doesn't seem like it would cause any trouble. So I think the idea is excellent.
But where I ran into trouble is the procedure of skipping the first line of index numbers and then using a button to move from one line to the next.Originally I was using a routine to load the labels that relied on "line_number1" and "line_value1()"; so I substituted "line_value1()" for "filelines" but when I click the next button I get an error "object reference not set for an instance of an object" at

Label1.text = line_value1(index1)

The question is then is this the right thing to do using line_value1 to replace filelines and is this problem related to the fact that the index number are displayed in the labels instead of the first line of the content.Any suggestions?
 
Zero based indexing

If you want to use the line_value1 variable instead of fileLines that's fine, but you must change it where I have used fileLines in my code, so that it reads:

Visual Basic:
line_value1 = fileData.Split(ControlChars.CrLf)

Label1.Text = line_value1(index1)

The reason the number 1400 is appearing is that the text "1400" is the first line in the file and so will be the first item in the line_value1 array - if you set index1 to 1 then you'll get the next line, 2 for the third line etc. Remember arrays in VB.Net are zero based, so the first item ("1400") is at index 0.

:)
 
Re: Zero based indexing

I did that and I get an error that "the path is too long after being fully qualified.Make sure path is less than 260 characters." where I open the file:
Dim i As Integer
Dim line_input(1) As String
Dim FILE_NAME1 As String = fileData1
'Dim line_value1 As String
FileOpen(1, FILE_NAME1, OpenMode.Input) <<error points here
Input(1, line_number1)

For i = 1 To 1326
Input(1, line_value1(i))
Next i
The intellisense shows the contents of the decoded file at the spot of the error!! Do I have control over the path?
 
No need for file handling

The code I posted previously was meant to replace the file handling, since the variable fileLines (or line_value1 if you prefer) already contains the entire file, separated into lines. You can then access an individual line of the file using its index:

Visual Basic:
'Decode file from base64
Dim bt64 As Byte() = DecodeToByte(src1)
Dim fileData As String = Encoding.Default.GetString(bt64)
Dim line_value1 As String() = fileData.Split(ControlChars.CrLf)

'At this point in the code, line_value1 is an array containing the entire
'decoded contents of the first file, each element of the array corresponding
'to one line in the file. We can therefore access any line in the file by
'using an index value, starting from 0 (the first line). There is no need for
'ANY further file handling after this point!

'First item of line_value1 contains the number
line_number1 = Integer.Parse(line_value1(0))

'Set label text to appropriate line
Label1.Text = line_value1(index1)
 
Re: No need for file handling

I still need a routine for the "next" button, right? This is what I had before
Dim i As Integer
Dim clickcount As Integer

If index1 < 1323 Then
index1 = index1 + 1
Else
MsgBox("This is the last record of the data")
End If
Label1.Text = line_value1(index1)
Label2.Text = line_value2(index1)
Label3.Text = line_value3(index1)
Label4.Text = line_value4(index1)
When I click the next button now I get an unhandled exception error(object not set to an instance of an object.
 
Populate other variables

You need to instantiate and populate the variables line_value2, line_value3 and line_value4 in the same way that you did for line_value1.

Visual Basic:
bt64 = DecodeToByte(src2)
fileData = Encoding.Default.GetString(bt64)
line_value2 = fileData.Split(ControlChars.CrLf)

bt64 = DecodeToByte(src3)
fileData = Encoding.Default.GetString(bt64)
line_value3 = fileData.Split(ControlChars.CrLf)

bt64 = DecodeToByte(src4)
fileData = Encoding.Default.GetString(bt64)
line_value4 = fileData.Split(ControlChars.CrLf)

For future reference, when an exception occurs, Visual Studio will break into the debugger so you can see exactly what line the exception occured on, and then by hovering the mouse over variables you can tell which one has not been instantiated (is set to Nothing).
 
Re: Populate other variables

I already have done that (I'm learning!!) and got the labels populated but the next button doesn't seem to work. I got it working by having the decoding done in the buttons for next and previous procedures followed by the next and previous click functions. In other words the text doesn't appear in the labels until I hit the next button and keeps moving to the next line with every click.Then I use the previous button to go backwards.It seems to work ok, so if there is no harm I guess it should be alright.
If I use the form load event it loads the labels but doesn't move on to the next record.
 
Re: Populate other variables

Mr Paul... I really want to thank you for all the help and guidance and patience that you demonstrated. I learned quite a bit and hope to learn a lot more practical programming stuff from people like yourself -- in addition to the tutorials of course. I have to say that it is knowledgeable and helpful members like you who make these forums worth visiting.
BTW you did mention something about not placing the password plainly in the code, but you didn't suggest alternatives. Do you have any advice on this topic?
 
Encryption

BTW you did mention something about not placing the password plainly in the code, but you didn't suggest alternatives. Do you have any advice on this topic?

I suppose it depends why you need the encryption in the first place. For example, you might request that the user enters the password - if the application is going to display the contents of the files then encrypting them is fairly pointless if anyone can just open the application, right?

As for placing a password in code, there are practically infinite ways you could go about it, depending on how much you want to hide it. For example, a very poor system might be to store the password backwards, then reverse it before decrypting the files:

Visual Basic:
Const storedPassword As String = "drowssap"
realPassword = storedPassword.Reverse()

Other techniques might involve jumbling the characters in the password, and then unjumbling them before decrypting:

Visual Basic:
Const storedPassword As String = "sopwrsad"
realPassword = storedPassword(2) & storedPassword(6) & _
               storedPassword(0) & storedPassword(5) & _
               storedPassword(3) & storedPassword(1) & _
               storedPassword(4) & storedPassword(7)

Maybe using two constants to store the password then combining them:

Visual Basic:
Const firstPassword As String = "pswr"
Const secondPassword As String = "asod"

realPassword = String.Empty
For i As Integer = 0 To firstPassword.Length - 1
    realPassword &= firstPassword(i) & secondPassword(i)
Next

Slightly more advanced approaches might also involve enciphering the password:

Visual Basic:
Const filePassword As String = "qbttxpse"

realPassword = String.Empty
For i As Integer = 0 To filePassword.Length - 1
    realPassword &= Chr(Asc(filePassword(i)) - 1)
Next

And of course you could combine these techniques. Bear in mind that no matter what you do, the password can be discovered by anyone using an MSIL disassembler and then stepping through your code.

Good luck :)
 
Re: Encryption

The idea of the password is just to make it a little harder to get at the contents of the files. The solution of storing the files in memory is excellent because the files don't exist as text even temporarily. So the way I have things right now, the text files exist in the encoded state; you raised the point that encryption with a password might be safer. So I am looking for an encryption/ decryption routine instead of the encoding/ decoding one as this makes it a little harder to decrypt the files.
Another question would an obfuscator prevent an MSIL disassembler from taking the code apart?
 
Back
Top