Microsoft KB Archive/301070

= How to encrypt and decrypt a file by using Visual Basic .NET or Visual Basic 2005 =

Article ID: 301070

Article Last Modified on 12/6/2006

-

APPLIES TO


 * Microsoft Visual Basic 2005
 * Microsoft Visual Basic .NET 2003 Standard Edition
 * Microsoft Visual Basic .NET 2002 Standard Edition

-



This article was previously published under Q301070





For a Microsoft Visual C# .NET version of this article, see 307010.



This article refers to the following Microsoft .NET Framework Class Library namespaces:
 * System.IO
 * System.Security
 * System.Security.Cryptography

IN THIS TASK
 SUMMARY  

Requirements

 

Use Encryption and Decryption

 

Verify That the Encryption and the Decryption Work

 

A Complete Code List

 </li> REFERENCES</li></ul>

<div class="summary_section">

SUMMARY
This article describes how to use the cryptography classes that are provided by the Microsoft .NET Framework. You can use the cryptography classes to encrypt a text file to an unreadable state. Then, you can decrypt that text file back to its original format.

back to the top

Requirements
The following list outlines the recommended hardware, software, network infrastructure, and service packs that you must have:
 * Microsoft Windows XP, Microsoft Windows Server 2003, Microsoft Windows 2000 Professional, Microsoft Windows 2000 Server, Microsoft Windows 2000 Advanced Server, or Microsoft Windows NT 4.0 Server
 * Microsoft Visual Studio .NET or Microsoft Visual Studio 2005

back to the top

Use Encryption and Decryption
The System.Security.Cryptographic namespace in the .NET Framework provides a variety of tools to aid in encryption and in decryption. The CryptoStream class is one of the many classes that is provided. The CryptoStream class is designed to encrypt or to decrypt content as that content is streamed out to a file.

To encrypt a file, follow these steps: <ol> Run Visual Studio .NET or Visual Studio 2005.</li> Create a new console application in Visual Basic .NET or in Visual Basic 2005. A module is created for you, together with an empty Main procedure.</li>  Use the Imports statement on the System namespace, the System.Security namespace, the System.Security.Cryptography namespace, the System.Text namespace, and the System.IO namespace. You must do this so that you do not have to qualify declarations from these namespaces later in your code. You must use these statements before any other declarations. Imports System Imports System.IO Imports System.Security Imports System.Security.Cryptography Imports System.Runtime.InteropServices Imports System.Text </li> Generate a secret key to encrypt and to decrypt the data. The DESCryptoServiceProvider class is based on a symmetric encryption algorithm. The symmetric encryption requires a key and an initialization vector (IV) to encrypt the data. To decrypt the data, you must have the same key and the same IV. You must also use the same encryption algorithm. You can generate the keys by using either of the following methods:  Method 1 You can prompt the user for a password. Then, use the password as the key and the IV.</li> Method 2 When you create a new instance of the symmetric cryptographic classes, a new key and a new IV are automatically created for the session. You can use the key and the IV that are generated by the managed symmetric cryptographic classes to encrypt and to decrypt the file.

For more information about how to generate and to distribute keys, visit the following Microsoft Web site or see the .NET Framework software development kit (SDK) documentation:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpcongeneratingkeysforencryptiondecryption.asp</li></ul> </li>  Add the following function to generate a new key for a session as noted in Method 2: ' Call this function to remove the key from memory after it is used for security. Private Declare Sub ZeroMemory Lib &quot;kernel32.dll&quot; Alias &quot;RtlZeroMemory&quot; _ (ByVal Destination As String, ByVal Length As Integer) ' Function to generate a key. Function GenerateKey As String ' Create an instance of Symmetric Algorithm. The key and the IV are generated automatically. Dim desCrypto As DESCryptoServiceProvider = DESCryptoServiceProvider.Create

' Use the automatically generated key for encryption. Return ASCIIEncoding.ASCII.GetString(desCrypto.Key) End Function </li>  Create a method in your class that is named EncryptFile. The EncryptFile method must have three parameters:  sInputFile</li> sOutputFile</li> sKey (This is the secret key that is used to encrypt and to decrypt the file.)</li></ul>

