3. Key Exchange Formatting
The .NET Framework includes classes specifically for exchanging session keys
using asymmetric encryption. The process for encrypting a key value
is as follows:
Create a new instance of the appropriate symmetric algorithm class
and create a new session key.
Create a new instance of an asymmetric algorithm class and import the
public key that you wish to use to encrypt the session key value.
Create a new instance of a key exchange formatter and specify the
asymmetric class created in the previous step.
Encrypt the session key value using the key exchange formatter.
The formatter class is responsible for preparing the session key data
prior to encryption with the asymmetric algorithm. Figure 3 illustrates the .NET class hierarchy for key
exchange formatter classes. The .NET class library includes
formatting classes for the RSA algorithm; the DSA algorithm is not
suitable for session key exchange since it does not support data
encryption.
Two formatting schemes are supported—the OAEP scheme is
preferred. The second scheme, PKCS #1 v1.5, is included for
compatibility with legacy systems. The formatting scheme is used to
protect the session key value from specific attacks, but it is not
essential that you understand the details of the formatting schemes
available, only that you know how to use them. Table 3
summarizes
the members of the abstract
AsymmetricExchangeFormatter class.
Table 3. AsymmetricExchangeFormatter members
Member
|
Description
|
---|
Properties
| |
SetKey
|
Sets the instance of the asymmetric algorithm implementation class to
encrypt the session key
|
CreateKeyExchange
|
Encrypts a session key, expressed as an array of bytes
|
Methods
| |
Parameters
|
Returns the parameters of the key used to encrypt the session key
|
Example 1 statements demonstrate how to create and
format a 128-bit Rijndael session key using the RSA algorithm and the
OAEP formatting scheme:
Example 17-1. bit Rijndael session key
# C#
// create an instance of the Rijndael algorithm and // specify 128-bits as the key length Rijndael x_rijndael = Rijndael.Create( ); x_rijndael.KeySize = 128;
// rely on the fact that the algorithm implementation // class will create a new key to obtain the session value byte[] x_session_key = x_rijndael.Key;
// create an instance of the RSA algorithm class RSA x_rsa = new RSACryptoServiceProvider( );
// // ... specify public key to encrypt with //
// create a new instance of the RSA OAEP formatter RSAOAEPKeyExchangeFormatter x_formatter = new RSAOAEPKeyExchangeFormatter( );
// specify the RSA instance we created as the one // to use when encrypting the session key data x_formatter.SetKey(x_rsa);
// encrypt the session key with the formatter byte[] x_exchange_data = x_formatter.CreateKeyExchange(x_session_key);
// write out the encrypted data foreach (byte b in x_exchange_data) { Console.Write("{0:X2} ", b); }
# Visual Basic .NET
' create an instance of the Rijndael algorithm and ' specify 128-bits as the key length Dim x_rijndael As Rijndael = Rijndael.Create( ) x_rijndael.KeySize = 128
' rely on the fact that the algorithm implementation ' class will create a new key to obtain the session value Dim x_session_key( ) As Byte = x_rijndael.Key
' create an instance of the RSA algorithm class Dim x_rsa As RSA = New RSACryptoServiceProvider( )
' ' ... specify public key to encrypt with '
' create a new instance of the RSA OAEP formatter Dim x_formatter As RSAOAEPKeyExchangeFormatter = New RSAOAEPKeyExchangeFormatter( ) ' specify the RSA instance we created as the one ' to use when encrypting the session key data x_formatter.SetKey(x_rsa)
' encrypt the session key with the formatter Dim x_exchange_data( ) As Byte = x_formatter.CreateKeyExchange(x_session_key)
' write out the encrypted data Dim b As Byte For Each b In x_exchange_data Console.Write("{0:X2} ", b) Next
|
The output below shows an example of the formatted exchange data; the
data will change each time the statements are executed, because a new
session key will have been created at random by the Rijndael class:
C5 3B 7F 1C 44 B9 DF 3C C6 7F 7E 18 3E E7 F9 15 2E 0C B3 2A EF EC 4C EF 45 1D 51
B8 CC D1 FB C8 7F 8B A8 4F 58 92 76 20 61 13 C1 A2 4E 06 50 9A E2 0E 97 34 8A C7
19 8C 21 59 67 30 3A 57 9A E3 B9 4C 5F 56 4F 10 54 1A 83 5B 45 1A 4F 39 A9 C4 64
C2 11 5C 82 6D E1 A9 F3 BD F3 79 87 EA 13 52 2B EF 5F 71 8B 82 08 F6 9D 57 88 43
42 AE 75 E4 DD B9 BD 52 0F DB CD 86 E7 D2 17 0F 2F DB BF A8
The output is sent to the person with whom you wish to exchange
confidential messages. Notice that the encrypted session key is much
longer than the 20 bytes that make up the 128-bit Rijndael session
key; this is a result of the padding added to the session key during
the formatting process; the encrypted data is always the same length
to prevent revealing the length of the session key to eavesdroppers.
Figure 4 illustrates the hierarchy for the
classes that decrypt the exchange data and restore the session key
value by removing the formatting.
The process for decrypting a key value is as follows:
Create a new instance of an asymmetric algorithm class and import the
private key that you wish to use to decrypt the formatted exchange
data.
Create a new instance of a key exchange deformatter and specify the
asymmetric class created in the previous step.
Decrypt the formatted exchange data using the key exchange
deformatter.
Create a new instance of the appropriate symmetric algorithm class
and set the session key.
Table 4 summarizes
the
members of the abstract
AsymmetricExchangeDeformatter class.
Table 4. AsymmetricExchangeDeformatter members
Member
|
Description
|
---|
Properties
| |
SetKey
|
Sets the instance of the asymmetric algorithm implementation class to
decrypt the exchange data
|
DecryptKeyExchange
|
Decrypts exchange data, expressed as an array of bytes
|
Methods
| |
Parameters
|
Returns the parameters of the key used to decrypt the exchange data
|
The following statements demonstrate how to decrypt the exchange data
from the previous example to restore the session key:
# C#
byte[] x_exchange_data = new byte[] {0xC5, 0x3B, 0x7F, 0x1C, 0x44, 0xB9, 0xDF,
0x3C, 0xC6, 0x7F, 0x7E, 0x18, 0x3E, 0xE7, 0xF9, 0x15, 0x2E, 0x0C, 0xB3,
0x2A, 0xEF, 0xEC, 0x4C, 0xEF, 0x45, 0x1D, 0x51, 0xB8, 0xCC, 0xD1, 0xFB,
0xC8, 0x7F, 0x8B, 0xA8, 0x4F, 0x58, 0x92, 0x76, 0x20, 0x61, 0x13, 0xC1,
0xA2, 0x4E, 0x06, 0x50, 0x9A, 0xE2, 0x0E, 0x97, 0x34, 0x8A, 0xC7, 0x19,
0x8C, 0x21, 0x59, 0x67, 0x30, 0x3A, 0x57, 0x9A, 0xE3, 0xB9, 0x4C, 0x5F,
0x56, 0x4F, 0x10, 0x54, 0x1A, 0x83, 0x5B, 0x45, 0x1A, 0x4F, 0x39, 0xA9,
0xC4, 0x64, 0xC2, 0x11, 0x5C, 0x82, 0x6D, 0xE1, 0xA9, 0xF3, 0xBD, 0xF3,
0x79, 0x87, 0xEA, 0x13, 0x52, 0x2B, 0xEF, 0x5F, 0x71, 0x8B, 0x82, 0x08,
0xF6, 0x9D, 0x57, 0x88, 0x43, 0x42, 0xAE, 0x75, 0xE4, 0xDD, 0xB9, 0xBD,
0x52, 0x0F, 0xDB, 0xCD, 0x86, 0xE7, 0xD2, 0x17, 0x0F, 0x2F, 0xDB, 0xBF,
0xA8};
// create an instance of the RSA algorithm class
RSA x_rsa = new RSACryptoServiceProvider( );
//
// ... specify private key to decrypt with
//
// create a new instance of the RSA OAEP deformatter
RSAOAEPKeyExchangeDeformatter x_deformatter
= new RSAOAEPKeyExchangeDeformatter( );
// specify the RSA instance we created as the one
// to use when encrypting the session key data
x_deformatter.SetKey(x_rsa);
// decrypt the exchange data with the deformatter to
// obtain the Rijndael session key
byte[] x_session_key = x_deformatter.DecryptKeyExchange(x_exchange_data);
// create an instance of the Rijndael algorithm
Rijndael x_rijndael = Rijndael.Create( );
// set the session key
x_rijndael.Key = x_session_key;
# Visual Basic .NET
Dim x_exchange_data( ) As Byte = New Byte( ) {&HC5, &H3B, &H7F, &H1C, &H44, &HB9, _
&HDF, &H3C, &HC6, &H7F, &H7E, &H18, &H3E, &HE7, &HF9, &H15, &H2E, &HC, &HB3, _
&H2A, &HEF, &HEC, &H4C, &HEF, &H45, &H1D, &H51, &HB8, &HCC, &HD1, &HFB, _
&HC8, &H7F, &H8B, &HA8, &H4F, &H58, &H92, &H76, &H20, &H61, &H13, &HC1, _
&HA2, &H4E, &H6, &H50, &H9A, &HE2, &HE, &H97, &H34, &H8A, &HC7, &H19, _
&H8C, &H21, &H59, &H67, &H30, &H3A, &H57, &H9A, &HE3, &HB9, &H4C, &H5F, _
&H56, &H4F, &H10, &H54, &H1A, &H83, &H5B, &H45, &H1A, &H4F, &H39, &HA9, _
&HC4, &H64, &HC2, &H11, &H5C, &H82, &H6D, &HE1, &HA9, &HF3, &HBD, &HF3, _
&H79, &H87, &HEA, &H13, &H52, &H2B, &HEF, &H5F, &H71, &H8B, &H82, &H8, _
&HF6, &H9D, &H57, &H88, &H43, &H42, &HAE, &H75, &HE4, &HDD, &HB9, &HBD, _
&H52, &HF, &HDB, &HCD, &H86, &HE7, &HD2, &H17, &HF, &H2F, &HDB, &HBF, _
&HA8}
' create an instance of the RSA algorithm class
Dim x_rsa As RSA = New RSACryptoServiceProvider( )
'
' ... specify private key to decrypt with
'
' create a new instance of the RSA OAEP deformatter
Dim x_deformatter As RSAOAEPKeyExchangeDeformatter _
= New RSAOAEPKeyExchangeDeformatter( )
' specify the RSA instance we created as the one
' to use when encrypting the session key data
x_deformatter.SetKey(x_rsa)
' decrypt the exchange data with the deformatter to
' obtain the Rijndael session key
Dim x_session_key( ) As Byte = x_deformatter.DecryptKeyExchange(x_exchange_data)
' create an instance of the Rijndael algorithm
Dim x_rijndael As Rijndael = Rijndael.Create( )
' set the session key
x_rijndael.Key = x_session_key