The “parameters” are an instance of DiffieHellmanParameters, which is a simple structure:
public struct DiffieHellmanParameters
{
// The generator.
public byte[] G;
// The prime modulus.
public byte[] P;
// The private key.
public byte[] X;
// The public key.
public byte[] Y;
}
Both the parameters and keys are byte arrays. You can convert them to strings for transport if needed, and then back to byte arrays on the other side. Using Convert.ToBase64String/Convert.FromBase64String is the most simple choice, writing a hexadecimal string encoder/parser is another possibility.
Just like any instance of .NET’s AsymmetricAlgorithm object, DiffieHellmanCryptoServiceProvider generates a key pair and optionally the parameters unless imported.
Calling alice.ExportParameters(false) generates parameters and key pair and returns an instance of DiffieHellmanParameters with only G (generator), P (prime) and Y set (public key – the same value you get by calling alice.GetPublicKey()).
Calling bob.ImportParameters(parameters) imports P and G. It generates a new key pair (using the same generator and prime) unless both Y and X are present as well.
This is another variant of the sample code that is easier to follow – P and G are generated at the beginning and the rest of the code is the same for Alice and Bob:
// parameters
byte[] P;
byte[] G;
// generate P (prime) and G (generator)
// (alternatively, you could you pre-generated P and G)
using (var tmp = new DiffieHellmanCryptoServiceProvider())
{
var parameters = tmp.ExportParameters(false);
P = parameters.P;
G = parameters.G;
}
// machine A: import parameters, generate ephemeral keypair for 'Alice', and get her public key
var inputParamsAlice= new DiffieHellmanParameters();
inputParamsAlice.P = P;
inputParamsAlice.G = G;
var alice = new DiffieHellmanCryptoServiceProvider();
alice.ImportParameters(inputParamsAlice);
byte[] publicKeyAlice = alice.GetPublicKey();
// machine B: import parameters, generate ephemeral keypair for 'Alice', and get her public key
var inputParamsBob = new DiffieHellmanParameters();
inputParamsBob.P = P;
inputParamsBob.G = G;
var bob = new DiffieHellmanCryptoServiceProvider();
bob.ImportParameters(inputParamsBob);
byte[] publicKeyBob = bob.GetPublicKey();
// machine A: compute shared key from Alice's private key and Bob's public key
byte[] sharedKeyA = alice.GetSharedSecretKey(publicKeyBob);
// machine B: compute shared key from Bob's private key and Alices's public key
byte[] sharedKeyB = bob.GetSharedSecretKey(publicKeyAlice);
// result of both computations is the same shared key
Console.WriteLine(BitConverter.ToString(sharedKeyA));
Console.WriteLine(BitConverter.ToString(sharedKeyB));