Kyber Key Exchange Examples
Purpose
The objective of an MTE Kyber "Examples" is to provide a short example of basic MTE Kyber actions.
Simple demonstration of Kyber within one application.
- C
- C++
- CSharp
- Java
- JavaScript
- Swift
- ObjC
- Python
- Go
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "mte_alloca.h"
#include "mte_kyber.h"
#include "mte_random.h"
/********************************************************************
* 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)
********************************************************************/
char *bytesToHex(const uint8_t *input, size_t inputBytes) {
static char buffer[513];
if (sizeof(buffer) < (2 * inputBytes + 1))
inputBytes = (sizeof(buffer) - 1) / 2;
const uint8_t *pin = input;
const char *hex = "0123456789ABCDEF";
char *pout = buffer;
while (pin < input + inputBytes) {
*pout++ = hex[(*pin >> 4) & 0xF];
*pout++ = hex[*pin++ & 0xF];
}
*pout = 0;
return buffer;
}
/*-----------------------------------------------*/
/* entropy callback for mte_kyber_create_keypair */
/*-----------------------------------------------*/
static int entropy_cb(void *context, void **entropy,
size_t *entropy_bytes,
size_t min_entropy_bytes,
size_t max_entropy_bytes) {
(void)context;
(void)min_entropy_bytes;
mte_random(*entropy, min_entropy_bytes);
*entropy_bytes = min_entropy_bytes;
return MTE_KYBER_SUCCESS;
}
static uint8_t *initiator_private_key;
static size_t initiator_private_key_bytes;
static uint8_t *initiator_public_key;
static size_t initiator_public_key_bytes;
static uint8_t *initiator_secret;
static size_t initiator_secret_bytes;
static uint8_t *responder_encrypted;
static size_t responder_encrypted_bytes;
static uint8_t* responder_secret;
static size_t responder_secret_bytes;
int main() {
bool still_valid;
printf("Eclypses Kyber Demo\n");
printf("-------------------\n\n");
// Init Kyber.
if (mte_kyber_init(512) == MTE_KYBER_SUCCESS) {
bool still_valid = true;
// Allocate buffers and set their sizes.
initiator_private_key_bytes = mte_kyber_get_privkey_size();
initiator_private_key = MTE_ALLOCA(initiator_private_key_bytes);
initiator_public_key_bytes = mte_kyber_get_pubkey_size();
initiator_public_key = MTE_ALLOCA(initiator_public_key_bytes);
// Create keys with the initiator.
printf("Create the key pair with the initiator:\n\n");
if (mte_kyber_create_keypair(initiator_private_key,
&initiator_private_key_bytes,
initiator_public_key,
&initiator_public_key_bytes,
entropy_cb, NULL) != MTE_KYBER_SUCCESS) {
printf("Failed to create the key pair with the initiator.\n");
still_valid = false;
}
if (still_valid) {
printf("Private Key%s:\n%s\n\n",
initiator_private_key_bytes > 256 ?
" (first 256 bytes)" : "",
bytesToHex(initiator_private_key,initiator_private_key_bytes));
printf("Public Key%s:\n%s\n\n",
initiator_public_key_bytes > 256 ?
" (first 256 bytes)" : "",
bytesToHex(initiator_public_key,initiator_public_key_bytes));
// Allocate buffers and set their sizes.
responder_encrypted_bytes = mte_kyber_get_encrypted_size();
responder_encrypted = MTE_ALLOCA(responder_encrypted_bytes);
responder_secret_bytes = mte_kyber_get_secret_size();
responder_secret = MTE_ALLOCA(responder_secret_bytes);
// Use the responder to encrypt the peer public key,
// to get the encrypted and shared secret.
printf("Create secret with the responder:\n\n");
if (mte_kyber_create_secret(initiator_public_key,
initiator_public_key_bytes,
responder_secret,
&responder_secret_bytes,
responder_encrypted,
&responder_encrypted_bytes,
entropy_cb, NULL) != MTE_KYBER_SUCCESS) {
printf("Failed to create/encrypt the secret with the responder.\n");
still_valid = false;
}
}
if (still_valid) {
printf("Encrypted secret from the responder%s:\n%s\n\n",
responder_encrypted_bytes > 256 ?
" (first 256 bytes)" : "",
bytesToHex(responder_encrypted, responder_encrypted_bytes));
printf("Cleartext Secret from the responder:\n");
printf("%s\n\n", bytesToHex(responder_secret, responder_secret_bytes));
// Allocate buffers and set their sizes.
initiator_secret_bytes = mte_kyber_get_secret_size();
initiator_secret = MTE_ALLOCA(initiator_secret_bytes);
// Use the initiator to decrypt the encrypted secret from the responder.
printf("Decrypt with the initiator:\n\n");
if (mte_kyber_decrypt_secret
(initiator_private_key, initiator_private_key_bytes,
responder_encrypted, responder_encrypted_bytes,
initiator_secret, &initiator_secret_bytes) != MTE_KYBER_SUCCESS) {
printf("Failed to decrypt the secret with the initiator.\n");
still_valid = false;
}
}
if (still_valid) {
printf("Secret from the initiator:\n");
printf("%s\n\n", bytesToHex(initiator_secret, initiator_secret_bytes));
// Compare the secrets.
printf("Compare secrets: ");
if (memcmp(responder_secret, initiator_secret,
responder_secret_bytes) != 0) {
printf("No match\n");
}
else {
printf("Match\n");
}
}
}
else {
printf("Failed to initialize Kyber.\n");
}
return 0;
}
#include "MteKyber.h"
#include "MteRandom.h"
/********************************************************************
* 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)
********************************************************************/
char* bytesToHex(const uint8_t* input, size_t inputBytes) {
static char buffer[512];
if (sizeof(buffer) < (2 * inputBytes + 1))
inputBytes = (sizeof(buffer) - 1) / 2;
const uint8_t* pin = input;
const char* hex = "0123456789ABCDEF";
char* pout = buffer;
while (pin < input + inputBytes) {
*pout++ = hex[(*pin >> 4) & 0xF];
*pout++ = hex[*pin++ & 0xF];
}
*pout = 0;
return buffer;
}
/*****************************************************
* Implementation of an application defined callback
* which is used to generate entropy for ecdhB and
* also to test the "zeroize" and "getRandom" methods.
****************************************************/
class KyberCallback : public MteKyber::EntropyCallback {
public:
virtual int entropyCallback(void** entropy, size_t* entropyBytes, size_t minEntropyBytes, size_t maxEntropyBytes) {
if (*entropyBytes < MteKyber::getMinEntropySize() || *entropyBytes > MteKyber::getMaxEntropySize())
{
return MteKyber::MemoryFail;
}
memset(*entropy, 0xCC, minEntropyBytes);
MteKyber::zeroize(*entropy, minEntropyBytes);
for (int i = 0; i < int(minEntropyBytes); i++)
{
if (((uint8_t*)*entropy)[i] != 0)
{
return MteKyber::MemoryFail;
}
}
*entropyBytes = minEntropyBytes;
return MteRandom::getBytes(*entropy, minEntropyBytes);
}
};
static uint8_t* publicKey;
static size_t publicKeyBytes;
static uint8_t* entropyData;
static size_t entropyDataBytes;
static uint8_t* encrypted;
static size_t encryptedBytes;
static uint8_t* secret;
static size_t secretBytes;
static uint8_t* secret2;
static size_t secret2Bytes;
int main()
{
printf("Eclypses Kyber Demo Driver\n");
printf("-------------------------------------------------------\n\n");
// Init Kyber.
if (MteKyber::init(K512) == MteKyber::Success)
{
bool stillValid = true;
// Create Kyber initiator.
MteKyber initiator;
// Get random data to use for entropy for the initiator.
entropyDataBytes = MteKyber::getMinEntropySize();
entropyData = static_cast<uint8_t*>(malloc(entropyDataBytes));
if (entropyData == nullptr)
{
printf("There was a problem attempting to create a buffer of sufficient size for minimum entropy.\n");
stillValid = false;
}
if (stillValid)
{
MteRandom::getBytes(entropyData, entropyDataBytes);
initiator.setEntropy(entropyData, entropyDataBytes);
publicKeyBytes = MteKyber::getPublicKeySize();
publicKey = static_cast<uint8_t*>(malloc(publicKeyBytes));
if (publicKey == nullptr)
{
printf("There was a problem attempting to create a buffer of sufficient size for the public key.\n");
stillValid = false;
}
}
if (stillValid)
{
// Create keys with the initiator.
printf("Create the key pair with the initiator:\n");
if (initiator.createKeyPair(publicKey, publicKeyBytes) != MteKyber::Success)
{
printf("Failed to create the key pair with the initiator.\n");
stillValid = false;
}
}
// Create Kyber responder.
MteKyber responder;
KyberCallback kyberCallback;
responder.setEntropyCallback(&kyberCallback);
if (stillValid)
{
char* buffer = nullptr;
buffer = bytesToHex(publicKey, publicKeyBytes);
printf("Public: %.*s\n", static_cast<int>(MteKyber::getPublicKeySize()), buffer);
printf(" %s\n", buffer + MteKyber::getPublicKeySize());
encryptedBytes = MteKyber::getEncryptedSize();
encrypted = static_cast<uint8_t*>(malloc(publicKeyBytes));
if (encrypted == nullptr)
{
printf("There was a problem attempting to create a buffer of sufficient size for the encrypted secret.\n");
stillValid = false;
}
}
if (stillValid)
{
secretBytes = MteKyber::getSecretSize();
secret = static_cast<uint8_t*>(malloc(secretBytes));
if (secret == nullptr)
{
printf("There was a problem attempting to create a buffer of sufficient size for the secret.\n");
stillValid = false;
}
}
if (stillValid)
{
// Use the responder to encrypt the peer public key, to get the encrypted and shared secret.
printf("Create secret with the responder:\n");
if (responder.createSecret(publicKey, publicKeyBytes, secret, secretBytes, encrypted, encryptedBytes) != MteKyber::Success)
{
printf("There was a problem attempting to create the secret with the responder.\n");
stillValid = false;
}
}
if (stillValid)
{
printf("Secret from the responder: ");
printf("%s\n", bytesToHex(secret, secretBytes));
secret2Bytes = MteKyber::getSecretSize();
secret2 = static_cast<uint8_t*>(malloc(secret2Bytes));
if (secret2 == nullptr)
{
printf("There was a problem attempting to create a buffer of sufficient size for the secret.\n");
stillValid = false;
}
}
if (stillValid)
{
// Use the initiator to decrypt the encrypted output from the responder.
printf("Decrypt with the initiator: \n");
if (initiator.decryptSecret(encrypted, encryptedBytes, secret2, secret2Bytes) != MteKyber::Success)
{
printf("There was a problem attempting to decrypt the secret with the initiator.\n");
stillValid = false;
}
}
if (stillValid)
{
printf("Secret from the initiator: ");
printf("%s\n", bytesToHex(secret2, secret2Bytes));
// Compare the secrets.
printf("Compare secrets: ");
if (memcmp(secret, secret2, secretBytes) != 0)
{
printf("No match\n");
}
else
{
printf("Match\n");
}
}
}
else
{
printf("Kyber was not initiated with a valid strength value.\n");
}
// Free the buffers.
if (entropyData != nullptr)
{
free(entropyData);
}
if (publicKey != nullptr)
{
free(publicKey);
}
if (secret != nullptr)
{
free(secret);
}
if (secret2 != nullptr)
{
free(secret2);
}
return 0;
}
using System;
using System.Globalization;
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 byte[] publicKey;
private static byte[] encrypted;
private static byte[] secret;
private static byte[] secret2;
/*****************************************************
* 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 KyberCallback : IMteKyberEntropyCallback {
public unsafe int EntropyCallback(byte[] entropyInput, UInt32* entropySize, UInt32 minEntropySize, UInt32 maxEntropySize) {
Array.Fill(entropyInput, (byte)0xCC);
MteKyber.Zeroize(entropyInput);
for (int i = 0; i < entropyInput.Length; i++)
if (entropyInput[i] != 0)
return MteKyber.MemoryFail;
// Get random bytes.
byte[] temp = MteRandom.GetBytes((uint)minEntropySize);
if (temp.Length == 0) {
return MteKyber.EntropyFail;
}
*entropySize = (uint)temp.Length;
Array.Copy(temp, entropyInput, temp.Length);
return MteKyber.Success;
}
}
/*************************************************
* Main program.
************************************************/
static int Main() {
Console.WriteLine("Eclypses Kyber Demo Driver\n");
Console.WriteLine("-------------------------------------------------------\n\n");
// Init Kyber.
if (MteKyber.Init(MteKyber.KyberStrength.K512) == MteKyber.Success) {
bool stillValid = true;
// Create Kyber initiator.
MteKyber initiator = new MteKyber();
// Create keys with the initiator.
Console.WriteLine("Create key pair with the initiator:");
publicKey = new byte[MteKyber.PublicKeySize];
if (initiator.CreateKeyPair(publicKey) != MteKyber.Success) {
Console.WriteLine("Failed to create the key pair with the initiator.");
stillValid = false;
}
// Create Kyber responder.
MteKyber responder = new MteKyber();
KyberCallback kyberCallback = new();
responder.SetEntropyCallback(kyberCallback);
if (stillValid) {
string s = BytesToHex(publicKey);
Console.WriteLine("Public: {0}", s[..(Int32)MteKyber.PublicKeySize]);
Console.WriteLine(" {0}", s[(Int32)MteKyber.PublicKeySize..]);
encrypted = new byte[MteKyber.EncryptedSize];
secret = new byte[MteKyber.SecretSize];
// Use the responder to encrypt the peer public key, to get the encrypted and shared secret.
Console.WriteLine("Create secret with the responder:");
if (responder.CreateSecret(publicKey, secret, encrypted) != MteKyber.Success) {
Console.WriteLine("There was a problem attempting to create the secret with the responder.");
stillValid = false;
}
}
if (stillValid) {
Console.WriteLine("Secret from the responder:");
Console.WriteLine(BytesToHex(secret));
secret2 = new byte[MteKyber.SecretSize];
// Use the initiator to decrypt the encrypted output from the responder.
Console.WriteLine("Decrypt with the initiator:");
if (initiator.DecryptSecret(encrypted, secret2) != MteKyber.Success) {
Console.WriteLine("There was a problem attempting to decrypt the secret with the initiator.");
stillValid = false;
}
}
if (stillValid) {
Console.WriteLine("Secret from the initiator:");
Console.WriteLine(BytesToHex(secret2));
// Compare the secrets.
Console.Write("Compare secrets: ");
if (!secret.SequenceEqual(secret2)) {
Console.WriteLine("No match");
} else {
Console.WriteLine("Match");
}
}
} else {
Console.WriteLine("Kyber was not initiated with a valid strength value.");
}
return 0;
}
}
}
import java.nio.ByteBuffer;
import java.util.Arrays;
import com.eclypses.mte.MteKyber;
import com.eclypses.mte.MteRandom;
public class demoJavaKyber implements MteKyber.EntropyCallback {
//-------------------------------------------
// This helper function converts a byte array
// of arbitrary length to a hex string.
//-------------------------------------------
private String bytesToHex(byte[] bytes) {
StringBuilder hex = new StringBuilder();
for (byte b : bytes)
hex.append(String.format("%02X", b));
return hex.toString();
}
//----------------------------------------------------
// Implementation of an application defined callback
// which is used to generate entropy for Kyber and
// also to test the "zeroize" and "getRandom" methods.
//----------------------------------------------------
public MteKyber.EntropyCallback.BuffStatus entropyCallback(int minEntropyBytes, int maxEntropyBytes) {
byte[] entropyInput = new byte[minEntropyBytes];
MteKyber.EntropyCallback.BuffStatus myBuffStatus =
new MteKyber.EntropyCallback.BuffStatus();
Arrays.fill(entropyInput, (byte)0xCC);
MteKyber.zeroize(entropyInput);
for (int i = 0; i < entropyInput.length; i++) {
if (entropyInput[i] != 0) {
myBuffStatus.status = MteKyber.MemoryFail;
myBuffStatus.buff = null;
return myBuffStatus;
}
}
byte[] temp = MteRandom.getBytes(entropyInput.length);
myBuffStatus.status = MteKyber.Success;
// Create a direct buffer with the contents.
myBuffStatus.buff = ByteBuffer.allocate(temp.length);
myBuffStatus.buff.put(temp, 0, temp.length);
return myBuffStatus;
}
private static byte[] publicKey;
private static byte[] encrypted;
private static byte[] secret;
private static byte[] secret2;
/*************************************************
* Main program.
************************************************/
public int run() {
System.out.println("Eclypses Kyber Demo Driver");
System.out.println("-------------------------------------------------------");
// Init Kyber.
if (MteKyber.init(MteKyber.KyberStrength.K512) == MteKyber.Success) {
boolean stillValid = true;
// Create Kyber initiator.
MteKyber initiator = new MteKyber();
publicKey = new byte[MteKyber.getPublicKeySize()];
// Create keys with the initiator.
System.out.println("Create the key pair with the initiator:");
if (initiator.createKeyPair(publicKey) != MteKyber.Success) {
System.out.println("Failed to create the key pair with the initiator.");
stillValid = false;
}
// Create Kyber responder.
MteKyber responder = new MteKyber();
responder.setEntropyCallback(this);
if (stillValid) {
String s = bytesToHex(publicKey);
System.out.println("Public: " + s.substring(0, MteKyber.getPublicKeySize()));
System.out.println(" " + s.substring(MteKyber.getPublicKeySize()));
encrypted = new byte[MteKyber.getEncryptedSize()];
secret = new byte[MteKyber.getSecretSize()];
// Use the responder to encrypt the peer public key, to get the encrypted and shared secret.
System.out.println("Create secret with the responder:");
if (responder.createSecret(publicKey, secret, encrypted) != MteKyber.Success) {
System.out.println("There was a problem attempting to create the secret with the responder.");
stillValid = false;
}
}
if (stillValid) {
System.out.println("Secret from the responder:");
System.out.println(bytesToHex(secret));
secret2 = new byte[MteKyber.getSecretSize()];
// Use the initiator to decrypt the encrypted output from the responder.
System.out.println("Decrypt with the initiator:");
if (initiator.decryptSecret(encrypted, secret2) != MteKyber.Success) {
System.out.println("There was a problem attempting to decrypt the secret with the initiator.");
stillValid = false;
}
}
if (stillValid) {
System.out.println("Secret from the initiator:");
System.out.println(bytesToHex(secret2));
// Compare the secrets.
System.out.println("Compare secrets: ");
if (!Arrays.equals(secret, secret2)) {
System.out.println("No match");
} else {
System.out.println("Match");
}
}
} else {
System.out.println("Kyber was not initiated with a valid strength value.");
}
return 0;
}
//-----------------------------------------------------------
// This static main() function is used to run the demo driver
// as a console app in Linux and Windows. This function is
// not used in Android.
//-----------------------------------------------------------
public static void main(String[] args) {
demoJavaKyber job = new demoJavaKyber();
job.run();
}
}
import { MteKyber, MteKyberStatus, MteKyberStrength, MteWasm, MteMem } from "./Mte.js";
// Create and instantiate the singleton WASM. The instantiate() call returns a
// promise that must be resolved before any other MTE objects can be created.
// The instantiated, resolved MteWasm object must be passed as an argument to
// create any other MTE objects.
let wasm = new MteWasm();
wasm.instantiate().then(function () { main(); });
// Main function.
function main() {
console.log("Eclypses Kyber Demo");
console.log("-------------------\n");
var initiator = new MteKyber(wasm, MteKyberStrength.K512);
var responder = new MteKyber(wasm, MteKyberStrength.K512);
// Create key pair from the initiator.
console.log("Creating key pair from initiator");
var result = initiator.createKeypair();
if (result.status !== MteKyberStatus.success) {
console.log("Initiator: Failed to create the key pair.");
return;
}
var publicKey = result.result1;
var str = publicKey.reduce(function (s, b) {
return s + b.toString(16).padStart(2, '0');
}, '').toUpperCase();
console.log("Public key from initiator:\n" + str + "\n");
// Create encrypted and unencrypted secrets from responder.
console.log("Creating secrets from responder");
result = responder.createSecret(publicKey);
if (result.status !== MteKyberStatus.success) {
console.log("Responder: Failed to create the secrets.");
return;
}
var responderSecret = result.result1;
var encryptedSecret = result.result2;
str = encryptedSecret.reduce(function (s, b) {
return s + b.toString(16).padStart(2, '0');
}, '').toUpperCase();
console.log("Responder encrypted secret:\n" + str + "\n");
str = responderSecret.reduce(function (s, b) {
return s + b.toString(16).padStart(2, '0');
}, '').toUpperCase();
console.log("Responder cleartext secret:\n" + str + "\n");
// Decrypt the encrypted secret from initiator.
result = initiator.decryptSecret(encryptedSecret);
if (result.status !== MteKyberStatus.success) {
throw new Error("Initiator: Failed to decrypt the secret.");
}
var initiatorSecret = result.result1;
str = initiatorSecret.reduce(function (s, b) {
return s + b.toString(16).padStart(2, '0');
}, '').toUpperCase();
console.log("Initiator cleartext secret:\n" + str + "\n");
// Compare the secrets.
if (responderSecret.length === initiatorSecret.length &&
responderSecret.every(function (v, i) { return v === initiatorSecret[i]; })) {
console.log("Shared secrets: MATCH.");
}
else {
console.log("Shared secrets: NO MATCH.");
}
initiator.destruct();
responder.destruct();
// Success.
return;
}
import Foundation
class Test: MteKyberEntropyCallback {
var initiator: MteKyber!
var responder: MteKyber!
let testNist = true
let testSetCallback = false
func runTest() {
initiator = MteKyber(strength: 512)
responder = MteKyber(strength: 512)
if testNist {
var status = initiator.setEntropy(getNistSeed())
checkStatus(status: status, message: "Initiator setEntropy")
status = responder.setEntropy(getBlankSeed())
checkStatus(status: status, message: "Responder setEntropy")
} else if testSetCallback {
initiator.setEntropyCallback(self)
responder.setEntropyCallback(self)
}
// Returns a status and initiator's public key
let createKeyPairResult: (status: Int, publicKey: [UInt8]) = initiator.createKeyPair()
checkStatus(status: createKeyPairResult.status, message: "createKeyPair")
// Takes initiator's public key as a parameter and returns a status and responder's encrypted secret and clear secret
let encryptResult: (status: Int, encryptedSecret: [UInt8], secret: [UInt8]) = responder.createSecret(peerPublicKey: createKeyPairResult.publicKey)
checkStatus(status: createKeyPairResult.status, message: "createSecret")
// Takes responder's encrypted secret as a parameter and returns the decrypted secret
let decryptResult: (status: Int, secret: [UInt8]) = initiator.decryptSecret(encryptedSecret: encryptResult.encryptedSecret)
checkStatus(status: createKeyPairResult.status, message: "decryptedSecret")
print("Initiator hex secret:\n\(decryptResult.secret.map { String(format: "%02X", $0) }.joined())")
print("Responder hex secret:\n\(encryptResult.secret.map { String(format: "%02X", $0) }.joined())")
if testNist {
if (decryptResult.secret.map { String(format: "%02X", $0) }.joined() == nistSecret) {
print("\nSecret matches expected NIST secret")
}
}
// Compare Secrets
let initiatorSecret = decryptResult.secret
let responderSecret = encryptResult.secret
initiator = nil
responder = nil
if responderSecret != initiatorSecret {
print("Secret Mismatch")
exit(EXIT_FAILURE)
} else {
print("\n****** SUCCESS! SECRETS MATCH *****\n")
}
}
func checkStatus(status: Int, message: String) {
if KyberResultCode(status).stringValue != KyberResultCode.success.stringValue {
print("MteKyber failure in \(message).")
exit(EXIT_FAILURE)
}
}
func entropyCallback(_ entropyInput: inout [UInt8], _ eiBytes: Int) -> Int32 {
return MteRandom.getBytes(&entropyInput)
}
let nistSecret = "0A6925676F24B22C286F4C81A4224CEC506C9B257D480E02E3B49F44CAA3237F"
func getBlankSeed() -> [UInt8] {
let hex = String(repeating: "0", count: 96)
return convertStrToHexBytes(seed: hex)
}
func getNistSeed() -> [UInt8] {
let hex = "061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA1"
return convertStrToHexBytes(seed: hex)
}
// For display to the user only
func convertStrToHexBytes(seed: String) -> [UInt8] {
var byteArray = [UInt8]()
// Process two characters at a time
for index in stride(from: 0, to: seed.count, by: 2) {
let startIndex = seed.index(seed.startIndex, offsetBy: index)
let endIndex = seed.index(startIndex, offsetBy: 2)
if let byte = UInt8(seed[startIndex..<endIndex], radix: 16) {
byteArray.append(byte)
}
}
return byteArray
}
}
#import <Foundation/Foundation.h>
#import "Test.h"
@implementation Test
- (int)runTest {
NSLog(@"Beginning Objective-C Kyber Test\n");
int status = Success;
MteKyber *initiator = [[MteKyber alloc] init:512];
MteKyber *responder = [[MteKyber alloc] init:512];
Boolean isNistTest = true;
// TO TEST setEntropyCallback functionality
// [initiator setEntropyCallback:self];
// [responder setEntropyCallback:self];
if (isNistTest)
{
// TO TEST NIST TEST VECTOR SEED
NSMutableData *nistSeedData = [NSMutableData dataWithBytes:nistSeed length:sizeof(nistSeed)];
[initiator setEntropy:nistSeedData];
uint8_t blankSeed[48];
memset(blankSeed, 0, sizeof(blankSeed));
NSMutableData *blankSeedData = [NSMutableData dataWithBytes:blankSeed length:sizeof(blankSeed)];
[responder setEntropy:blankSeedData];
}
// Create keyPair
NSMutableData *publicKeyData = [[NSMutableData alloc]initWithLength:mte_kyber_get_pubkey_size()];
status = [initiator createKeyPair:(publicKeyData)];
if (status != Success) {
return status;
}
// Create Secrets
NSMutableData *encryptedSecretData = [[NSMutableData alloc]initWithLength:mte_kyber_get_encrypted_size()];
NSMutableData *secretData = [[NSMutableData alloc]initWithLength:mte_kyber_get_secret_size()];
status = [responder createSecret:publicKeyData
:secretData
:encryptedSecretData];
if (status != Success) {
return status;
}
NSMutableData *decryptedSecretData = [[NSMutableData alloc]initWithLength:mte_kyber_get_secret_size()];
status = [initiator decryptSecret:encryptedSecretData
:decryptedSecretData];
if (status != Success) {
return status;
}
printf("\nSecret: \n");
const unsigned char * ptr = [secretData bytes];
for (NSUInteger i = 0; i < secretData.length; i++) {
printf("%02x ", ptr[i]);
}
printf("\nDecrypted Secret: \n");
const unsigned char * ptr2 = [decryptedSecretData bytes];
for (NSUInteger i = 0; i < decryptedSecretData.length; i++) {
printf("%02x ", ptr2[i]);
}
if (isNistTest) {
if ([secretData isEqual:[NSMutableData dataWithBytes:nistSecret length:sizeof(nistSecret)]])
{
printf("\nSecret matches expected NIST secret\n");
}
}
Boolean secretsMatch = [secretData isEqual:decryptedSecretData];
[MteKyber zeroize:[encryptedSecretData mutableBytes] :encryptedSecretData.length];
[MteKyber zeroize:[secretData mutableBytes] :secretData.length];
[MteKyber zeroize:[decryptedSecretData mutableBytes] :decryptedSecretData.length];
initiator = nil;
responder = nil;
if (secretsMatch) {
printf("\n****** SUCCESS! SECRETS MATCH *****\n");
exit(EXIT_SUCCESS);
} else {
printf("Secret Mismatch\n");
exit(EXIT_FAILURE);
}
}
- (int32_t)entropyCallback:(uint8_t *)entropyInput :(size_t)eiBytes {
return [MteRandom getRandom:entropyInput :eiBytes];
}
uint8_t nistSeed[] = {
0x06, 0x15, 0x50, 0x23, 0x4d, 0x15, 0x8c, 0x5e, 0xc9, 0x55, 0x95, 0xfe,
0x04, 0xef, 0x7a, 0x25, 0x76, 0x7f, 0x2e, 0x24, 0xcc, 0x2b, 0xc4, 0x79,
0xd0, 0x9d, 0x86, 0xdc, 0x9a, 0xbc, 0xfd, 0xe7, 0x05, 0x6a, 0x8c, 0x26,
0x6f, 0x9e, 0xf9, 0x7e, 0xd0, 0x85, 0x41, 0xdb, 0xd2, 0xe1, 0xff, 0xa1};
uint8_t nistSecret[] = {
0x0a, 0x69, 0x25, 0x67, 0x6f, 0x24, 0xb2, 0x2c, 0x28, 0x6f, 0x4c, 0x81,
0xa4, 0x22, 0x4c, 0xec, 0x50, 0x6c, 0x9b, 0x25, 0x7d, 0x48, 0x0e, 0x02,
0xe3, 0xb4, 0x9f, 0x44, 0xca, 0xa3, 0x23, 0x7f};
@end
import ctypes
import MteKyber
import copy
from MteKyber import KyberEntropyCallback
import MteRandom
def bytes_to_hex(input):
hex_chars = "0123456789ABCDEF"
sb = []
i = 0
while i < len(input):
sb.append(hex_chars[(input[i] >> 4) & 0xF])
sb.append(hex_chars[input[i] & 0xF])
i += 1
return''.join(sb)
class KyberEntropyCallbackCustom:
def entropy_callback(entropyInput, entropySize, minEntropySize, maxEntropySize):
#Generate a random byte string with the maxEntropySize.
rand = MteRandom.MteRandom()
entropyInput[0] = rand.get_bytes(minEntropySize)
#Set entropy size to the size of our random_bytes.
entropySize[0] = maxEntropySize
return 0
def main():
status = 0
kyberA = MteKyber.MteKyber()
kyberA.init(512)
publicKeyA = bytearray(kyberA.get_public_key_size())
# Create key pair A and check for success.
if status == 0:
print("\n\nPairing test using Python supplied RNG")
print("----------------------------------\n")
print("Create key pair: ")
entropySize = kyberA.get_max_entropy_size()
rand = MteRandom.MteRandom()
kyberA.set_entropy(rand.get_bytes(entropySize))
if kyberA.create_keypair(publicKeyA) != MteKyber.Success:
print("Failed")
status = -1
else:
s = bytes_to_hex(publicKeyA)
print("Public: " + s)
kyberB = MteKyber.MteKyber()
kyberB.init(512)
secretB = bytearray(kyberB.get_secret_size())
secretEncB = bytearray(kyberB.get_encrypted_size())
# Create secret and encrypted secret.
if status == 0:
print("Create Secret: ")
kyberCallback = KyberEntropyCallbackCustom
kyberB.set_entropy_callback(kyberCallback)
returning = kyberB.create_secret(publicKeyA, secretB, secretEncB)
if returning != MteKyber.Success:
print("create_keypair() returned: " + str(returning))
status = -1
else:
s = bytes_to_hex(secretB)
print("Secret: " + s)
secretA = bytearray(kyberA.get_secret_size())
# Decrypt Secret.
if status == 0:
print("Decrypting Secret: ")
if kyberA.decrypt_secret(secretEncB, secretA) != MteKyber.Success:
print("Failed")
status = -1
else:
s = bytes_to_hex(secretA)
print("Decrypted Secret: " + s)
# Check if the shared secrets match.
if status == 0:
print("Comparing secrets: ")
if secretA != secretB:
print("No Match")
else:
print("Match")
if status < 0:
print("\n\nFAILURE.")
return status
main()
package main
import "C"
import (
"fmt"
"goKyberDemo/mte"
"os"
"reflect"
)
// Callbacks that will get entropy, nonce, and timestamp from stdin.
// THIS IS NOT A SECURE WAY TO CAPTURE THESE ITEMS AND IS ONLY FOR
// DEMONSTRATION PURPOSES.
type Cbs struct {
}
/*****************************************************
* Implementation of an application defined callback
* which is used to generate entropy for ecdhB and
* also to test the "Zeroize" and "Random_GetBytes" methods.
****************************************************/
func (cbs *Cbs) EntropyCallback(minEntropyBytes int, maxEntropyBytes int) (entropyData []byte, status int) {
entropyData = make([]byte, minEntropyBytes)
// Set byte array to 0xcc.
for i := range entropyData {
entropyData[i] = 0xcc
}
// Zeroize the entropy.
mte.MteKyberZeroize(entropyData)
// Ensure each value is zero.
for i := range entropyData {
if entropyData[i] != 0 {
return []byte{}, mte.MTE_KYBER_MEMORY_FAIL
}
}
var entropySize = len(entropyData)
res, temp := mte.Random_GetBytes(entropySize)
if res {
// Copy to the entropy buffer.
copy(entropyData, temp)
} else {
return []byte{}, mte.MTE_KYBER_ENTROPY_FAIL
}
return entropyData, mte.MTE_KYBER_SUCCESS
}
func doMain() int {
var publicKey []byte
var encrypted []byte
var secret []byte
var secret2 []byte
var status int
fmt.Print("Eclypses Kyber Demo Driver\n")
fmt.Print("-------------------------------------\n\n")
// Init Kyber.
if mte.MteKyberInit(mte.MTE_KYBER_STRENGTH_512) == mte.MTE_KYBER_SUCCESS {
var stillValid bool = true
// Create Kyber initator.
initiator := mte.NewMteKyberDef()
defer initiator.Destroy()
// Create keys with the initiator.
fmt.Print("Create key pair with the initiator:\n")
status, publicKey = initiator.CreateKeypair()
if status != mte.MTE_KYBER_SUCCESS {
fmt.Print("Failed to create the key pair with the initiator.\n")
stillValid = false
}
// Create Kyber responder.
responder := mte.NewMteKyberDef()
cbs := &Cbs{}
defer responder.Destroy()
responder.SetEntropyCallback(cbs)
if stillValid {
fmt.Printf("Public: %X\n", publicKey[0:mte.MteKyberGetPublicKeySize()/2])
fmt.Printf(" %X\n", publicKey[mte.MteKyberGetPublicKeySize()/2:])
// Use the responder to encrypt the peer public key, to get the encrypted and shared secret.
fmt.Print("Create secret with the responder:\n")
status, encrypted, secret = responder.CreateSecret(publicKey)
if status != mte.MTE_KYBER_SUCCESS {
fmt.Print("There was a problem attempting to create the secret with the responder.\n")
stillValid = false
}
}
if stillValid {
fmt.Print("Secret from the responder:\n")
fmt.Printf("%X\n", secret)
// Use the initiator to decrypt the encrypted output from the responder.
fmt.Print("Decrypt with the initiator:\n")
status, secret2 = initiator.DecryptSecret(encrypted)
if status != mte.MTE_KYBER_SUCCESS {
fmt.Print("There was a problem attempting to decrypt the secret with the initiator.\n")
stillValid = false
}
}
if stillValid {
fmt.Print("Secret from the initiator:\n")
fmt.Printf("%X\n", secret2)
// Compare the secrets.
if !reflect.DeepEqual(secret, secret2) {
fmt.Print("No match\n")
status = -1
} else {
fmt.Print("Match\n")
}
}
} else {
fmt.Print("Kyber was not initiated with a valid strength value.")
}
// Success.
return 0
}
func main() {
os.Exit(doMain())
}