14.10 Exchange Symmetric Session Keys Securely


Problem

You need to exchange symmetrically encrypted data with somebody, and you need a secure method of delivering the symmetric session key with the data.

Solution

Use the key exchange mechanism implemented by the System.Security.Cryptography.RSACryptoServiceProvider class. This will asymmetrically encrypt your symmetric key using the intended recipient's public key. You can then send the encrypted symmetric key along with the encrypted data to the recipient. The recipient must decrypt the symmetric key using the private key, and then proceed to decrypt the data.

Discussion

Each time you symmetrically encrypt data for transmission you should generate a new key, also known as a session key . The use of session keys provides two major benefits:

  • If an unauthorized person obtains multiple blocks of ciphertext encrypted using the same symmetric key, it increases the chance of decrypting the data using cryptanalytic techniques.

  • If a person does discover your session key, it gives them access to only a single set of encrypted data ”not all of your past and future secrets as well.

The problem with session keys is an issue of key distribution and security. If you always use the same key, it's not such a problem to meet the other party or arrange a high-security courier to physically exchange keys. However, if you generate new keys for every data exchange, physical meetings are simply out of the question. One answer would be to agree upon a large number of session keys up front with those people with whom you exchange data. Unfortunately, this quickly becomes hard to administer, and the fact that all of your future keys are stored somewhere increases the chances that they will be compromised. A better approach is to send the session key in a strongly encrypted form along with the data that you encrypted with that key ”a process known as key exchange .

Key exchange involves using asymmetric encryption to encrypt the symmetric session key. If you want to send data to somebody, you generate a symmetric session key, encrypt the data, and then encrypt the session key using the recipient's public key. When the intended recipient receives the data, they decrypt the session key using their private key, and then decrypt the data. Importantly, key exchange allows you to exchange large amounts of encrypted data with anybody, even people you have never communicated with before, as long as you have access to their asymmetric public keys.

Note  

Ideally, you would use an asymmetric algorithm to encrypt all data, thus avoiding the need to exchange symmetric keys. However, the speed at which asymmetric algorithms encrypt and decrypt data makes them impractical for use with large amounts of data. Using asymmetric algorithms to encrypt symmetric session keys is a solution that, although more complex, offers the best of both worlds : flexibility and speed.

The .NET Framework class library includes support for key exchange using only the RSA algorithm, but you must choose between two formatting schemes: Optimal Asymmetric Encryption Padding (OAEP) and PKCS #1 v 1.5. A discussion of these formatting schemes is beyond the scope of this book. Generally, you should use OAEP formatting unless you have a specific need to communicate with a legacy system that uses PKCS formatting. The following two classes implement the key exchange mechanism ”one for each formatting scheme:

  • System.Security.Cryptography.RSAOAEPKeyExchangeFormatter

  • System.Security.Cryptography.RSAPKCS1KeyExchangeFormatter

To prepare a symmetric key for exchange you must create a formatter object of the desired type and then assign an asymmetric algorithm object ( RSACryptoServiceProvider ) to the formatter by calling the formatter's SetKey method. You must configure the asymmetric algorithm to use the recipient's public key. Once configured, call the formatter's CreateKeyExchange method and pass a byte array containing the symmetric session key that you want to format. The CreateKeyExchange method returns a byte array containing the key exchange data that you should send to the intended recipient.

Deformatting the exchanged key mirrors the formatting process. There are two deformatter classes ”one for each formatting scheme.

  • System.Security.Cryptography.RSAOAEPKeyExchangeDeformatter

  • System.Security.Cryptography.RSAPKCS1KeyExchangeDeformatter

To deformat a formatted session key, create a deformatter object of the appropriate type and call its SetKey method to assign an asymmetric algorithm object. You must load your private key into the asymmetric algorithm. Finally, call the DecryptKeyExchange method passing in the key exchange data. The DecryptKeyExchange method returns a byte array containing the original symmetric session key.

The KeyExchangeExample.cs file contains a demonstration of key exchange. The sample's Main method (not shown here, but available in the sample code for this chapter) simulates the creation, formatting, exchange, and deformatting of a symmetric session key. The Main method generates an asymmetric key pair for use throughout the example. In a real key exchange situation, the sender who created the symmetric key would only have the recipient's public key. The recipient would have the private key, which is kept secret.

Note  

