Windows Data Protection | File.Encrypt | Hashing | CryptoStream | Symmetric Encryption | Asymmetic Encryption | Digital Signatures

"Cryptography" is the science concerned with the study of secret communication. "Encryption" is a process or algorithm (known as a cipher) to make information hidden or secret.

.Voynich Manuscript
Voynich Manuscript - Undeciphered Manuscript from the 15th Century

The .NET Framework provides several standard cryptographic algorithms in an extensible pattern of class inheritance. The cryptographic algorithm class hierarchy is:

  1. Algorithm type class - such as SymmetricAlgorithm, AsymmetricAlgorithm or HashAlgorithm.
  2. Algorithm class that inherits from an algorithm type class - such as Aes, RC2, or ECDiffieHellman.
  3. Implementation of an algorithm class that inherits from an algorithm class - such as AesManaged, RC2CryptoServiceProvider, or ECDiffieHellmanCng.

The .NET name of the algorithm classes contain common acronyms for encryption algorithms, such as:

  1. AES - Advanced Encryption Standard
  2. SHA - Secure Hash Algorithm
  3. MD5 - Message Digest 5
  4. CNG - Cryptography Next Generation
  5. ECDSA - Elliptic Curve Digital Signature Algorithm

The .NET Framework contains several encryption algorithms for various purposes in the System.Security.Cryptography namespace. Encryption algorithms can be used for data privacy (protect from unwanted viewing) or for data integrity (protect from unwanted data changes). Encryption is also used in verifying software authors (Digital Signatures), in the exchange of encryption keys, in the generation of encrypted random numbers, and for protecting stored passwords (i.e. hash output and salt is stored in database instead of text based password). The following is a list .NET encryption algorithms categorized by application.

List of .NET Recommended Cryptographic Algorithms by Application
  1. Data privacy
    • Aes - the abstract base class from which all implementations of the Advanced Encryption Standard (AES) must inherit.
  2. Data Integrity
    • HMACSHA256 - computes a Hash-based Message Authentication Code (HMAC) by using the SHA256 hash function.
    • HMACSHA512- computes a Hash-based Message Authentication Code (HMAC) using the SHA512 hash function.
  3. Digital signature
    • ECDsa - provides an abstract base class that encapsulates the Elliptic Curve Digital Signature Algorithm (ECDSA).
    • RSA - represents the base class from which all implementations of the RSA algorithm inherit.
  4. Key Exchange
    • ECDiffieHellman- provides an abstract base class that Elliptic Curve Diffie-Hellman (ECDH) algorithm implementations can derive from. This class provides the basic set of operations that all ECDH implementations must support.
    • RSA -rRepresents the base class from which all implementations of the RSA algorithm inherit.
  5. Random Number Generation
    • RNGCryptoServiceProvider - implements a cryptographic Random Number Generator (RNG) using the implementation provided by the cryptographic service provider (CSP). This class cannot be inherited.
  6. Generating a Key from a Password
    • Rfc2898DeriveBytes - implements password-based key derivation functionality, PBKDF2, by using a pseudo-random number generator based on HMACSHA1.

Note1: It is illegal to transport certain encryption software to many countries, such as an Internet browser with strong encryption. Check with the US State Department for current information.

Note2: For a chronicling of the history of cryptography from ancient Egypt to 1967, read: The Codebreakers – The Story of Secret Writing (ISBN 0-684-83130-9) by David Kahn.

Windows Data Protection API

The Windows Data Protection API (DPAPI) was introduced in Windows 2000. DPAPI initially generates a strong key called a MasterKey, which is protected by the user's password. DPAPI uses a standard cryptographic process called Password-Based Key Derivation to generate a key from the password. This password-derived key is then used with Triple-DES to encrypt the MasterKey, which is finally stored in the user's profile directory.

A drawback to using the logon password is that all applications running under the same user can access any protected data that they know about. Of course, because applications must store their own protected data, gaining access to the data could be somewhat difficult for other applications, but certainly not impossible. To counteract this, DPAPI allows an application to use an additional secret when protecting data. This additional secret (entropy) is then required to unprotect the data.

The API consists of two system-level services which provide data encryption to user and system processes. In .NET the DPAPI is exposed through the ProtectedData class. The class contains two static methods Protect and Unprotect which take the DataProtectionScope enumeration an argument to specify the scope of the data protection:

  1. CurrentUser - the protected data is associated with the current user. Only threads running under the current user context can unprotect the data.
  2. LocalMachine - the protected data is associated with the machine context. Any process running on the computer can unprotect data. This enumeration value is usually used in server-specific applications that run on a server where untrusted users are not allowed access.
ProtectedData.Protect(data, s_aditionalEntropy, DataProtectionScope.CurrentUser);

