using System.Security.Cryptography;
public static byte[] alicePublicKey;
public static void Main(string[] args)
Participant alice = new Participant("Alice");
Participant bob = new Participant("Bob");
alice.Send(bob, "VERY SECRET MESSAGE");
public readonly String name;
protected readonly ECDiffieHellmanCng ecdh;
public Participant(String name)
Console.WriteLine("[" + name + "] Creating ECDH");
ecdh = new ECDiffieHellmanCng();
ecdh.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
ecdh.HashAlgorithm = CngAlgorithm.Sha256;
public byte[] GetPublicKey()
byte[] pk = ecdh.PublicKey.ToByteArray();
Console.WriteLine("[" + name + "] Returning my PK: '" + BitConverter.ToString(pk) + "'");
public void Send(Participant receiver, String message)
Console.WriteLine("[" + name + "] Sending message '" + message + "'");
byte[] secretKey = DeriveKey(receiver.GetPublicKey());
Console.WriteLine("[" + name + "] Derived shared key from " + receiver.name + "'s PK and " + name + "'s SK: '" + BitConverter.ToString(secretKey) + "'");
Payload p = Encrypt(secretKey, message);
Console.WriteLine("[" + name + "] Encrypted '" + message + "' into '" + BitConverter.ToString(p.encrypted) + "'");
receiver.Receive(this, p);
public void Receive(Participant sender, Payload payload)
Console.WriteLine("[" + name + "] Received encrypted message '" + BitConverter.ToString(payload.encrypted) + "'");
byte[] secretKey = DeriveKey(sender.GetPublicKey());
Console.WriteLine("[" + name + "] Derived shared key from " + sender.name + "'s PK and " + name + "'s SK: '" + BitConverter.ToString(secretKey) + "'");
String message = Decrypt(secretKey, payload);
Console.WriteLine("[" + name + "] Decrypted into: '" + message + "'");
private byte[] DeriveKey(byte[] otherPublicKey)
return ecdh.DeriveKeyMaterial(CngKey.Import(otherPublicKey, CngKeyBlobFormat.EccPublicBlob));
private Payload Encrypt(byte[] key, string message)
using (Aes aes = new AesCryptoServiceProvider())
using (MemoryStream ciphertext = new MemoryStream())
using (CryptoStream cs = new CryptoStream(ciphertext, aes.CreateEncryptor(), CryptoStreamMode.Write))
byte[] plaintextMessage = Encoding.UTF8.GetBytes(message);
cs.Write(plaintextMessage, 0, plaintextMessage.Length);
byte[] encryptedMessage = ciphertext.ToArray();
return new Payload(encryptedMessage, iv);
private String Decrypt(byte[] secretKey, Payload payload)
using (Aes aes = new AesCryptoServiceProvider())
using (MemoryStream plaintext = new MemoryStream())
using (CryptoStream cs = new CryptoStream(plaintext, aes.CreateDecryptor(), CryptoStreamMode.Write))
cs.Write(payload.encrypted, 0, payload.encrypted.Length);
return Encoding.UTF8.GetString(plaintext.ToArray());
public readonly byte[] encrypted;
public readonly byte[] iv;
public Payload(byte[] encrypted, byte[] iv)
this.encrypted = encrypted;