Diffie-Hellman Key Exchange Samples
Purpose
There are many different ways to exchange information to pair the two devices using the MTE. One way to exchange information when in a zero-knowledge environment is by using the Diffie-Hellman key exchange as a secure way to generate MTE entropy. This sample demonstrates how to use a Diffie-Hellman Algorithm to exchange the public key values between two different devices, then each side uses this value and their own private keys to generate a value that will be the same for these two devices that then can be used for entropy.
The Diffie-Hellman Key exchange does not depend on the communication type used, it is a secure algorithm where public keys can be exchanged between devices to then compute a "secret key" that will be unique and secure as long as the private data on each device is not shared or available to outside sources. For more information about the Diffie-Hellman Key exchange please click here.
Below is a visual representation of the Diffie-Hellman functionality:
Public Key Exchange using Diffie-Hellman
Here is an example of how to use the Diffie-Hellman key exchange to exchange the public keys when pairing devices with the MTE.
Encoder Device Side
- C
- C++
- CSharp
- Java
- Swift
- ObjC
- TypeScript
- Python
- Go
#include "mtesupport_ecdh.h"
byte_array get_entropy_for_MTE_encoder()
{
// Create private and public keys.
byte_array private_key;
private_key.size = SZ_ECDH_P256_PRIVATE_KEY;
private_key.data = ECDH_ALLOCA(SZ_ECDH_P256_PRIVATE_KEY);
byte_array public_key;
public_key.size = SZ_ECDH_P256_PUBLIC_KEY;
public_key.data = ECDH_ALLOCA(SZ_ECDH_P256_PUBLIC_KEY);
int res = ecdh_p256_create_keypair(&private_key, &public_key, NULL, NULL);
// Check for private and public key success.
if (res != ECDH_P256_SUCCESS)
{
printf("Unable to create key pair: %i\n", res);
byte_array temp;
temp.size = 0;
temp.data = NULL;
return temp;
}
// Send public key to Decoder side and get back
// Decoder side public key.
//---------------------------------------------------------
// This method is not included in this sample!!!
// This is here only to demonstrate that the user MUST
// send the public key to other side and receive back the
// public key from the other side.
//---------------------------------------------------------
const byte_array partner_public_key = send_public_key_get_partner_public_key(public_key);
// Create the shared secret with the public key received from the Decoder.
byte_array shared_secret;
shared_secret.size = SZ_ECDH_P256_SECRET_DATA;
shared_secret.data = ECDH_ALLOCA(SZ_ECDH_P256_SECRET_DATA);
res = ecdh_p256_create_secret(private_key, partner_public_key, &shared_secret);
if (res != ECDH_P256_SUCCESS)
{
printf("Unable to create shared secret: %i\n", res);
byte_array temp;
temp.size = 0;
temp.data = NULL;
return temp;
}
// Return the shared secret so that it can bes used as the entropy value
// when creating the MTE Encoder within the calling program.
return shared_secret;
}
#include "EcdhP256.h"
byte_array getEntropyForMTEEncoder()
{
// Create Eclypses DH.
EcdhP256 ecdh;
// Create key pair and retrieve the public key.
byte_array publicKey;
publicKey.size = EcdhP256::SzPublicKey;
publicKey.data = (uint8_t*)(ECDH_ALLOCA(EcdhP256::SzPublicKey));
int res = ecdh.createKeyPair(publicKey);
if (res < 0)
{
throw std::exception("Unable to create key pair: %i", res);
}
// Send public key to Decoder side and get back
// Decoder side public key.
//---------------------------------------------------------
// This method is not included in this sample!!!
// This is here only to demonstrate that the user MUST
// send the public key to other side and receive back the
// public key from the other side.
//---------------------------------------------------------
byte_array partnerPublicKey = sendPublicKeyGetPartnerPublicKey(publicKey);
// Create the shared secret with the public key received from the Decoder.
byte_array sharedSecret;
sharedSecret.size = EcdhP256::SzPublicKey;
sharedSecret.data = (uint8_t*)(ECDH_ALLOCA(EcdhP256::SzPublicKey));
res = ecdh.getSharedSecret(partnerPublicKey, sharedSecret);
if (res < 0) {
throw std::exception("Unable to create shared secret: %i", res);
}
// Return the shared secret so it can be used as the entropy value
// when creating the MTE Encoder within the calling program.
return sharedSecret;
}
using Eclypses.EcdhP256;
public byte[] GetEntropyForMTEEncoder() {
// Create Eclypses DH.
EcdhP256 ecdh = new EcdhP256();
// Create key pair and retrieve the public key.
byte[] publicKey = new byte[EcdhP256.SzPublicKey];
int res = ecdh.CreateKeyPair(publicKey);
if (res < 0) {
throw new Exception("Unable to create key pair: " + res);
}
// Send public key to Decoder side and get back
// Decoder side public key.
//---------------------------------------------------------
// This method is not included in this sample!!!
// This is here only to demonstrate that the user MUST
// send the public key to other side and receive back the
// public key from the other side.
//---------------------------------------------------------
byte[] partnerPublicKey = SendPublicKeyGetPartnerPublicKey(publicKey);
// Create the shared secret with the public key received from the Decoder.
byte[] sharedSecret = new byte[EcdhP256.SzSecretData];
res = ecdh.GetSharedSecret(partnerPublicKey, sharedSecret);
if (res < 0) {
throw new Exception("Unable to create shared secret: " + res);
}
// Return the shared secret so it can be used as the entropy value
// when creating the MTE Encoder within the calling program.
return sharedSecret;
}
import com.eclypses.ecdh.EcdhP256;
public byte[] getEntropyForMTEEncoder() {
// Create Eclypses DH.
EcdhP256 ecdh;
// Create key pair and retrieve the public key.
byte[] publicKey = new byte[EcdhP256.SzPublicKey];
int res = ecdh.createKeyPair(publicKey);
if (res < 0) {
throw new Exception("Unable to create key pair: " + res);
}
// Send public key to Decoder side and get back
// Decoder side public key.
//---------------------------------------------------------
// This method is not included in this sample!!!
// This is here only to demonstrate that the user MUST
// send the public key to other side and receive back the
// public key from the other side.
//---------------------------------------------------------
byte[] partnerPublicKey = sendPublicKeyGetPartnerPublicKey(publicKey);
// Create the shared secret with the public key received from the Decoder.
byte[] sharedSecret = new byte[EcdhP256.SzSecretData];
res = ecdh.getSharedSecret(partnerPublicKey, sharedSecret);
if (res < 0) {
throw new Exception("Unable to create shared secret: " + res);
}
// Return the shared secret so it can be used as the entropy value
// when creating the MTE Encoder within the calling program.
return sharedSecret;
}
func getEntropyForMTEEncoder() throws -> [uint8] {
// Create Eclypses DH.
var ecdh: EcdhP256 = EcdhP256(name: "")
// Create key pair and retrieve the public key.
let res: (status:Int, publicKey:[uint8]?) = ecdh.createKeyPair()
if res.status != EcdhP256.ResultCodes.success {
print("Unable to create key pair: \(res.status)")
var temp: [uint8] = []
return temp
}
// Send public key to Decoder side and get back
// Decoder side public key.
//---------------------------------------------------------
// This method is not included in this sample!!!
// This is here only to demonstrate that the user MUST
// send the public key to other side and receive back the
// public key from the other side..0
//---------------------------------------------------------
let partnerPublicKey = sendPublicKeyGetPartnerPublicKey(publicKey: res.publicKey ?? [])
// Create the shared secret with the public key received from the Decoder.
var sharedSecret:[uint8] = []
let res2:Int = ecdh.getSharedSecret(peerPublicKey: partnerPublicKey, secret: &sharedSecret)
if res2 != EcdhP256.ResultCodes.success {
print("Unable to create shared secret: \(res2)")
var temp: [uint8] = []
return temp
}
// Return the shared secret so it can be used as the entropy value
// when creating the MTE Encoder within the calling program.
return sharedSecret
}
+(NSMutableArray*)getEntropyForMTEEncoder {
// Create Eclypses DH.
EcdhP256 *ecdh = [[EcdhP256 alloc]initWithName:@""];
// Create key pair and retrieve the public key.
NSMutableArray *publicKey = [NSMutableArray arrayWithCapacity:PublicKeySize];
int res = [ecdh createKeyPair:publicKey];
if (res != Success) {
printf("Unable to create key pair: %i.", res);
exit(EXIT_FAILURE);
}
// Send public key to Decoder side and get back
// Decoder side public key.
//---------------------------------------------------------
// This method is not included in this sample!!!
// This is here only to demonstrate that the user MUST
// send the public key to other side and receive back the
// public key from the other side..0
//---------------------------------------------------------
NSMutableArray *partnerPublicKey = [self sendPublicKeyGetPartnerPublicKey];
// Create the shared secret with the public key received from the Decoder.
NSMutableArray *sharedSecret =[NSMutableArray arrayWithCapacity:SecretDataSize];
res = [ecdh getSharedSecret:partnerPublicKey :sharedSecret];
if (res != Success) {
printf("Unable to create shared secret: %i.", res);
exit(EXIT_FAILURE);
}
// Return the shared secret so it can be used as the entropy value
// when creating the MTE Encoder within the calling program.
return sharedSecret;
}
import { EcdhP256, EcdhStatus } from './ecdhp256';
const getEntropyForMTEEncoder = () => {
// Create Eclypses DH
const ecdh = new EcdhP256();
// Get public key
const publicKey = ecdh.createKeyPair();
// Check for public key success
if (publicKey.status !== EcdhStatus.success) {
throw new Error(`Unable to create key pair: ${publicKey.status}`);
}
// Send public key to Decoder side and get back
// Decoder side public key
//---------------------------------------------------------
// This method is not included in this sample!!!
// This is here only to demonstrate that the user MUST
// send the public key to other side and receive back the
// public key from the other side
//---------------------------------------------------------
const partnerPublicKey = sendPublicKeyGetPartnerPublicKey(publicKey);
// Create the shared secret with the public key received from the Decoder
const sharedSecret = ecdh.getSharedSecret(partnerPublicKey);
if (sharedSecret.status !== EcdhStatus.success) {
throw new Error(`Unable to create shared secret: ${sharedSecret.status}`);
}
// Return the shared secret so it can be used as the entropy value
// when creating the MTE Encoder within the calling program
return sharedSecret;
}
import EcdhP256
def get_entropy_for_MTE_encoder():
# Create Eclypses DH.
ecdh = EcdhP256.EcdhP256()
# Create key pair and retrieve the public key.
publicKey = bytearray(EcdhP256.SzPublicKey)
res = ecdh.create_keypair(publicKey)
if res < 0:
print("Unable to create key pair: " + str(res))
# Send public key to Decoder side and get back
# Decoder side public key.
#---------------------------------------------------------
# This method is not included in this sample!!!
# This is here only to demonstrate that the user MUST
# send the public key to other side and receive back the
# public key from the other side.
#---------------------------------------------------------
partnerPublicKey = send_public_key_get_partner_public_key(publicKey)
# Create the shared secret with the public key received from the Decoder.
sharedSecret = bytearray(EcdhP256.SzSecretData);
res = ecdh.get_shared_secret(partnerPublicKey, sharedSecret)
if res < 0:
print("Unable to create shared secret: " + str(res))
# Return the shared secret so it can be used as the entropy value
# when creating the MTE Encoder within the calling program.
return sharedSecret
import "goEcdhDemo/ecdh"
func GetEntropyForMTEEncoder() []byte {
// Create Eclypses DH.
var ecdhA = ecdh.NewEcdhP256Def()
// Create key pair and retrieve the public key.
var publicKey = make([]byte, ecdh.SZ_PUBLIC_KEY)
var res int = 0
res, publicKey = ecdhA.CreateKeypair()
if res != ecdh.SUCCESS {
fmt.Printf("Unable to create key pair: %v", res)
var temp []byte
return temp
}
// Send public key to Decoder side and get back
// Decoder side public key.
//---------------------------------------------------------
// This method is not included in this sample!!!
// This is here only to demonstrate that the user MUST
// send the public key to other side and receive back the
// public key from the other side.
//---------------------------------------------------------
partnerPublicKey := SendPublicKeyGetPartnerPublicKey(publicKey)
// Create the shared secret with the public key received from the Decoder.
var sharedSecret = make([]byte, ecdh.SZ_SECRET_DATA)
res, sharedSecret = ecdhA.GetSharedSecret(partnerPublicKey)
if res != ecdh.SUCCESS {
fmt.Printf("Unable to create shared secret: %v", res)
var temp []byte
return temp
}
// Return the shared secret so it can be used as the entropy value
// when creating the MTE Encoder within the calling program.
return sharedSecret
}
Decoder Device Side
- C
- C++
- CSharp
- Java
- Swift
- ObjC
- TypeScript
- Python
- Go
#include "mtesupport_ecdh.h"
byte_array get_entropy_for_MTE_decoder()
{
// Create private and public keys.
byte_array private_key;
private_key.size = SZ_ECDH_P256_PRIVATE_KEY;
private_key.data = ECDH_ALLOCA(SZ_ECDH_P256_PRIVATE_KEY);
byte_array public_key;
public_key.size = SZ_ECDH_P256_PUBLIC_KEY;
public_key.data = ECDH_ALLOCA(SZ_ECDH_P256_PUBLIC_KEY);
int res = ecdh_p256_create_keypair(&private_key, &public_key, NULL, NULL);
// Check for private and public key success.
if (res != ECDH_P256_SUCCESS)
{
printf("Unable to create key pair: %i\n", res);
byte_array temp;
temp.size = 0;
temp.data = NULL;
return temp;
}
// Send public key to Encoder side and get back
// Encoder side public key.
//---------------------------------------------------------
// This method is not included in this sample!!!
// This is here only to demonstrate that the user MUST
// send the public key to other side and receive back the
// public key from the other side.
//---------------------------------------------------------
const byte_array partner_public_key = send_public_key_get_partner_public_key(public_key);
// Create the shared secret with the public key received from the Encoder.
byte_array shared_secret;
shared_secret.size = SZ_ECDH_P256_SECRET_DATA;
shared_secret.data = ECDH_ALLOCA(SZ_ECDH_P256_SECRET_DATA);
res = ecdh_p256_create_secret(private_key, partner_public_key, &shared_secret);
if (res != ECDH_P256_SUCCESS)
{
printf("Unable to create shared secret: %i\n", res);
byte_array temp;
temp.size = 0;
temp.data = NULL;
return temp;
}
// Return the shared secret so that it can bes used as the entropy value
// when creating the MTE Decoder within the calling program.
return shared_secret;
}
#include "EcdhP256.h"
byte_array getEntropyForMTEDecoder()
{
// Create Eclypses DH.
EcdhP256 ecdh;
// Create key pair and retrieve the public key.
byte_array publicKey;
publicKey.size = EcdhP256::SzPublicKey;
publicKey.data = (uint8_t*)(ECDH_ALLOCA(EcdhP256::SzPublicKey));
int res = ecdh.createKeyPair(publicKey);
if (res < 0)
{
throw std::exception("Unable to create key pair: %i", res);
}
// Send public key to Encoder side and get back
// Encoder side public key.
//---------------------------------------------------------
// This method is not included in this sample!!!
// This is here only to demonstrate that the user MUST
// send the public key to other side and receive back the
// public key from the other side.
//---------------------------------------------------------
byte_array partnerPublicKey = sendPublicKeyGetPartnerPublicKey(publicKey);
// Create the shared secret with the public key received from the Encoder.
byte_array sharedSecret;
sharedSecret.size = EcdhP256::SzPublicKey;
sharedSecret.data = (uint8_t*)(ECDH_ALLOCA(EcdhP256::SzPublicKey));
res = ecdh.getSharedSecret(partnerPublicKey, sharedSecret);
if (res < 0) {
throw std::exception("Unable to create shared secret: %i", res);
}
// Return the shared secret so it can be used as the entropy value
// when creating the MTE Decoder within the calling program.
return sharedSecret;
}
using Eclypses.EcdhP256;
public byte[] GetEntropyForMTEEncoder() {
// Create Eclypses DH.
EcdhP256 ecdh = new EcdhP256();
// Create key pair and retrieve the public key.
byte[] publicKey = new byte[EcdhP256.SzPublicKey];
int res = ecdh.CreateKeyPair(publicKey);
if (res < 0) {
throw new Exception("Unable to create key pair: " + res);
}
// Send public key to Decoder side and get back
// Decoder side public key.
//---------------------------------------------------------
// This method is not included in this sample!!!
// This is here only to demonstrate that the user MUST
// send the public key to other side and receive back the
// public key from the other side.
//---------------------------------------------------------
byte[] partnerPublicKey = SendPublicKeyGetPartnerPublicKey(publicKey);
// Create the shared secret with the public key received from the Decoder.
byte[] sharedSecret = new byte[EcdhP256.SzSecretData];
res = ecdh.GetSharedSecret(partnerPublicKey, sharedSecret);
if (res < 0) {
throw new Exception("Unable to create shared secret: " + res);
}
// Return the shared secret so it can be used as the entropy value
// when creating the MTE Encoder within the calling program.
return sharedSecret;
}
import com.eclypses.ecdh.EcdhP256;
public byte[] getEntropyForMTEDecoder() {
// Create Eclypses DH.
EcdhP256 ecdh;
// Create key pair and retrieve the public key.
byte[] publicKey = new byte[EcdhP256.SzPublicKey];
int res = ecdh.createKeyPair(publicKey);
if (res < 0) {
throw new Exception("Unable to create key pair: " + res);
}
// Send public key to Encoder side and get back
// Encoder side public key.
//---------------------------------------------------------
// This method is not included in this sample!!!
// This is here only to demonstrate that the user MUST
// send the public key to other side and receive back the
// public key from the other side.
//---------------------------------------------------------
byte[] partnerPublicKey = sendPublicKeyGetPartnerPublicKey(publicKey);
// Create the shared secret with the public key received from the Encoder.
byte[] sharedSecret = new byte[EcdhP256.SzSecretData];
res = ecdh.getSharedSecret(partnerPublicKey, sharedSecret);
if (res < 0) {
throw new Exception("Unable to create shared secret: " + res);
}
// Return the shared secret so it can be used as the entropy value
// when creating the MTE Decoder within the calling program.
return sharedSecret;
}
func getEntropyForMTEDecoder() throws -> [uint8] {
// Create Eclypses DH.
var ecdh: EcdhP256 = EcdhP256(name: "")
// Create key pair and retrieve the public key.
let res: (status:Int, publicKey:[uint8]?) = ecdh.createKeyPair()
if res.status != EcdhP256.ResultCodes.success {
print("Unable to create key pair: \(res.status)")
var temp: [uint8] = []
return temp
}
// Send public key to Encoder side and get back
// Encoder side public key.
//---------------------------------------------------------
// This method is not included in this sample!!!
// This is here only to demonstrate that the user MUST
// send the public key to other side and receive back the
// public key from the other side..0
//---------------------------------------------------------
let partnerPublicKey = sendPublicKeyGetPartnerPublicKey(publicKey: res.publicKey ?? [])
// Create the shared secret with the public key received from the Encoder.
var sharedSecret:[uint8] = []
let res2:Int = ecdh.getSharedSecret(peerPublicKey: partnerPublicKey, secret: &sharedSecret)
if res2 != EcdhP256.ResultCodes.success {
print("Unable to create shared secret: \(res2)")
var temp: [uint8] = []
return temp
}
// Return the shared secret so it can be used as the entropy value
// when creating the MTE Decoder within the calling program.
return sharedSecret
}
+(NSMutableArray*)getEntropyForMTEDecoder {
// Create Eclypses DH.
EcdhP256 *ecdh = [[EcdhP256 alloc]initWithName:@""];
// Create key pair and retrieve the public key.
NSMutableArray *publicKey = [NSMutableArray arrayWithCapacity:PublicKeySize];
int res = [ecdh createKeyPair:publicKey];
if (res != Success) {
printf("Unable to create key pair: %i.", res);
exit(EXIT_FAILURE);
}
// Send public key to Encoder side and get back
// Decoder side public key.
//---------------------------------------------------------
// This method is not included in this sample!!!
// This is here only to demonstrate that the user MUST
// send the public key to other side and receive back the
// public key from the other side..0
//---------------------------------------------------------
NSMutableArray *partnerPublicKey = [self sendPublicKeyGetPartnerPublicKey];
// Create the shared secret with the public key received from the Encoder.
NSMutableArray *sharedSecret =[NSMutableArray arrayWithCapacity:SecretDataSize];
res = [ecdh getSharedSecret:partnerPublicKey :sharedSecret];
if (res != Success) {
printf("Unable to create shared secret: %i.", res);
exit(EXIT_FAILURE);
}
// Return the shared secret so it can be used as the entropy value
// when creating the MTE Decoder within the calling program.
return sharedSecret;
}
import { EcdhP256, EcdhStatus } from './ecdhp256';
const getEntropyForMTEDecoder = () => {
// Create Eclypses DH
const ecdh = new EcdhP256();
// Get public key
const publicKey = ecdh.createKeyPair();
// Check for public key success
if (publicKey.status !== EcdhStatus.success) {
throw new Error(`Unable to create key pair: ${publicKey.status}`);
}
// Send public key to Encoder side and get back
// Encoder side public key
//---------------------------------------------------------
// This method is not included in this sample!!!
// This is here only to demonstrate that the user MUST
// send the public key to other side and receive back the
// public key from the other side
//---------------------------------------------------------
const partnerPublicKey = sendPublicKeyGetPartnerPublicKey(publicKey);
// Create the shared secret with the public key received from the Encoder
const sharedSecret = ecdh.getSharedSecret(partnerPublicKey);
if (sharedSecret.status !== EcdhStatus.success) {
throw new Error(`Unable to create shared secret: ${sharedSecret.status}`);
}
// Return the shared secret so it can be used as the entropy value
// when creating the MTE Decoder within the calling program
return sharedSecret;
}
import EcdhP256
def get_entropy_for_MTE_decoder():
# Create Eclypses DH.
ecdh = EcdhP256.EcdhP256()
# Create key pair and retrieve the public key.
publicKey = bytearray(EcdhP256.SzPublicKey)
res = ecdh.create_keypair(publicKey)
if res < 0:
print("Unable to create key pair: " + str(res))
# Send public key to Encoder side and get back
# Encoder side public key.
#---------------------------------------------------------
# This method is not included in this sample!!!
# This is here only to demonstrate that the user MUST
# send the public key to other side and receive back the
# public key from the other side.
#---------------------------------------------------------
partnerPublicKey = send_public_key_get_partner_public_key(publicKey)
# Create the shared secret with the public key received from the Encoder.
sharedSecret = bytearray(EcdhP256.SzSecretData);
res = ecdh.get_shared_secret(partnerPublicKey, sharedSecret)
if res < 0:
print("Unable to create shared secret: " + str(res))
# Return the shared secret so it can be used as the entropy value
# when creating the MTE Decoder within the calling program.
return sharedSecret
import "goEcdhDemo/ecdh"
func GetEntropyForMTEDecoder() []byte {
// Create Eclypses DH.
var ecdhA = ecdh.NewEcdhP256Def()
// Create key pair and retrieve the public key.
var publicKey = make([]byte, ecdh.SZ_PUBLIC_KEY)
var res int = 0
res, publicKey = ecdhA.CreateKeypair()
if res != ecdh.SUCCESS {
fmt.Printf("Unable to create key pair: %v", res)
var temp []byte
return temp
}
// Send public key to Encoder side and get back
// Encoder side public key.
//---------------------------------------------------------
// This method is not included in this sample!!!
// This is here only to demonstrate that the user MUST
// send the public key to other side and receive back the
// public key from the other side.
//---------------------------------------------------------
partnerPublicKey := SendPublicKeyGetPartnerPublicKey(publicKey)
// Create the shared secret with the public key received from the Encoder.
var sharedSecret = make([]byte, ecdh.SZ_SECRET_DATA)
res, sharedSecret = ecdhA.GetSharedSecret(partnerPublicKey)
if res != ecdh.SUCCESS {
fmt.Printf("Unable to create shared secret: %v", res)
var temp []byte
return temp
}
// Return the shared secret so it can be used as the entropy value
// when creating the MTE Decoder within the calling program.
return sharedSecret
}
Eclypses ECDH Package
Eclypses has developed language file and tests for many languages.