ProtectedData.Unprotect(data, s_aditionalEntropy, DataProtectionScope.CurrentUser);

Note: Windows 7 Enterprise and Windows 7 Ultimate (but not other versions) contain BitLocker drive encryption as an integral security feature. Access through the Windows Explorer, General Tab, Advanced. Transparent file encryption (including File.Encrypt) is not supported in Windows 7 Home Edition.



Some editions of Windows contain support for transparent file encryption. This corresponds to the File.Encryption method. Transparent encryption uses a key seeded from the user's password. The encrypted data supports changes to the password made by the user. However, if an administrator changes the password, the data in the encrypted files is unrecoverable.

Transparent File Encryption with File Class


Transparent file encryption also requires certain file systems. NTFS supports encryption and this is the most commonly used file system for hard drives. The file system for CD's (CDFS) and removable storage devices (FAT) do not support encryption. Below is a program which uses the native Kernel32.dll to determine if the volume support encryption.

Test if Volume Supports Encryption

using System;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;

/* Determine if hard drive file system support encryption */
namespace FileEncryptExample
    class Program
        const int FileSupportsEncryption = 0x20000;

        [DllImport("Kernel32.dll", SetLastError = true)]
        extern static bool GetVolumeInformation
        (string vol,
        StringBuilder name,
        int NameSize,
        out uint serialNum,
        out uint MaxNameLen,
        out uint flags,
        StringBuilder fileSysName,
        int FileSysNameSize);

        static void Main(string[] args)
            uint serialNum, maxNameLen, flags;

            bool success = GetVolumeInformation(@"C:\", null, 0, out serialNum,
                out maxNameLen, out flags, null, 0);
            if (!success)

                throw new Win32Exception();

            if ((flags & FileSupportsEncryption) > 0)
                Console.WriteLine("C: supports file encryption\n");

Note: The File Class also provides static methods for the creation, copying, deletion, moving, and opening of files.



A Cryptographic hashing algorithm is a one-way encryption. The hash algorithm applies transformations to a data value in such a way that it consistently returns the same fixed-size bit string (the hash). The resulting hash is always the same size regardless of the size of the input data. Generally speaking, a hash algorithm which creates a more secure hash requires more computational power than a weak hashing algorithm. However all hashing algorithms are designed to withstand all known types of cryptanalytic attacks (e.g. birthday attack, rainbow table). An open source application for cracking hashes is Password Cracker which uses a dictionary attack for determining the original text.

For password protection, the password is hashed and the hashed value is stored. The authentication process hashes what the user types and compares to the stored hash value. This way the decrypted password is never stored nor displayed. Hashing algorithms are also used as checksums to determine if a file has been modified or if a data stream contains errors. A significantly different hash result will occur if any data is changed in the file or data stream.

In C# the HashAlgorithm class is the base class for all hash algorithms. The classes ComputeHash() method computes the hash value. Derived from the HashAlgorithm base class are the following C# defined hash algorithms listed in ascending order of security.

  1. MD5 - is only recommended for compatibility with legacy applications. Creates an 128 bit hash.
  2. SHA1 - small changes to the data results in large unpredictable changes in the hash. Creates an 160 bit hash.
  3. SHA256 - an abstract class. Only implementation is SHA256 Managed. Creates a 256 bit hash.
  4. SHA384Some recommend using SHA512 instead as it takes about the same computational power but creates a stronger hash. Creates a 384 bit hash.
  5. SHA512 an abstract class. Only implementation is SHA512Managed. Creates a 512 bit hash.

The hashing algorithms which create a larger size hash are appropriate for password protection (MD5 and SHA1 are not appropriate for password protection). However a strong password policy is required to prevent against dictionary attacks. Additionally there are two ways to help defeat dictionary attacks.

  1. Repeated Rehasing - this makes the hashing process more computationally expensive. Rehasing can increase the time it takes to attack a password from hours to years. The Rfc2898DeriveBytes and PasswordDeriveBytes classes perform this type of rehashing to obtain more computationally intensive bit sequences.
  2. Salting - a salt is a long series of bytes obtained from a random number generator (RandomNumberGenerator.GetBytes) which is combined with the password before hashing. This makes cracking the hash longer to compute and (hopefully) the hackers will not have access to the salt value.

The following code computes an SHA512 hash using the SHA512Managed class

byte[] data = new byte[DataSize];
byte[] result;

SHA512 shaM = new SHA512Managed();
result = shaM.ComputeHash(data);



.NET uses a stream-oriented design for cryptography using CryptoStream as its core. CryptoStream is a decorator stream which performs cryptographic transformations. You can both read and write data to a CryptoStream. It is important to dispose of a CryptoStream to ensure the memory cache is flushed. CryptoStream needs a memory cache because encryption algorithms work with blocks of data instead of individual bytes. Disposing of the encryption object is also recommended to immediately wipe any encryption related keys and data from memory, instead of waiting for garbage collection to clear the memory. The common way to ensure of proper disposal is with a using statement (which gets translated to a call to the Dispose() method in the finally clause of a try block).

