Skip to main content

ECDH Key Exchange Examples

Purpose

The objective of an MTE ECDH "Examples" is to provide a short example of basic MTE Ecdh actions.

Simple demonstration of ECDH within one application.

using System.Text;

namespace Eclypses.MTE {
class Program {

//*******************************************************************
// Helper function to convert a byte array to a hex string.
//
// Overview: convert a byte array to an ASCII hex representation
// Input: pointer to the input byte array
// length of the input byte array
// pointer to the output byte array
// size of the output byte array
// Output: pointer to the output byte array (convenience result)
//*******************************************************************
private static string BytesToHex(byte[] input) {
const string hex = "0123456789ABCDEF";
StringBuilder sb = new();
sb.Clear();
int i = 0;
while (i < input.Length) {
sb.Append(hex[(input[i] >> 4) & 0xF]);
sb.Append(hex[input[i] & 0xF]);
i++;
}
return sb.ToString();
}

private static readonly byte[] publicKeyA = new byte[MteEcdh.SzPublicKey];
private static readonly byte[] secretA = new byte[MteEcdh.SzSecretData];
private static readonly byte[] publicKeyB = new byte[MteEcdh.SzPublicKey];
private static readonly byte[] secretB = new byte[MteEcdh.SzSecretData];

/*****************************************************
* Implementation of an application defined callback
* which is used to generate entropy for ecdhB and
* also to test the "zeroize" and "getRandom" methods.
****************************************************/
public class EcdhBCallback : IMteEcdhEntropyCallback {
public int EntropyCallback(byte[] entropyInput) {
if (entropyInput.Length != MteEcdh.SzPrivateKey)
return MteEcdh.MemoryFail;
Array.Fill(entropyInput, (byte)0xCC);
MteEcdh.Zeroize(entropyInput);
for (int i = 0; i < entropyInput.Length; i++)
if (entropyInput[i] != 0)
return MteEcdh.MemoryFail;
// Get random bytes.
byte[] temp = MteRandom.GetBytes((uint)entropyInput.Length);
if (temp.Length == 0) {
return MteEcdh.EntropyFail;
}

Array.Copy(temp, entropyInput, temp.Length);
return MteEcdh.Success;
}
}

/*************************************************
* Main program, loop through all the test vectors
* and print out results to the console.
************************************************/
static int Main() {

Console.WriteLine("Ecdh Add-On Demo");

MteEcdh ecdhA = new();

// Create key pair for ecdhA.
if (ecdhA.CreateKeyPair(publicKeyA) != MteEcdh.Success) {
Console.WriteLine("MteEcdh creating key pair A failed");
return -1;
}

string s = BytesToHex(publicKeyA);
Console.WriteLine("EcdhA public key: {0}", s[..MteEcdh.SzPublicKey]);
Console.WriteLine(" {0}", s[MteEcdh.SzPublicKey..]);

// Create key pair for ecdhB.
MteEcdh ecdhB = new();
EcdhBCallback ecdhBCallback = new();
ecdhB.SetEntropyCallback(ecdhBCallback);
if (ecdhB.CreateKeyPair(publicKeyB) != MteEcdh.Success) {
Console.WriteLine("MteEcdh creating key pair B failed");
return -1;
}

s = BytesToHex(publicKeyB);
Console.WriteLine("EcdhB public key: {0}", s[..MteEcdh.SzPublicKey]);
Console.WriteLine(" {0}", s[MteEcdh.SzPublicKey..]);

// Create secret for ecdhA.
if (ecdhA.CreateSecret(publicKeyB, secretA) != MteEcdh.Success) {
Console.WriteLine("MteEcdh creating secret A failed.");
return -1;
}
Console.WriteLine("EcdhA secret: {0}", BytesToHex(secretA));

// Create secret for ecdhB.
if (ecdhB.CreateSecret(publicKeyA, secretB) != MteEcdh.Success) {
Console.WriteLine("MteEcdh creating secret B failed.");
return -1;
}
Console.WriteLine("EcdhB secret: {0}", BytesToHex(secretB));

Console.Write("Pairing secrets: ");
if (!secretA.SequenceEqual(secretB)) {
Console.WriteLine("No match");
return -1;
} else {
Console.WriteLine("Match");
}

return 0;
}
}
}