Decrypting Data

Decryption is the reverse operation of encryption. For secret-key encryption, you must know both the key and IV that were used to encrypt the data. For public-key encryption, you must know either the public key (if the data was encrypted using the private key) or the private key (if the data was encrypted using the public key).

Symmetric Decryption

The decryption of data encrypted with symmetric algorithms is similar to the process used to encrypt data with symmetric algorithms. The CryptoStream class is used with symmetric cryptography classes provided by the .NET Framework to decrypt data read from any managed stream object.

The following example illustrates how to create a new instance of the RijndaelManaged class and use it to perform decryption on a CryptoStream object. This example first creates a new instance of the RijndaelManaged class. Next it creates a CryptoStream object and initializes it to the value of a managed stream called MyStream. Next, the CreateDecryptor method from the RijndaelManaged class is passed the same key and IV that was used for encryption and is then passed to the CryptoStream constructor. Finally, the CryptoStreamMode.Read enumeration is passed to the CryptoStream constructor to specify read access to the stream.

Dim RMCrypto As New RijndaelManaged()
Dim CryptStream As New CryptoStream(MyStream, RMCrypto.CreateDecryptor(RMCrypto.Key, RMCrypto.IV), CryptoStreamMode.Read)
[C#]
RijndaelManaged RMCrypto = new RijndaelManaged();
CryptoStream CryptStream = new CryptoStream(MyStream, RMCrypto.CreateDecryptor(Key, IV), CryptoStreamMode.Read);

The following example shows the entire process of creating a stream, decrypting the stream, reading from the stream, and closing the streams. A TCPListener object is created that initializes a network stream when a connection to the listening object is made. The network stream is then decrypted using the CryptoStream class and the RijndaelManaged class. This example assumes that the key and IV values have been either safely transferred or previously agreed upon. It does not show the code needed to encrypt and transfer these values.

Imports System
Imports System.Net.Sockets
Imports System.Threading
Imports System.IO
Imports System.Security.Cryptography

Module Module1
    Sub Main()
        'The key and IV must be the same values that were used
        'to encrypt the stream.  
        Dim Key As Byte() = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16}
        Dim IV As Byte() = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16}
        Try
            'Initialize a TCPListener on port 11000
            'using the current IP address.
            Dim TCPListen As New TcpListener(11000)

            'Start the listener.
            TCPListen.Start()

            'Check for a connection every five seconds.
            While Not TCPListen.Pending()
                Console.WriteLine("Still listening. Will try in 5 seconds.")

                Thread.Sleep(5000)
            End While

            'Accept the client if one is found.
            Dim TCP As TcpClient = TCPListen.AcceptTcpClient()

            'Create a network stream from the connection.
            Dim NetStream As NetworkStream = TCP.GetStream()

            'Create a new instance of the RijndaelManaged class
            'and decrypt the stream.
            Dim RMCrypto As New RijndaelManaged()


            'Create an instance of the CryptoStream class, pass it the NetworkStream, and decrypt 
            'it with the Rijndael class using the key and IV.
            Dim CryptStream As New CryptoStream(NetStream, RMCrypto.CreateDecryptor(Key, IV), CryptoStreamMode.Read)

            'Read the stream.
            Dim SReader As New StreamReader(CryptStream)

            'Display the message.
            Console.WriteLine("The decrypted original message: {0}", SReader.ReadToEnd())

            'Close the streams.
            SReader.Close()
            NetStream.Close()
            TCP.Close()
            'Catch any exceptions. 
        Catch
            Console.WriteLine("The Listener Failed.")
        End Try
    End Sub
End Module
[C#]
using System;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.Security.Cryptography;

class Class1
{
   static void Main(string[] args)
   {
      //The key and IV must be the same values that were used
      //to encrypt the stream.  
      byte[] Key = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16};
      byte[] IV = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16};
      try
      {
         //Initialize a TCPListener on port 11000
         //using the current IP address.
         TcpListener TCPListen = new TcpListener(11000);

         //Start the listener.
         TCPListen.Start();

         //Check for a connection every five seconds.
         while(!TCPListen.Pending())
         {
            Console.WriteLine("Still listening. Will try in 5 seconds.");
            Thread.Sleep(5000);
         }

         //Accept the client if one is found.
         TcpClient TCP = TCPListen.AcceptTcpClient();

         //Create a network stream from the connection.
         NetworkStream NetStream = TCP.GetStream();

         //Create a new instance of the RijndaelManaged class
         // and decrypt the stream.
         RijndaelManaged RMCrypto = new RijndaelManaged();


         //Create a CryptoStream, pass it the NetworkStream, and decrypt 
         //it with the Rijndael class using the key and IV.
         CryptoStream CryptStream = new CryptoStream(NetStream, 
            RMCrypto.CreateDecryptor(Key, IV), 
            CryptoStreamMode.Read);

         //Read the stream.
         StreamReader SReader = new StreamReader(CryptStream);

         //Display the message.
         Console.WriteLine("The decrypted original message: {0}", SReader.ReadToEnd());

         //Close the streams.
         SReader.Close();
         NetStream.Close();
         TCP.Close();
      }
      //Catch any exceptions. 
      catch
      {
         Console.WriteLine("The Listener Failed.");
      }
   }
}

For the previous sample to work, an encrypted connection must be made to the listener. The connection must use the same key, IV, and algorithm used in the listener. If such a connection is made, the message is decrypted and displayed to the console.

Asymmetric Decryption

Someone who generates a public/private key pair typically performs asymmetric decryption. You can decrypt data using the RSACryptoServiceProvider that you used to create the public/private key pair or initialize a new RSACryptoServiceProvider with the key information. Decryption will be successful only if you use the private key that corresponds to the public key used to encrypt the data.

The following example illustrates the decryption of two arrays of bytes that represent a symmetric key and IV.

'Create a new instance of the RSACryptoServiceProvider class.
Dim RSA As New RSACryptoServiceProvider()

'Decrypt the symmetric key and IV.
SymmetricKey = RSA.Decrypt(EncryptedSymmetricKey, False)
SymmetricIV = RSA.Decrypt(EncryptedSymmetricIV, False)
[C#]
//Create a new instance of the RSACryptoServiceProvider class.
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();

//Decrypt the symmetric key and IV.
SymmetricKey = RSA.Decrypt( EncryptedSymmetricKey, false);
SymmetricIV = RSA.Decrypt( EncryptedSymmetricIV , false);

See Also

Generating Keys for Encryption and Decryption | Encrypting Data | Cryptographic Tasks | Cryptographic Services