Sub EncryptFile(ByVal sInputFilename As String, _                  ByVal sOutputFilename As String, _                   ByVal sKey As String) End Sub </li>  In the EncryptFile procedure, create an input FileStream object and an output FileStream object. These objects can be read from and written to the target files. Dim fsInput As New FileStream(sInputFilename, _                                   FileMode.Open, FileAccess.Read) Dim fsEncrypted As New FileStream(sOutputFilename, _                                   FileMode.Create, FileAccess.Write) </li>  Declare an instance of the DESCryptoServiceProvider class. This represents the actual encryption and the actual decryption technology that is used on the files. At this point, you can create a different provider if you want to use RSA security or another cryptographic technique. Dim DES As New DESCryptoServiceProvider </li> <li> The cryptographic provider must be provided with your secret key as an array of bytes. The System.Text namespace provides a function that is named GetBytes. As part of its encoding features, the GetBytes function takes a string and then returns an array of bytes. The size of the key is different for each cryptographic technique. For example, Data Encryption Standard (DES) takes a 64-bit key that is equal to 8 bytes or to 8 characters.

If you do not provide a key, the provider randomly generates one. This successfully encrypts the file, but there is no way to decrypt the file. Note that you also must provide the IV. This value is used as part of the encryption. Like the key, the IV is randomly generated if you do not provide the value. Because the values must be the same for both the encryption and the decryption, you must not permit random generation of these values. DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey) DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey) </li> <li> Create an instance of the CryptoStream class. Use the cryptographic provider to obtain an encrypting object (CreateEncryptor) and the existing output FileStream object as a part of the constructor. Dim cryptostream As New CryptoStream(fsEncrypted, _                                    desencrypt, _                                     CryptoStreamMode.Write) </li> <li> Read in the input file, and then write out to the output file. Pass through the CryptoStream object where the file is encrypted by using the key that you provided. Dim bytearrayinput(fsInput.Length - 1) As Byte fsInput.Read(bytearrayinput, 0, bytearrayinput.Length) cryptostream.Write(bytearrayinput, 0, bytearrayinput.Length) </li></ol>

To decrypt a file, follow these steps: <ol> <li> Create a method that is named DecryptFile. The decryption process is similar to the encryption process. However, DecryptFile has two key differences from the EncryptFile procedure. <ul> <li>CreateDecryptor is used instead of CreateEncryptor to create the CryptoStream object that specifies how the object can be used.</li> <li>When the decrypted text is written to the destination file, the CryptoStream object is now the source instead of the destination stream.</li></ul>

Sub DecryptFile(ByVal sInputFilename As String, _   ByVal sOutputFilename As String, _    ByVal sKey As String)

Dim DES As New DESCryptoServiceProvider 'A 64-bit key and an IV are required for this provider. 'Set secret key for DES algorithm. DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey) 'Set initialization vector. DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey)

'Create a file stream to read the encrypted file back. Dim fsread As New FileStream(sInputFilename, FileMode.Open, FileAccess.Read) 'Create a DES Decryptor from your DES instance. Dim desdecrypt As ICryptoTransform = DES.CreateDecryptor 'Create a crypto stream set to read and to do a DES decryption transform on incoming bytes. Dim cryptostreamDecr As New CryptoStream(fsread, desdecrypt, CryptoStreamMode.Read) 'Print out the contents of the decrypted file. Dim fsDecrypted As New StreamWriter(sOutputFilename) fsDecrypted.Write(New StreamReader(cryptostreamDecr).ReadToEnd) fsDecrypted.Flush fsDecrypted.Close End Sub </li> <li> Add the following lines to the Main procedure to call both EncryptFile and DecryptFile. Public Sub Main     'Must be 64 bits, 8 bytes. Dim sSecretKey As String

' Get the key for the file to encrypt. ' You can distribute this key to the user who will decrypt the file. sSecretKey = GenerateKey

' For additional security, pin the key. Dim gch As GCHandle = GCHandle.Alloc(sSecretKey, GCHandleType.Pinned)

' Encrypt the file. EncryptFile(&quot;%USERPROFILE%\MyData.txt&quot;, _                     &quot;%USERPROFILE%\Encrypted.txt&quot;, _                      sSecretKey)

' Decrypt the file. DecryptFile(&quot;%USERPROFILE%\Encrypted.txt&quot;, _                 &quot;%USERPROFILE%\Decrypted.txt&quot;, _                  sSecretKey)

' Remove the key from memory. ZeroMemory(gch.AddrOfPinnedObject, sSecretKey.Length * 2) gch.Free End Sub </li> <li>Save the file. Run your application. Make sure that the path that is used for the input file name points to an existing and a not important file.</li></ol>