As a decorator stream, CryptoStream can be chained together with other streams. Another decorator stream commonly used is DeflateStream which compresses and decompresses the stream data. Chaining together CryptoStream and DeflateStream will create encrypted and compressed data. Streams demand little memory usage, regardless of the amount of data which goes through the stream, even when the streams are chained together.

The following program chains together a CryptoStream and a DeflateStream to write and read a file that is encrypted and compressed.

.CryptoStream chained to Deflate Stream to Encrypt and Compress Text
CryptoStream chained to Deflate Stream to Encrypt and Compress Text

using System;
using System.IO;
using System.IO.Compression;
using System.Security.Cryptography;
using System.Text;

namespace EncryptCompressStream
    class Program
        static void Main()
            // Encrypt Text using AES, Compress, Write to File
            using (Aes algorithm = Aes.Create())
                using (ICryptoTransform encryptor = algorithm.CreateEncryptor())
                using (Stream f = File.Create("kevin.bin"))
                using (Stream c = new CryptoStream(f, encryptor, CryptoStreamMode.Write))
                using (Stream d = new DeflateStream(c, CompressionMode.Compress))
                using (StreamWriter w = new StreamWriter(d))
                    w.WriteLine("How now brown cow.");

                // Read Encrypted Bytes from File
                Console.Write("Encrypted and Compressed bytes are:");
                using (Stream f = File.OpenRead("kevin.bin"))
                using (BinaryReader b = new BinaryReader(f))
                    while (b.BaseStream.Position != b.BaseStream.Length)
                        Console.Write(b.ReadByte() + ".");

                // Read Encrypted Text from File as UTF8
                Console.Write("\n\nEncrypted and Compressed UTF8 is:");
                using (Stream f = File.OpenRead("kevin.bin"))
                using (BinaryReader b = new BinaryReader(f))
                    while (b.BaseStream.Position != b.BaseStream.Length)
                        //Console.Write(Encoding.Convert(Encoding.Default, Encoding.ASCII, b.ReadBytes(1)));

                // Decrypt and Decompress Text from File
                using (ICryptoTransform decryptor = algorithm.CreateDecryptor())
                using (Stream f = File.OpenRead("kevin.bin"))
                using (Stream c = new CryptoStream(f, decryptor, CryptoStreamMode.Read))
                using (Stream d = new DeflateStream(c, CompressionMode.Decompress))
                using (StreamReader r = new StreamReader(d))
                    Console.WriteLine("\n\nDecrypted and Uncompressed text is: {0}\n", r.ReadLine());


Symmetric Encryption

Symmetric Encryption is a class of algorithms that use the same key for both encryption and decryption. The key represents a shared secret between two parties that can used to maintain private communications (i.e. both parties must have access to the secret key). Symmetric algorithms also requires the creation of a n initialization vector (IV). The IV does not have to be secret, but should be changed for each session. To communicate a symmetric key and IV to a remote party, you would usually encrypt the symmetric key by using asymmetric encryption. Sending the key across an insecure network without encrypting it is unsafe, because anyone who intercepts the key and IV can then decrypt your data.

The SymmetricAlgorithm class is the abstract base class for all symmetric encryption algorithms. Further, each type of symmetric algorithm includes a base class; these include:

  1. AES - Advanced Encryption Standard Base Class (Recommended)
  2. DES - Data Encryption Standard Base Class
  3. RC2 - RC2 Base Class
  4. Rijndael- Rijndael Base Class
  5. TripleDES - Triple Data Encryption Standard Base Class

Other names for symmetric encryption include: shared-key, single-key, secret-key, and one-key encryption. Advantage and disadvantages of symmetric encryption include:

  • Advantages of Symmetric Encryption
    • Symmetric encryption is faster (than asymmetric encryption) for encrypting large amounts of data.
    • It is also a simple encryption method to use which is good for encryption of your own files, which you do not intend to share.

  • Disadvantages of Symmetric Encryption
    • The initial sharing of the secret key needs a secure method of exchange. The key must be exchanged in a way that ensures it remains secret.
    • Many shared keys are generated as a new shared key it generated for communication with every different party. Managing and ensuring the security of all these keys can be a problem.
    • Messages cannot be verified to have come from a particular user since both sender and receiver use the same key, . This may be a problem if there is a dispute.

Rijndael alogorithm is considered the premium symmetric encryption algorithm in .NET, for which there are two implementations:

  1. Rijndael - available since .NET 1.0 (RijndaelManaged)
  2. AES - introduced in .NET 3.5 (AesManaged)

