15.02.2015 Views

C# 4 and .NET 4

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

encryption ❘ 557<br />

}<br />

alicePubKeyBlob = aliceKey.Export(CngKeyBlobFormat.EccPublicBlob);<br />

bobPubKeyBlob = bobKey.Export(CngKeyBlobFormat.EccPublicBlob);<br />

In the method AliceSendsData(), the string that contains text characters is converted to a byte array<br />

by using the Encoding class. An ECDiffieHellmanCng object is created <strong>and</strong> initialized with the key pair<br />

from Alice. Alice creates a symmetric key by using her key pair <strong>and</strong> the public key from Bob calling the<br />

method DeriveKeyMaterial(). The returned symmetric key is used with the symmetric algorithm AES to<br />

encrypt the data. AesCryptoServiceProvider requires the key <strong>and</strong> an initialization vector (IV). The IV<br />

is generated dynamically from the method GenerateIV(). The symmetric key is exchanged with the help<br />

of the EC Diffie Hellman algorithm, but the IV must also be exchanged. From the security st<strong>and</strong>point, it is<br />

okay to transfer the IV unencrypted across the network — just the key exchange must be secured. The IV<br />

is stored first as content in the memory stream, followed by the encrypted data where the CryptoStream<br />

class uses the encryptor created by the AesCryptoServiceProvider class. Before the encrypted data is<br />

accessed from the memory stream, the crypto stream must be closed. Otherwise, end bits would be missing<br />

from the encrypted data.<br />

private static byte[] AliceSendsData(string message)<br />

{<br />

Console.WriteLine("Alice sends message: {0}", message);<br />

byte[] rawData = Encoding.UTF8.GetBytes(message);<br />

byte[] encryptedData = null;<br />

}<br />

using (var aliceAlgorithm = new ECDiffieHellmanCng(aliceKey))<br />

using (CngKey bobPubKey = CngKey.Import(bobPubKeyBlob,<br />

CngKeyBlobFormat.EccPublicBlob))<br />

{<br />

byte[] symmKey = aliceAlgorithm.DeriveKeyMaterial(bobPubKey);<br />

Console.WriteLine("Alice creates this symmetric key with " +<br />

"Bobs public key information: {0}",<br />

Convert.ToBase64String(symmKey));<br />

var aes = new AesCryptoServiceProvider();<br />

aes.Key = symmKey;<br />

aes.GenerateIV();<br />

using (ICryptoTransform encryptor = aes.CreateEncryptor())<br />

using (MemoryStream ms = new MemoryStream())<br />

{<br />

// create CryptoStream <strong>and</strong> encrypt data to send<br />

var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write);<br />

// write initialization vector not encrypted<br />

ms.Write(aes.IV, 0, aes.IV.Length);<br />

cs.Write(rawData, 0, rawData.Length);<br />

cs.Close();<br />

encryptedData = ms.ToArray();<br />

}<br />

aes.Clear();<br />

}<br />

Console.WriteLine("Alice: message is encrypted: {0}",<br />

Convert.ToBase64String(encryptedData));;<br />

Console.WriteLine();<br />

return encryptedData;<br />

Bob receives encrypted data in the argument of the method BobReceivesData(). First, the unencrypted<br />

initialization vector must be read. The BlockSize property of the class AesCryptoServiceProvider<br />

returns the number of bits for a block. The number of bytes can be calculated by doing a divide by 8, <strong>and</strong><br />

the fastest way to do this is by doing a bit shift of 3 bits. Shifting by 1 bit is a division by 2, 2 bits by 4,<br />

<strong>and</strong> 3 bits by 8. With the for loop, the first bytes of the raw bytes that contain the IV unencrypted are<br />

written to the array iv. Next, an ECDiffieHellmanCng object is instantiated with the key pair from Bob.<br />

Using the public key from Alice, the symmetric key is returned from the method DeriveKeyMaterial().<br />

www.it-ebooks.info

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!