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));