Recipe 16.3. Encrypting and Decrypting a File


Problem

You want an easy-to-use function that encrypts and decrypts any file.

Solution

Sample code folder: Chapter 16\Cryptography

Use the FileEncrypt() and FileDecrypt() functions presented in this recipe.

Discussion

You can theoretically load an entire file into a string and call the StringEncrypt() and StringDecrypt() functions presented in Recipe 16.2 to process all its contents in one shot, but there may be problems with this approach. For one thing, larger files require a lot of memory during processing. It's better to process chunks of files a piece at a time until the whole file is processed. In the FileEncrypt() and FileDecrypt() functions presented here, a buffer of 4,096 bytes processes the streams of data in smaller, manageable chunks. Here are the two functions showing how this buffer is used:

 Public Sub FileEncrypt(ByVal sourceFile As String, _       ByVal destinationFile As String, _       ByVal keyText As String)    ' ----- Create file streams.    Dim sourceStream As New FileStream( _       sourceFile, FileMode.Open, FileAccess.Read)    Dim destinationStream As New FileStream( _       destinationFile, FileMode.Create, FileAccess.Write)    ' ----- Convert key string to 32-byte key array.    Dim keyBytes( ) As Byte = _       Encoding.UTF8.GetBytes(GetHash(keyText))    ' ----- Create initialization vector.    Dim IV( ) As Byte = { _       50, 199, 10, 159, 132, 55, 236, 189, _       51, 243, 244, 91, 17, 136, 39, 230}    ' ----- Create a Rijndael engine.    Dim rijndael As New RijndaelManaged    ' ----- Create the cryptography transform.    Dim cryptoTransform As ICryptoTransform    cryptoTransform = _       rijndael.CreateEncryptor(keyBytes, IV)    ' ----- Bytes will be processed by CryptoStream.    Dim cryptoStream As New CryptoStream( _       destinationStream, cryptoTransform, _       CryptoStreamMode.Write)    ' ----- Process bytes from one file into the other.    Const BlockSize As Integer = 4096    Dim buffer(BlockSize) As Byte    Dim bytesRead As Integer    Do       bytesRead = sourceStream.Read(buffer, 0, BlockSize)       If (bytesRead = 0) Then Exit Do       cryptoStream.Write(buffer, 0, bytesRead)    Loop ' ----- Close the streams.    cryptoStream.Close( )    sourceStream.Close( )    destinationStream.Close( ) End Sub Public Sub FileDecrypt(ByVal sourceFile As String, _       ByVal destinationFile As String, _       ByVal keyText As String)    ' ----- Create file streams.    Dim sourceStream As New   FileStream( _       sourceFile, FileMode.Open, FileAccess.Read)    Dim destinationStream As New   FileStream( _       destinationFile, FileMode.Create, FileAccess.Write)    ' ----- Convert key string to 32-byte key array.    Dim keyBytes( ) As Byte = _       Encoding.UTF8.GetBytes(GetHash(keyText))    ' ----- Create initialization vector.    Dim IV( ) As Byte = { _       50, 199, 10, 159, 132, 55, 236, 189, _       51, 243, 244, 91, 17, 136, 39, 230}    ' ----- Create a Rijndael engine.    Dim rijndael As New RijndaelManaged    ' ----- Create the cryptography transform.    Dim cryptoTransform As ICryptoTransform    cryptoTransform = _       rijndael.CreateDecryptor(keyBytes, IV)    ' ----- Bytes will be processed by   CryptoStream.    Dim cryptoStream As New CryptoStream( _       destinationStream, cryptoTransform, _       CryptoStreamMode.Write)    ' ----- Process bytes from one file into the other.    Const BlockSize As Integer = 4096    Dim buffer(BlockSize) As Byte    Dim bytesRead As Integer    Do       bytesRead = sourceStream.Read(buffer, 0, BlockSize)       If (bytesRead = 0) Then Exit Do       cryptoStream.Write(buffer, 0, bytesRead)    Loop    ' ----- Close the streams.    cryptoStream.Close( )    sourceStream.Close( )    destinationStream.Close( ) End Sub 

These two functions are similar to the StringEncrypt() and StringDecrypt() functions, except for a couple of important features. Instead of the memory stream being used to process the strings, the file contents are processed through file streams. The cryptoStream object is hooked into the file stream to process the bytes as they flow through the streams.

The other difference is the use of a byte-array buffer that holds 4,096 bytes. Chunks of 4,096 bytes are read from the input file, processed by the streams in the process, and then written to the output file. This allows processing of very large files a piece at a time.

The following code demonstrates these two functions by first creating a plain-text file, then encrypting it to a second file, and finally decrypting the result to a third file, always using the same key:

 Dim result As New System.Text.StringBuilder Dim file1Text As String = _    "This is sample content for a text file" & vbNewLine & _    "to be encrypted and decrypted. File1 and" & vbNewLine & _    "File3 should show this plain text. File2" & vbNewLine & _    "is encrypted and will be indecipherable." Dim file2Text As String Dim file3Text As String Dim file1 As String = Application.StartupPath & "\File1.txt" Dim file2 As String = Application.StartupPath & "\File2.ezz" Dim file3 As String = Application.StartupPath & "\File3.txt" ' ----- Create the encrypted   and decrypted   files. My.Computer.  FileSystem.WriteAllText(file1, file1Text, False) FileEncrypt(file1, file2, "key") FileDecrypt(file2, file3, "key") ' ----- Display the results. file2Text = My.Computer.FileSystem.ReadAllText(file2) file3Text = My.Computer.FileSystem.ReadAllText(file3) result.AppendLine("File1:") result.AppendLine(file1Text) result.AppendLine( ) result.AppendLine("File3:") result.AppendLine(file3Text) result.AppendLine( ) result.AppendLine("File2:") result.Append(file2Text) MsgBox(result.ToString( )) 

The original file and the decrypted file are displayed first in the message box, as shown in Figure 16-3, and the encrypted file (File2) is displayed last. The encrypted file consists of binary data unsuitable for normal display, resulting in a truncated list of strange characters.

Figure 16-3. Original, encrypted, and decrypted versions of a file


See Also

Recipe 16.9 includes the full source code for the Crypto module.




Visual Basic 2005 Cookbook(c) Solutions for VB 2005 Programmers
Visual Basic 2005 Cookbook: Solutions for VB 2005 Programmers (Cookbooks (OReilly))
ISBN: 0596101775
EAN: 2147483647
Year: 2006
Pages: 400

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net