Encrypting & Decrypting Files

One of most common task in cryptography is data encryption. This article deals with the symmetric cryptography and Asymmetric cryptography. We can have a detailed analysis of Symmetric and asymmetric methodology.

Using Symmetric Cryptography
In this section we can learn how to encrypt and decrypt simple text using the symmetric methodology. The example uses the RijndaelManaged algorithm class for illustration.

C# Code Snippet-1

private void btnEncrypt_Click(object sender, System.EventArgs e)
   FileStream        FIn;                    // Input file.
   FileStream        FOut;                   // Output file.
   Byte[]            Data = new Byte[100];   // Temporary buffer.
   int               Counter = 0;            // Total converted.
   int               ReadByte = 0;           // Currently read counter.
   CryptoStream      CryptStream;            // Cryptographic stream.
   RijndaelManaged   RM;                     // Encryption Algorithm.
   byte[] Key = {0x01, 0x02, 0x03, 0x04,     // Encryption Key.
                 0x05, 0x06, 0x07, 0x08,
                 0x09, 0x10, 0x11, 0x12,
                 0x13, 0x14, 0x15, 0x16};
   byte[] IV = {0x01, 0x02, 0x03, 0x04,      // Initialization vector.
                0x05, 0x06, 0x07, 0x08,
                0x09, 0x10, 0x11, 0x12,
                0x13, 0x14, 0x15, 0x16};
   // Open the input and output files.
   FIn = new FileStream(txtInput.Text,
   FOut = new FileStream(txtEncrypt.Text,
   // Create the cryptographic stream.
   RM = new RijndaelManaged();
   CryptStream = new CryptoStream(FOut,
                                  RM.CreateEncryptor(Key, IV),  
   // Encrypt the file.
   while(Counter < FIn.Length)
      ReadByte = FIn.Read(Data, 0, 100);
      CryptStream.Write(Data, 0, ReadByte);
      Counter = Counter + ReadByte;
   // Close the open stream and files.

Any Symmetric encryption technology is dependent on “Cipher-Chaining” method of encryption. The encryption algorithm is uses the previous cipher block in a chain of blocks to determine the encryption seed for the current block. Of course, there’s no previous block for the first block of code, so you must supply a seed value for the encryption algorithm called the initialization vector (IV). Consequently, all of these encryption techniques require that you provide both a Key and IV  Byte array as basic input values. Notice how these two values work with the RM.CreateEncryptor() method. As the example shows, the CSP is part of this constructor call, so you don’t use the Key and IV  with the CSP, but you do use it to create the data transfer object.

As you can see in the example code, the idea is to open an input and an output  file. The input file contains the plain text that you want to encrypt. Notice the CreateEncryptor()  method call in CryptoStream() constructor. You would replace this with a CreateDecryptor ()  call in the decryption portion of the code.

(This figure shows that text is completely garbled)

 Using Aysymmetric Cryptography
Asymmetric method is different from the Symmetric method, The first step is to create a key pair. This process is bit tedious. Let us examine the code sample mentioned below for creating the Key pair   


C# Code Snippet-2

public frmMain()
   String         KeyPath;    // The location of the key.
   CspParameters  Params;     // Cryptographic parameters.
   FileStream     KeyFile;    // Key disk storage.
   Char[]         KeyData;    // Key data as a Char array.
   Byte[]         KeyConv;    // Converted key data.
   StringBuilder  KeyString;  // Key data as a String.
   Int32          Counter;    // Loop counter.
   // Required for Windows Form Designer support
   // Create the key path string.
   KeyPath = Application.ExecutablePath;
   KeyPath = KeyPath.Substring(0, KeyPath.LastIndexOf(@"\") + 1)
             + "SpecialKey";
   // Define the cryptographic parameters.
   Params = new CspParameters();
   Params.KeyContainerName = "TemporarySpecialKey";
   Params.KeyNumber = 1;
   Params.ProviderName =
      "Microsoft RSA SChannel Cryptographic Provider";
   Params.ProviderType = 12;
   Params.Flags = CspProviderFlags.UseMachineKeyStore;
   // Detect the presence of a key pair file.
   if (!File.Exists(KeyPath))
      // Generate a key pair.
      RSACrypto = new RSACryptoServiceProvider(2048, Params);
      // Convert the key data for storage.
      KeyData = RSACrypto.ToXmlString(true).ToCharArray();
      KeyConv = new Byte[KeyData.Length];
      for (Counter = 0; Counter < KeyData.Length; Counter++)
         KeyConv[Counter] = Convert.ToByte(KeyData[Counter]);
      // Save the key to a file.
      KeyFile = File.Open(KeyPath, FileMode.CreateNew);
      KeyFile.Write(KeyConv, 0, RSACrypto.ToXmlString(true).Length);
      // Open the key file for reading.
      KeyFile = File.Open(KeyPath, FileMode.Open);
      KeyConv = new Byte[KeyFile.Length];
      KeyFile.Read(KeyConv, 0, (Int32)KeyFile.Length);
      // Convert the key file.
      KeyString = new StringBuilder(KeyConv.Length);
      for (Counter = 0; Counter < KeyConv.Length; Counter++)
      // Create the key.
      RSACrypto = new RSACryptoServiceProvider(2048, Params);

The code begins by creating a key path. You can store the key anywhere safe, but the example uses a file so that you can see how certain elements of the key generation work. In general, you’ll need to produce a file that contains the public key to send to others, but you might want to keep the private/public key pair on your machine. It’s relatively easy to use the machine’s key storage for this purpose. Unfortunately, if you have to reformat the hard drive or lose contact with the machine for other reasons, the key is also lost. Although the machine’s key storage is safer than using a file, it’s also beneficial to create a file for the private/public key pair to store in an offsite location so you can recover your data should an emergency occur.

Next, the code creates a CspParameters object. Although this object is optional, you should create it so that you can better control the encryption process. Otherwise, the system will make all of the critical decisions for you. This object has four fields and one property that you should fill with data. Microsoft’s documentation says you should look at the Windows CryptoAPI documentation for details on everything. In short, this object is almost undocumented.

The KeyContainerName property contains a simple string that identifies the key container. A single container can contain multiple keys. You would use this name if you wanted to access the key using the machine’s store. If you plan to create just a disk version of the key or if you want to use the default key container, you don’t need to include this value.

The KeyNumber property is the number of the key within the container. Unless you create multiple keys for a given container, set this value to 1.

The ProviderName property is where things get interesting. You must supply a specific text value—one that the system supports, but these values don’t appear in the .NET documentation. The fastest way to locate these values is to look in the WinCrypt.H file found in the \Program Files\Microsoft Visual Studio .NET 2003\Vc7\PlatformSDK\Include folder. The supported names include:

Hide comments


  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.