Just as it's important that you use a symmetric key of a length appropriate to the secrecy of the data being protected, it's important that you encrypt your session key using an asymmetric algorithm and key length that's at least the equivalent of your symmetric key. If your asymmetric key is weaker than your symmetric key, an attacker will more likely attempt to break your asymmetric encryption and obtain the symmetric key instead of trying to decrypt the symmetrically encrypted data. See http://ietf.org/internet-drafts/draft-orman-public- key-lengths-05.txt for details on the equivalence of asymmetric and symmetric key lengths.

The Main method then calls the example's FormatKeyExchange method passing a byte array containing the symmetric key and an RSAParameters object containing the recipient's public key. The FormatKeyExchange method returns a byte array containing the encrypted and formatted symmetric key, ready to send to the intended recipient. Next the Main method calls the example's DeformatKeyExchange method passing the formatted key exchange data and a CspParameters object that contains a reference to the MyKeys key container, which contains the recipient's private key. During the process, the Main method displays the original session key, the formatted exchange data, and finally the deformatted session key.

 using System; using System.Text; using System.Security.Cryptography; public class KeyExchangeExample {     // Main method not shown, see sample code for a complete listing          // Method to encrypt the symmetric session key and format it for     // key exchange. To encrypt the session key we need access to the      // RSA public key of the intended recipient, which is passed to the      // method contained in an RSAParameters structure. This key could have     // been sent to us, or we could have downloaded it from a key      // distribution service.      private static byte[] FormatKeyExchange(byte[] sessionKey,          RSAParameters rsaParams) {                  // Create an RSA asymmetric algorithm.         using (RSACryptoServiceProvider asymAlg =              new RSACryptoServiceProvider()) {                     // Import the recipient's public key to the algorithm.             asymAlg.ImportParameters(rsaParams);                          // Create an RSA OAEP formatter to format the key              // exchange data.             RSAOAEPKeyExchangeFormatter formatter                    = new RSAOAEPKeyExchangeFormatter();                  // Specify the RSA algorithm as the one to use to encrypt the              // session key.             formatter.SetKey(asymAlg);                  // Encrypt and format the session key and return the result.             return formatter.CreateKeyExchange(sessionKey);         }     }     // Method to decrypt the key exchange data and extract the symmetric      // session key. To decrypt the key exchange data, we need access to      // the RSA private key, which we access from the key container      // specified in the cspParams argument. This approach avoids the need     // to hold secret data in memory and pass it between methods.     private static byte[] DeformatKeyExchange(byte[] exchangeData,          CspParameters cspParams) {                     // Create an RSA asymmetric algorithm.         using (RSACryptoServiceProvider asymAlg =              new RSACryptoServiceProvider(cspParams)) {                      // Create an RSA OAEP deformatter to extract the session key             // from the key exchange data.             RSAOAEPKeyExchangeDeformatter deformatter                  = new RSAOAEPKeyExchangeDeformatter();                      // Specify the RSA algorithm as the one to use to decrypt the              // key exchange data.             deformatter.SetKey(asymAlg);             // Decrypt the key exchange data and return the session key.             return deformatter.DecryptKeyExchange(exchangeData);         }     } } 

Running KeyExchangeExample will generate console output similar to that shown here.

 Session Key at Source = EE-5B-16-5B-AC-46-3D-72-CC-73-19-D9-0B-8A-19-E2-A6- 02-13-BE-F8-CE-DF-40 Exchange Data = 60-FA-3B-63-41-25-F1-AD-08-F9-FC-67-CD-C6-FB-3E-0F-C3-62- C6-3F-5C-C0-7E-D1-60-2D-19-58-07-EE-BB-7C-53-A5-C2-FB-CA-D7-64-FF-BA-33-77- AC-52-87-5F-75-E7-57-99-01-90-CD-70-36-1E-53-0C-82-C6-CE-B8-BC-8B-C9-39-6F- 29-39-5F-6C-A6-43-E5-B0-A1-42-46-1C-9B-1C-72-EB-5E-67-06-44-C0-CE-AB-70-B8- 39-8E-9F-01-E8-49-51-36-D6-27-09-94-DA-42-CE-79-C2-72-88-4D-CE-63-B4-A0-AC- 07-AF-26-A7-76-DE-21-BE-A5 Session Key at Destination = EE-5B-16-5B-AC-46-3D-72-CC-73-19-D9-0B-8A-19- E2-A6-02-13-BE-F8-CE-DF-40 



C# Programmer[ap]s Cookbook
C# Programmer[ap]s Cookbook
ISBN: 735619301
EAN: N/A
Year: 2006
Pages: 266

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net