The second elliptic curve algorithm added to Orcas is elliptic curve Diffie-Hellman, as the ECDiffieHellmanCng class.
This is the first time Diffie-Hellman is available as part of the .NET Framework, so lets take a quick look at what it is and what it does. Diffie-Hellman is one of the oldest asymmetric algorithms, however unlike the other asymmetric algorithms in the framework today, it does not perform encryption or digital signatures. Instead it allows two parties to exchange private key material even if they only can communicate through a completely public channel. (In Network Security: Private Communication in a Public World, an amusing example is given where Diffie-Hellman is performed by two parties taking out ads in the local newspaper).
Key exchange is somewhat of a misleading term, since it implies that one party to the communication generates a key and via the communication protocol lets the other party know what that key is. Instead what really happens is that Diffie-Hellman allows both parties to calculate the same secret value, which is referred to as the secret agreement in the managed Diffie-Hellman classes. This secret agreement can then be used for any number of purposes, including being used as a symmetric key.
Instead of exposing the secret agreement directly however, the ECDiffieHellmanCng class does some post-processing on the agreement before letting the value out. We refer to this post processing as the key derivation function; you can select which KDF you want to use and set its parameters via a set of properties on the instance of the Diffie-Hellman object:
The result of passing the secret agreement through the key derivation function is a byte array that may be used as key material for your application. The number of bytes of key material generated is dependent on the key derivation function, for instance SHA-256 will generate 256 bits of key material, while SHA-512 will generate 512 bits of key material.
The basic flow of an elliptic curve Diffie-Hellman key exchange is:
In code, this looks basically as you would expect:
ECDiffieHellmanCng alice = new ECDiffieHellmanCng();
alice.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
alice.HashAlgorithm = CngAlgorithm.Sha256;
ECDiffieHellmanCng bob = new ECDiffieHellmanCng();
bob.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
bob.HashAlgorithm = CngAlgorithm.Sha256;
byte bobKey = bob.DeriveKeyMaterial(alice.PublicKey);
byte aliceKey = alice.DeriveKeyMaterial(bob.PublicKey);
After running this code, aliceKey and bobKey are both 32 bytes long and match each other. Now, Alice could use this as a symmetric key:
AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
aes.Key = aliceKey;
Obviously, this example is simplified as both Alice and Bob are unlikely to be running in the same process. ECDiffieHellmanPublicKey, which is the class returned by the PublicKey property is Serializable, so that it may be sent across any remoting channel. It also can be manually converted to and from a byte array and XML, allowing for manual serialization in advanced use cases.
One thing to note about Diffie-Hellman is that it only guarantees that both parties are generating a secret that nobody else knows about. It does not let either party know the identity of the other. For instance, in the above code, Alice cannot be sure that the other person in the conversation is Bob; there could potentially be a man-in-the-middle attack here.
In order to solve that, Alice or Bob could use a well-known public key that is distributed by PKI (you can pass a CngKey to the DeriveKeyMaterial API in this case). You could also use HMAC as the KDF and a key that you know only Alice and Bob share to solve this problem.