Return to
HomePage
Creating and securely storing a symmetric encryption key and Initialization Vector (VB.NET)
Applies to
* .NET 2.0
* VB.NET
Summary
The purpose of this code sample is to demonstrate the secure creation and storage of a symmetric cryptographic key and initialization vector to be used for encrypting and decrypting blocks of data.
Objectives
* Create a random encryption key to be used within a symmetric encryption cipher.
* Securely store the symmetric encryption key without needing to implement additional encryption operations or relying on filesystem or database security.
* Discuss the use and distribution of initialization vectors.
Scenarios
* The application is required to store sensitive data in an encrypted form
* Two entities in a client-server or client-client architecture need to transmit data in an encrypted form
* Application developers should not have access to production encryption keys; a product support group may use a utility containing the solution code to set the production encryption keys.
Solution Example
Public Sub [GenerateAndStoreSymmetricAESKey()]
' The .NET framework supports several symmetric or block ciphers including: Rijndael (AES),
' DES, 3DES, RC2, etc.
' Symmetric (secret key) encryption algorithms assume that both parties know the secret
' key and initialization vector or IV (when using a chained mode for the crypto
' operation). Protecting the secret key by both recipients is vital to the protection
' of data transmitted or stored by both parties.
' Symmetric ciphers are often well suited to protecting large blocks of data between two
' or more parties when the secret key has been negotiated in a secure manner.
' There exist many block ciphers today, however perhaps the most popular is AES, the
' current encryption standard approved by the National Institute of Standards and Technology
' (NIST). The AES algorithm was created by two Belgian cryptographers and commonly
' referred to as Rijndael as is the case in the .NET framework.
' The following call will create a Rijndael (AES) Crypto Provider with a cryptographically
' random key and initialization vector. This crypto provider defaults to a key size
' of 256 bits and considered extremely secure even by today's computing standards.
Dim rij As Rijndael = Rijndael.Create()
' The following method demonstrates the ability to generate a new key from the
' given crypto provider. Typically this method need not be called unless
' it is desired to "re-key". Re-keying may be performed in some communication protocols
' to mitigate the likelihood of an adversary having compromised a secret key used
' to protect the session.
' By default in the .NET framework a call to Rijndael.Create() constructor will
' automatically generate a key and associated it with the object created (stored in the
' Key member).
[rij.GenerateKey()]
' Encryption keys should be protected in storage. The .NET framework provides a method
' to securely protect secrets such as encryption keys and passwords known as the
' data protection api (DPAPI). For further details please refer to:
' http://msdn.microsoft.com/library/en-us/dnpag2/html/paght000005.asp
' The following method demonstrates the generation of a new initialization vector.
' Initialization vectors (IV) are used to ensure that encrypted blocks of data are "chained".
' When using a chaining encryption mode such as CBC, CFB, OFB, a random initialization
' vector should be chosen with which the first block of plaintext data is XOR by the
' cipher. Subsequent blocks of the plaintext message are [XORed] with the output
' (crypted text) of the previous block.
'
' When using a random initialization vector for each communication, an eavesdropper
' who observes traffic between Alice and Bob may not be able to detect
' repititious blocks of data even if the same message is sent multiple times.
' We don't actually store this value but it's contained here to demonstrate how it
' should be called during subsequent encryption operations
rij.GenerateIV()
' The IV need not be protected, as an intermediary who intercepts an encrypted
' communications still needs the secret key to decrypt the message. However,
' the recipient of the encrypted data needs the IV to successfully decrypt the
' message. It is common for an encrypted text (ciphertext) to be preceeded by the
' IV used in the chaining of the encryption routine. Because the IV is a fixed
' length (as determined by the encryption cipher), the recipient of the encrypted
' text must remove the IV from the beginning of the message and use this value in
' conjunction with the shared secret key to decrypt the message.
' Upon subsequent encrypt routines the application should generate a new Initialization
' vector each time.
' Store the AES symmetric (shared secret) key to a byte array
' encrypt and stored in the registry by using the DPAPI [ProtectedData] class.
' We're using the [CurrentUser] scope instead of the [MachineKey] scope so that other,
' users or applications which may become compromised cannot access this key in the
' registry and decrypt. This provides additional security but sacrifices interoperability
' with other applications. Consider using the [MachineKey] scope if you have a need to
' share keys between applications.
Dim [encryptedKeyPair] As Byte() = [ProtectedData.Protect(rij.Key,] Nothing, [DataProtectionScope.CurrentUser)]
' Create a security context for a new key that we will use to store
' our shared key. The security context will restrict access to only
' our user.
Dim user As String = [Environment.UserDomainName] + "\" + [Environment.UserName]
Dim security As [RegistrySecurity] = New [RegistrySecurity()]
Dim rule As [RegistryAccessRule] = New [RegistryAccessRule(user,] [RegistryRights.FullControl,] [InheritanceFlags.ContainerInherit,] [PropagationFlags.None,] [AccessControlType.Allow)]
[security.AddAccessRule(rule)]
' Actually create the new registry key and apply the security context
' we just came up with.
Registry.CurrentUser.CreateSubKey("AESSymmetricKey", [RegistryKeyPermissionCheck.ReadWriteSubTree,] security)
' Write the encrypted connection string into the registry
Registry.SetValue("HKEY_CURRENT_USER\AESSymmetricKey", "KeyData", [encryptedKeyPair)]
End Sub
Problem Example
The following code sample demonstrates hardcoded the encryption key and initialization vector which is a common pitfall by many developers.
Dim rijndaelAlg As Rijndael = Rijndael.Create()
'Set secret key for the AES algorithm.
rijndaelAlg.Key = ASCIIEncoding.ASCII.GetBytes("_A_SAMPLE_KEY_WE_USE_TO_ENCRYPT_")
' Hardcode our IV
rijndaelAlg.IV = ASCIIEncoding.ASCII.GetBytes("SAMPLEIV")
* If an unauthorized user gains access to the application source code or compiled code he/she will be able to extract the key and decrypt all future communications.
* A hardcoded initialization vector does not provide full confidentiality of messages in that all equivalent plaintext messages will result in the same encrypted value, providing knowledge to an attacker about common messages.
Test Case
The following classes must be included in any project making use of the sample code provided above:
Imports System.Security
Imports
System.Security.AccessControl Imports System.Security.Cryptography
Imports Microsoft.Win32
Execute the following code and then open "regedit" and look in the registry under the key "HKEY
CURRENTUSER\AESSymmetricKey" to see the AES shared secret key encrypted in the registry via the DPAPI.
Sub Main()
' Generate an AES encryption key and store in the registry
' using DPAPI
[GenerateAndStoreSymmetricAESKey()]
End Sub
Expected Result
The AES key is encrypted using DPAPI and stored in the registry key, "HKEY
CURRENTUSER\AESSymmetricKey"
More Information
Symmetric (secret key) encryption algorithms assume that both parties know the secret key and initialization vector or IV (when using a chained mode for the crypto operation an Initialization Vector is required). Protecting the secret key by both recipients is vital to the protection of data transmitted or stored by both parties.
Symmetric ciphers are often well suited to protecting large blocks of data between two or more parties when the secret key has been negotiated in a secure manner.
There exist many block ciphers today, however perhaps the most popular is AES, the current encryption standard approved by the National Institute of Standards and Technology (NIST). The AES algorithm was created by two Belgian cryptographers and commonly referred to as 'Rijndael', as is the case in the .NET framework.
While encryption keys should be protected in storage, the IV need not be protected, as an intermediary who intercepts an encrypted communications still needs the secret key to decrypt the message. However, the recipient of the encrypted data needs the IV to successfully decrypt the message.
It is common for an encrypted text (ciphertext) to be preceeded by the IV used in the chaining of the encryption routine. Because the IV is a fixed length (as determined by the encryption cipher), the recipient of the encrypted text must remove the IV from the beginning of the message and use this value in conjunction with the shared secret key to decrypt the message.
Additional Resources
* Cryptopgraphy (.NET): http://msdn.microsoft.com/library/en-us/dnpag2/html/PAGGuidelines0003.asp?frame=true#pagguidelines0003_cryptography
* Cryptography Simplified in .NET: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/cryptosimplified.asp
Attributes
*
Applies To: .NET Framework 2.0, VB
*
Category: Cryptography
*
Author: George Gal
Return to
HomePage