AES is essentially the Rijndael symmetric algorithm with a fixed block size and iteration count. The AES class functions the same way as the RijndaelManaged class but limits blocks to 128 bits and does not allow feedback modes (i.e. AES does not let you weaken security by lowering the block size, so AES is the recommended algorithm for symmetric encryption in .NET).


Asymmetric Encryption

Asymmetric Encryption is also known as Public-key Encryption and requires a pair of keys, one public key and one private key. The key pair is designed to work together (i.e. the public key and private key are mathematically linked). However the private key can not be derived from the public key. If the private key is lost, the data can not be decrypted. The keys in the public/private key pair function as:

  1. Public Key - encrypts the data.
  2. Private Key- decrypts the data.

The public key does not require a secure initial exchange of a secret key (as does symmetric encryption). The public key allows two computer to establish a communication channel (handshake) over a public network with no prior contact. Asymmetric encryption only works when the encrypted text is smaller than the key, making it useful for only encrypting small amounts of data. It is used to solve the problem of secure key sharing in symmetric encryption. Asymmetric encryption can be used to securely transmit the secret key needed for symmetric encryption. Subsequent symmetric encryption can then occur to process a large amount of data. This method of using asymmetric encryption to transmit the secret key, then switching to symmetric encryption to process the large amount of data -- is especially effective if a fresh public/private key pair is generated for each session.

Asymmetric encryption is also used in digital signing which is used to verify the sender of the message (document, program, etc) and also verify the message has not been changed (i.e. tampered with). Digital signing works by first hashing the data and then applying the asymmetric encryption to the resulting hash (more on digital signing below).

The AsymmetricAlgorithm class is the abstract base class for all asymmetric encryption algorithms. Further, each type of asymmetric algorithm includes a base class; these include:

  1. RSA - Ron Rivest, Adi Shamir and Leonard Adleman (Most Popular)
  2. DSA - Digital Signature Algorithm
  3. ECDiffieHellman - Elliptic Curve Diffie-Hellman (ECDH)
  4. ECDsa - Elliptic Curve Digital Signature Algorithm (ECDSA)

The advantages and disadvantages of asymmetric encryption include:

  • Advantages of Asymmetric Encryption
    • It solves the problem of distributing the secret key for symmetric encryption.
    • It allows the use of digital signatures which enables the recipient of a message to verify the integrity of the content and that the message is truly from a particular sender. A digitally signed message cannot be modified without invalidating the signature.

  • Disadvantages of Asymmetric Encryption
    • Asymmetric encryption is slow compared to symmetric encryption. So Asymmetric encryption is not feasible for use in decrypting bulk messages.
    • It is more computationally expensive than symmetric encryption.
    • The loss of a private key means that all messages encrypted with that key will not be able to be decrypted. (i.e. The messages are lost).

.Net implements the RSA algorithm with the RSACryptoServiceProvider class. If no public or private key is requested, the class automatically creates the key pair using a length of 1024 bits. If an application is security critical, the key pair should be requested with a larger size. Generating the key pair is computationally expensive, so RSA delays creating the keys until they are actually required (e.g. calling Encrypt() method).


Digital Signatures

.Digital Signature
VeriSign Digital Signature

A digital signature is a mathematical method for proving the authenticity of a digital message (document, program, etc). A valid digital signature give the recipient reason to believe the message is from the sender and the message has not been altered. Digital signatures can also provide non-repudiation, meaning that the signer cannot successfully claim they did not sign a message. Digital signatures are commonly used in software distribution and financial transactions.

A common model for digital signing is to first hash the data, then use an asymmetric algorithm to encrypt the hash. With digital signing the recipient must know, and trust, the public key. The public key can be from a prior communication, a site certificate, or a preconfiguration. A site certificate is an electronic record of the publisher's public key and name that has been signed by a trusted authority (e.g. VeriSign). Types for working with certificates is System.Security.Cryptography.X509Certificates, which contains the class X509Certificate. .NET also includes a command line tool for working with X.509 certificates stored on the local computer. To run the X.509 Certificate tool: Click Start, point to All Programs, point to Microsoft WSE 3.0, and then click X.509 Certificate Tool.

In a production environment, use an X.509 certificate issued by a certificate authority (CA) such as VeriSign. In a development environment, use the MakeCert utility to create a temporary X.509 certificate.The MakeCert utility is automatically installed with Visual Studio. To run the tool, use the Developer Command Prompt (or the Visual Studio Command Prompt in Windows 7).

To create a digital signature you can first create the hash yourself and then call the RSACryptoServiceProvider.SignHash method. Or you can just call the RSACryptoServiceProvider.SignData method which will both compute the hash value and sign it.


Reference Articles