back to the top

Verify That the Encryption and the Decryption Work
Test this code with a text (.txt) file to confirm that the file is correctly encrypted and decrypted. Make sure that you decrypt the file to a new file (as in the Sub Main procedure in this article) instead of to the original file. Examine the decrypted file and compare the decrypted file to the original.

back to the top

A Complete Code List
Imports System Imports System.IO Imports System.Security Imports System.Security.Cryptography Imports System.Runtime.InteropServices Imports System.Text

Module Module1

' Call this function to remove the key from memory after it is used for security. <DllImport(&quot;kernel32.dll&quot;)> _ Public Sub ZeroMemory(ByVal addr As IntPtr, ByVal size As Integer) End Sub

' Function to generate a 64-bit key. Function GenerateKey As String ' Create an instance of a symmetric algorithm. The key and the IV are generated automatically. Dim desCrypto As DESCryptoServiceProvider = DESCryptoServiceProvider.Create

' Use the automatically generated key for encryption. Return ASCIIEncoding.ASCII.GetString(desCrypto.Key)

End Function

Sub EncryptFile(ByVal sInputFilename As String, _                 ByVal sOutputFilename As String, _                  ByVal sKey As String)

Dim fsInput As New FileStream(sInputFilename, _                                 FileMode.Open, FileAccess.Read) Dim fsEncrypted As New FileStream(sOutputFilename, _                                 FileMode.Create, FileAccess.Write)

Dim DES As New DESCryptoServiceProvider

'Set secret key for DES algorithm. 'A 64-bit key and an IV are required for this provider. DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey)

'Set the initialization vector. DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey)

'Create the DES encryptor from this instance. Dim desencrypt As ICryptoTransform = DES.CreateEncryptor 'Create the crypto stream that transforms the file stream by using DES encryption. Dim cryptostream As New CryptoStream(fsEncrypted, _                                         desencrypt, _                                          CryptoStreamMode.Write)

'Read the file text to the byte array. Dim bytearrayinput(fsInput.Length - 1) As Byte fsInput.Read(bytearrayinput, 0, bytearrayinput.Length) 'Write out the DES encrypted file. cryptostream.Write(bytearrayinput, 0, bytearrayinput.Length) cryptostream.Close End Sub

Sub DecryptFile(ByVal sInputFilename As String, _      ByVal sOutputFilename As String, _       ByVal sKey As String)

Dim DES As New DESCryptoServiceProvider 'A 64-bit key and an IV are required for this provider. 'Set the secret key for the DES algorithm. DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey) 'Set the initialization vector. DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey)

'Create the file stream to read the encrypted file back. Dim fsread As New FileStream(sInputFilename, FileMode.Open, FileAccess.Read) 'Create the DES decryptor from the DES instance. Dim desdecrypt As ICryptoTransform = DES.CreateDecryptor 'Create the crypto stream set to read and to do a DES decryption transform on incoming bytes. Dim cryptostreamDecr As New CryptoStream(fsread, desdecrypt, CryptoStreamMode.Read) 'Print out the contents of the decrypted file. Dim fsDecrypted As New StreamWriter(sOutputFilename) fsDecrypted.Write(New StreamReader(cryptostreamDecr).ReadToEnd) fsDecrypted.Flush fsDecrypted.Close End Sub

Public Sub Main 'Must be 64 bits, 8 bytes. Dim sSecretKey As String

' Get the key for the file to encrypt. ' You can distribute this key to the user who will decrypt the file. sSecretKey = GenerateKey

' For additional security, pin the key. Dim gch As GCHandle = GCHandle.Alloc(sSecretKey, GCHandleType.Pinned)

' Encrypt the file. EncryptFile(&quot;%USERPROFILE%\MyData.txt&quot;, _                     &quot;%USERPROFILE%\Encrypted.txt&quot;, _                      sSecretKey)

' Decrypt the file. DecryptFile(&quot;%USERPROFILE%\Encrypted.txt&quot;, _                 &quot;%USERPROFILE%\Decrypted.txt&quot;, _                  sSecretKey)

' Remove the key from memory. ZeroMemory(gch.AddrOfPinnedObject, sSecretKey.Length * 2) gch.Free End Sub

End Module back to the top

<div class="references_section">