MTE Managed Key Encryption Add-On Code Examples
Purpose
The objective of an MTE Managed Key Encryption Add-On "Examples" is to provide short examples of how to use the MTE Managed Key Encryption Encoder Add-On and MTE Managed Key Encryption Decoder Add-On.
The Managed Key Encryption Add-On replaces the core encoder and decoder, which only do tokenization, with an encoder and decoder that combine standard encryption with tokenization. This allows much larger data to take advantage of the MTE technology without significantly increasing the data size.
MTE Managed Key Encryption (MKE) Encoder
Create MTE MKE Encoder
The MTE MKE Encoder will be created using default options. The default options will set preferred security options recommended by Eclypses. Custom options should only be used in special circumstances and after reading and understanding how to select the best options for a given situation. More information about how to select these options can be found in the official MTE Developer Guides.
Create Default MKE Encoder
- C
- C++
- CSharp
- Java
- JavaScript
- Swift
- Python
- Go
- PHP
/* Create the encoder. */
MTE_HANDLE encoder;
mte_mke_enc_init_info e_info = MTE_MKE_ENC_INIT_INFO_INIT(
MTE_DRBG_ENUM, MTE_TOKBYTES, MTE_VERIFIERS_ENUM,
MTE_CIPHER_ENUM, MTE_HASH_ENUM, NULL, NULL, NULL, NULL, NULL, NULL);
mte_enc_args e_args = MTE_ENC_ARGS_INIT(NULL, 0, NULL, &t_cb, NULL);
encoder = MTE_ALLOCA(mte_mke_enc_state_bytes(&e_info));
status = mte_mke_enc_state_init(encoder, &e_info);
if (status != mte_status_success)
{
fprintf(stderr, "Encoder init error (%s): %s\n",
mte_base_status_name(status),
mte_base_status_description(status));
return status;
}
status = mte_mke_enc_instantiate(encoder, &i_info);
if (status != mte_status_success)
{
fprintf(stderr, "Encoder instantiate error (%s): %s\n",
mte_base_status_name(status),
mte_base_status_description(status));
return status;
}
The entropy and nonce callbacks.
static mte_status ei_cb(void* context, mte_drbg_ei_info* info)
{
MTE_SIZE_T input_bytes;
(void)context;
/* Get the entropy. */
printf("Enter %u-%lu bytes of entropy> ",
(unsigned)info->min_length,
(unsigned long)info->max_length);
fflush(stdout);
(void)!fgets(ei_buff, sizeof(ei_buff), stdin);
input_bytes = (MTE_SIZE_T)(strlen(ei_buff) - 1);
/* If the entropy is less than the minimum required, we must return an
error. */
if (input_bytes < info->min_length)
{
return mte_status_drbg_catastrophic;
}
else if (input_bytes > info->bytes)
{
/* If the entropy is longer than the provided buffer, point at our buffer
instead. */
info->buff = (MTE_UINT8_T*)ei_buff;
}
else
{
/* Otherwise copy the entropy to the provided buffer. */
memcpy(info->buff, ei_buff, input_bytes);
}
/* Set the actual entropy length. */
info->bytes = input_bytes;
/* We got it successfully. */
return mte_status_success;
}
static void n_cb(void* context, mte_drbg_nonce_info* info)
{
MTE_SIZE8_T i;
MTE_UINT64_T u64;
char line[80];
(void)context;
/* Get the nonce. */
printf("Enter the nonce (decimal digits only)> ");
fflush(stdout);
(void)!fgets(line, sizeof(line), stdin);
u64 = strtoul(line, NULL, 10);
/* Copy the nonce in little-endian format to the nonce buffer. */
for (i = 0; i < info->max_length && i < sizeof(u64); ++i)
{
info->buff[i] = (MTE_UINT8_T)(u64 >> (i * 8));
}
/* If the minimum length is greater than the size of the nonce we got, fill
up to that length with zeros. */
for (; i < info->min_length; ++i)
{
info->buff[i] = 0;
}
/* Set the actual nonce length. */
info->bytes = i;
}
// Create the encoder.
MteMkeEnc encoder;
encoder.setEntropyCallback(&cbs);
encoder.setNonceCallback(&cbs);
encoder.setTimestampCallback(&cbs);
status = encoder.instantiate(personal);
if (status != mte_status_success)
{
std::cerr << "Encoder instantiate error ("
<< MteBase::getStatusName(status)
<< "): "
<< MteBase::getStatusDescription(status)
<< std::endl;
return status;
}
The entropy and nonce callbacks.
mte_status Cbs::entropyCallback(mte_drbg_ei_info& info)
{
// Display a prompt.
std::cout << "Enter "
<< static_cast<size_t>(info.min_length) << '-' << info.max_length
<< " bytes of entropy> " << std::flush;
// Get a line of input.
std::string line;
std::cin >> line;
// If the input was less than the minimum required, we must return an error.
if (line.size() < info.min_length)
{
return mte_status_drbg_catastrophic;
}
// Set the actual entropy length. It cannot exceed the maximum required.
size_t buffBytes = info.bytes;
info.bytes = std::min(static_cast<MTE_SIZE_T>(line.size()), info.max_length);
// If the length is greater than the length of the provided buffer, we have
// to create our own buffer instead.
if (info.bytes > buffBytes)
{
delete [] myEntropy;
myEntropy = new uint8_t[info.bytes];
info.buff = myEntropy;
}
// Copy the entropy to the buffer and we got it successfully.
memcpy(info.buff, line.data(), info.bytes);
return mte_status_success;
}
void Cbs::nonceCallback(mte_drbg_nonce_info& info)
{
// Display a prompt.
std::cout << "Enter the nonce (decimal digits only)> " << std::flush;
// Get the nonce and ignore the rest of the line.
MTE_UINT64_T u64;
std::cin >> u64;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// Copy the nonce in little-endian format to the nonce buffer.
size_t i;
for (i = 0; i < info.max_length && i < sizeof(u64); ++i)
{
info.buff[i] = static_cast<MTE_UINT8_T>(u64 >> (i * 8));
}
// If the minimum length is greater than the size of the nonce we got, fill
// up to that length with zeros.
for (; i < info.min_length; ++i)
{
info.buff[i] = 0;
}
// Set the actual nonce length.
info.bytes = static_cast<MTE_SIZE8_T>(i);
}
// Create MTE MKE Encoder with defaults
MteMkeEnc mkeEncoder = new MteMkeEnc();
// Need entropy, nonce and personalization string
// *** IMPORTANT NOTE ***
// Entropy is critical to security and should be created and
// handled like encryption keys. To permit decoding of encoded
// value, Encoder and Decoder must use identical Entropy, Nonce and
// Personalization String as well as Options . See Developer Guides for more information.
//-----------------------------------------------------------------
// The following personalization string and nonce values are for
// demonstration only and should not be used in a production environment
string personalizationString = "MySecretPersonalizationStringGoesHere";
long nonce = 12345678;
// Check how long of entropy we need.
// This example fills entropy with at string of zeros
// this should NOT be used in a production environment
int entropyMinBytes = mkeEncoder.GetDrbgsEntropyMinBytes(mkeEncoder.GetDrbg());
string entropy = (entropyMinBytes > 0)
? new String('0', entropyMinBytes)
: string.Empty;
// Set Encoder entropy and nonce
mkeEncoder.SetEntropy(Encoding.UTF8.GetBytes(entropy));
mkeEncoder.SetNonce(nonce);
// Initialize MTE MKE Encoder
MteStatus encoderStatus = mkeEncoder.Instantiate(personalizationString);
if(encoderStatus !=MteStatus.mte_status_success)
{
// MTE cannot continue so handle failure appropriately
// Below is an Example
throw new ApplicationException($"Failed to initialize the MTE Encoder engine." +
$"Status: {mkeEncoder.GetStatusName(encoderStatus)} / " +
$"{mkeEncoder.GetStatusDescription(encoderStatus)}");
}
// Create the MTE Encoder
MteMkeEnc mkeEncoder = new MteMkeEnc();
// Need entropy, nonce and personalization string
// *** IMPORTANT NOTE ***
// Entropy is critical to security and should be created and handled like encryption keys.
// To permit decoding of encoded value, Encoder and Decoder must use identical Entropy, Nonce and
// Personalization String as well as Options . See Developer Guides for more information.
//-----------------------------------------------------------------
// The following personalization string and nonce values are for
// demonstration only and should not be used in a production environment
String personalizationString = "MySecretPersonalizationStringGoesHere";
long nonce = 12345678;
// Check how long of entropy we need.
// This example fills entropy with at string of zeros
// this should NOT be used in a production environment
int entropyMinBytes = MteBase.getDrbgsEntropyMinBytes(mkeEncoder.getDrbg());
StringBuffer outputBuffer = new StringBuffer(entropyMinBytes);
for (int i = 0; i < entropyMinBytes; i++){
outputBuffer.append("0");
}
String entropy = outputBuffer.toString();
entropy.replace(' ', '0');
// Set Encoder entropy and nonce
mkeEncoder.setEntropy(entropy.getBytes());
mkeEncoder.setNonce(nonce);
// Initialize MTE Encoder
MteStatus encoderStatus = mkeEncoder.instantiate(personalizationString.getBytes());
if (encoderStatus != MteStatus.mte_status_success)
{
// MTE cannot continue so handle failure appropriately
// Below is an Example
throw new Exception("Failed to initialize the MTE Encoder engine. Status: "
+ MteBase.getStatusName(encoderStatus)+ " / "
+ MteBase.getStatusDescription(encoderStatus));
}
// Create MTE MKE Encoder with defaults
const mkeEncoder = MteMkeEnc.fromdefault(mteWasm);
// Need entropy, nonce and personalization string
// *** IMPORTANT NOTE ***
// Entropy is critical to security and should be created and
// handled like encryption keys. To permit decoding of encoded
// value, Encoder and Decoder must use identical Entropy, Nonce and
// Personalization String as well as Options . See Developer Guides for more information.
//-----------------------------------------------------------------
// The following personalization string and nonce values are for
// demonstration only and should not be used in a production environment
const personalizationString = "MySecretPersonalizationStringGoesHere";
const nonce = 12345678;
// Check how long of entropy we need.
// This example fills entropy with at string of zeros
// this should NOT be used in a production environment
const entropyMinBytes = mkeEncoder.getDrbgsEntropyMinBytes(
mkeEncoder.getDrbg(),
);
const encoderEntropy =
entropyMinBytes > 0 ? "0".repeat(entropyMinBytes) : encoderEntropy;
// Set Encoder entropy and nonce
mkeEncoder.setEntropyStr(entropy);
mkeEncoder.setNonce(nonce);
// Instantiate MTE MKE Encoder
const encoderStatus = mkeEncoder.instantiate(personalizationString);
if (encoderStatus !== MteStatus.mte_status_success) {
// MTE cannot continue so handle failure appropriately
// Below is an Example
const status = mteBase.getStatusName(encoderStatus);
const message = mteBase.getStatusDescription(encoderStatus);
throw new Error(`Error instantiating MKE Encoder.\n${status}: ${message}`);
}
// Create the encoder.
let encoder = try! MteMkeEnc()
encoder.setEntropyCallback(cbs)
encoder.setNonceCallback(cbs)
encoder.setTimestampCallback(cbs)
status = encoder.instantiate(personal)
if status != mte_status_success {
print("Encoder instantiate error (\(MteBase.getStatusName(status))): " +
MteBase.getStatusDescription(status))
return Int32(status.rawValue)
}
The entropy and nonce callbacks.
class Cbs: MteEntropyCallback, MteNonceCallback, MteTimestampCallback {
func entropyCallback(_ minEntropy: Int,
_ minLength: Int,
_ maxLength: UInt64,
_ entropyInput: inout [UInt8],
_ eiBytes: inout UInt64,
_ entropyLong: inout UnsafeMutableRawPointer?) -> mte_status {
// Display a prompt.
print("Enter \(minLength)-\(maxLength) bytes of entropy> ", terminator: "")
// Get a line of input.
let line = readLine()!
// If the input was less than the minimum required, we must return an error.
if line.utf8.count < minLength {
return mte_status_drbg_catastrophic
}
// Set the actual entropy length. It cannot exceed the maximum required.
let buffBytes = eiBytes
eiBytes = min(UInt64(line.utf8.count), maxLength)
// If the length is greater than the length of the provided buffer, we have
// to create our own buffer instead.
if eiBytes > buffBytes {
// Get the entropy input as an array.
let ei = [UInt8](line.utf8)
// If there is previous raw entropy, deallocate it.
if myEntropyRaw != nil {
myEntropyRaw!.deallocate()
}
// Allocate unsafe memory for the entropy.
myEntropyRaw =
UnsafeMutableRawPointer.allocate(byteCount: ei.count, alignment: 16)
// Copy from the entropy array to the unsafe memory.
ei.withUnsafeBytes { buff in
let raw = myEntropyRaw!.assumingMemoryBound(to: UInt8.self)
let ei = buff.bindMemory(to: UInt8.self)
raw.assign(from: ei.baseAddress!, count: ei.count)
}
// Set the raw pointer to point at the unsafe memory.
entropyLong = myEntropyRaw
}
else {
// Copy the entropy to the buffer.
entropyInput.replaceSubrange(Range(uncheckedBounds: (0, Int(eiBytes))),
with: line.utf8.prefix(Int(eiBytes)))
}
// Success.
return mte_status_success
}
func nonceCallback(_ minLength: Int,
_ maxLength: Int,
_ nonce: inout [UInt8],
_ nBytes: inout Int) {
// Display a prompt.
print("Enter the nonce (decimal digits only)> ", terminator: "")
// Get the nonce and ignore the rest of the line.
let u64 = UInt64(readLine()!)!
// Copy the nonce in little-endian format to the nonce buffer.
let nCopied = min(nonce.count, MemoryLayout.size(ofValue: u64))
for i in 0..<nCopied {
nonce[i] = UInt8(UInt64(u64 >> (i * 8)) & 0xFF)
}
// If the minimum length is greater than the size of the nonce we got, fill
// up to that length with zeros.
if nCopied < minLength {
for i in nCopied..<minLength {
nonce[i] = 0
}
nBytes = minLength
}
else {
nBytes = nCopied
}
}
# Create MTE MKE Encoder with defaults.
mke_encoder = MteMkeEnc.fromdefault()
# Need entropy, nonce and personalization string.
# *** IMPORTANT NOTE ***
# Entropy is critical to security and should be created and
# handled like encryption keys. To permit decoding of encoded
# value, Encoder and Decoder must use identical Entropy, Nonce and
# Personalization String as well as Options . See Developer Guides for more information.
#-----------------------------------------------------------------
# The following personalization string and nonce values are for
# demonstration only and should not be used in a production environment.
personalization_string = "MySecretPersonalizationStringGoesHere"
nonce = 12345678
# Check how long of entropy we need.
# This example fills entropy with at string of zeros.
# This should NOT be used in a production environment.
entropy_min_bytes = MteBase.get_drbgs_entropy_min_bytes(mke_encoder.get_drbg())
entropy = bytes("0" * entropy_min_bytes, 'utf-8')
# Set Encoder entropy and nonce.
mke_encoder.set_entropy(entropy)
mke_encoder.set_nonce(nonce)
# Initialize MTE MKE Encoder.
encoder_status = mke_encoder.instantiate(personalization_string)
if encoder_status != MteStatus.mte_status_success:
# MTE cannot continue so handle failure appropriately.
# Below is an Example.
raise Exception("Failed to initialize the MTE Encoder engine. Status: {0} / {1}\n".format(MteBase.get_status_name(encoder_status),
MteBase.get_status_description(encoder_status)))
// Create MKE Encoder with default options
// In practice, you will create an Encoder this way, create a custom Encoder,
// or create MKE or FLEN Encoder. See developer guide for more information
mkeEncoder := mte.NewMkeEncDef()
defer mkeEncoder.Destroy()
// Need entropy, nonce and personalization string
// *** IMPORTANT NOTE ***
// Entropy is critical to security and should be created and
// handled like encryption keys. To permit decoding of encoded
// value, Encoder and Decoder must use identical Entropy, Nonce and
// Personalization String as well as Options . See Developer Guides for more information.
//-----------------------------------------------------------------
// The following personalization string and nonce values are for
// demonstration only and should not be used in a production environment
personalizationString := "MySecretPersonalizationStringGoesHere"
nonce := 12345678
// Create all-zero entropy for this demo. The nonce will also be set to 0.
// This should never be done in real applications.
entropyBytes := mte.GetDrbgsEntropyMinBytes(mkeEncoder.GetDrbg())
entropy := make([]byte, entropyBytes)
// Set entropy and nonce
mkeEncoder.SetEntropy(entropy)
mkeEncoder.SetNonceInt(nonce)
// Instantiate the Encoder.
encoderStatus := mkeEncoder.InstantiateStr(personalizationString)
if encoderStatus != mte.Status_mte_status_success {
// Handle an error here -- below is a sample
fmt.Fprintf(os.Stderr, "Encoder instantiate error (%v): %v\n",
mte.GetStatusName(encoderStatus), mte.GetStatusDescription(encoderStatus))
return int(encoderStatus)
}
<?php
// Create MTE MKE Encoder with defaults
$mkeEncoder = new mteMkeEnc();
// Need entropy, nonce and personalization string
// *** IMPORTANT NOTE ***
// Entropy is critical to security and should be created and
// handled like encryption keys. To permit decoding of encoded
// value, Encoder and Decoder must use identical Entropy, Nonce and
// Personalization String as well as Options . See Developer Guides for more information.
//-----------------------------------------------------------------
// The following personalization string and nonce values are for
// demonstration only and should not be used in a production environment
$personalizationString = "MySecretPersonalizationStringGoesHere";
$nonce = 12345678;
// Check how long of entropy we need.
// This example fills entropy with at string of zeros
// this should NOT be used in a production environment
$entropyBytes = $mkeEncoder->getDrbgEntropyMinBytes(constant($mkeEncoder->getDrbg()));
$entropy = "";
$entropy = str_pad($entropy, $entropyBytes);
// Set entropy and nonce
$mkeEncoder->setEntropy($entropy);
$mkeEncoder->setNonce($nonce);
// Instantiate the Encoder.
$encoded = $mkeEncoder->instantiate($personalizationString);
if (constant($encoded["status"])==mte_status_success) {
// Handle an error here -- below is a sample
echo "Encoder instantiate error: "
.$mkeEncoder->getStatusName(constant($encoded["status"])).":"
.$mkeEncoder->getStatusDescription(constant($encoded["status"]));
return $mkeEncoder->getStatusCode(constant($encoded["status"]));
}
?>
Encoding a string or byte[]
Use the following methods to encode a string or a byte[]. The samples below display all the options that can be used to encode, only one method needs to be used to encode the data. The developer should select the method that works with the type of data that is used.
- C
- C++
- CSharp
- Java
- JavaScript
- Swift
- Python
- Go
- PHP
/* There are different functions available to use depending on program needs.
* The versions with b64 in the function name involve base 64 conversion,
* suitable for protocols requiring a string representation.
* Otherwise the default will use raw bytes.
*/
/* Allocate the buffer for encoding. */
char* encoded = MTE_ALLOCA(mte_mke_enc_buff_bytes_b64(encoder));
/* Encode the message. */
MTE_SET_ENC_IO(e_args, input, input_bytes, encoded);
status = mte_mke_enc_encode_b64(encoder, &e_args);
if (status != mte_status_success)
{
fprintf(stderr, "Encode error (%s): %s\n",
mte_base_status_name(status),
mte_base_status_description(status));
return status;
}
The timestamp callback.
static MTE_UINT64_T t_cb(void* context)
{
char line[80];
(void)context;
/* Get the timestamp. */
printf("Enter the timestamp (decimal digits only)> ");
fflush(stdout);
(void)!fgets(line, sizeof(line), stdin);
return strtoul(line, NULL, 10);
}
// There are different functions available to use depending on program needs.
// The versions with b64 in the function name involve base 64 conversion,
// suitable for protocols requiring a string representation.
// Otherwise the default will use raw bytes.
size_t encodedBytes = 0;
// Encode the message.
const void* encoded = encoder.encode(input, inputBytes, encodedBytes, status);
if (status != mte_status_success)
{
std::cerr << "Encode error ("
<< MteBase::getStatusName(status)
<< "): "
<< MteBase::getStatusDescription(status)
<< std::endl;
return status;
}
The timestamp callback.
MTE_UINT64_T Cbs::timestampCallback()
{
// Display a prompt.
std::cout << "Enter the timestamp (decimal digits only)> " << std::flush;
// Get the timestamp and ignore the rest of the line.
MTE_UINT64_T u64;
std::cin >> u64;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
return u64;
}
// Use MKE Encoder created in previous example
// Example values to be encoded
string inputString = "What I want to be encoded goes here";
byte[] bytesToBeEncoded = Encoding.ASCII.GetBytes(inputString);
// Initialize MTEStatus
MteStatus encoderStatus;
// Below are 4 different examples of how to encode
// ONLY ONE needs to be used.
// Encode byte[] to a base64 string
string encodedBytesAsString = mkeEncoder.EncodeB64(bytesToBeEncoded, out encoderStatus);
if(encoderStatus != MteStatus.mte_status_success)
{
// Handle encode failure appropriately
// Below is only an example
throw new Exception("Failed to encode. Status: "
+ mkeEncoder.GetStatusName(encoderStatus)+ " / "
+ mkeEncoder.GetStatusDescription(encoderStatus));
}
// Encode string to a base64 string
string encodedStringAsString = mkeEncoder.EncodeB64(inputString, out encoderStatus);
if(encoderStatus != MteStatus.mte_status_success)
{
// Handle encode failure appropriately
// Below is only an example
throw new Exception("Failed to encode. Status: "
+ mkeEncoder.GetStatusName(encoderStatus)+ " / "
+ mkeEncoder.GetStatusDescription(encoderStatus));
}
// Encode byte[] to a byte[]
byte[] encodedBytesAsBytes = mkeEncoder.Encode(bytesToBeEncoded, out encoderStatus);
if(encoderStatus != MteStatus.mte_status_success)
{
// Handle encode failure appropriately
// Below is only an example
throw new Exception("Failed to encode. Status: "
+ mkeEncoder.GetStatusName(encoderStatus)+ " / "
+ mkeEncoder.GetStatusDescription(encoderStatus));
}
// Encode string to a byte[]
byte[] encodedStringAsBytes = mkeEncoder.Encode(inputString, out encoderStatus);
if(encoderStatus != MteStatus.mte_status_success)
{
// Handle encode failure appropriately
// Below is only an example
throw new Exception("Failed to encode. Status: "
+ mkeEncoder.GetStatusName(encoderStatus)+ " / "
+ mkeEncoder.GetStatusDescription(encoderStatus));
}
// Use MKE Encoder created in previous example
// Example values to be encoded
String inputString = "What I want to be encoded goes here";
byte[] bytesToBeEncoded = inputString.getBytes(StandardCharsets.UTF_16);
// Initialize MteStatus
MteStatus encoderStatus;
// Below are 4 different examples of how to encode
// ONLY ONE needs to be used!!!
// Encode byte[] to a base64 string
String encodedBytesAsString = mkeEncoder.encodeB64(bytesToBeEncoded, out encoderStatus);
if(encoderStatus != MteStatus.mte_status_success)
{
// Handle encode failure appropriately
// Below is only an example
throw new Exception("Failed to encode. Status: "
+ MteBase.getStatusName(encoderStatus)+ " / "
+ MteBase.getStatusDescription(encoderStatus));
}
// Encode string to a base64 string
String encodedStringAsString = mkeEncoder.encodeB64(inputString, out encoderStatus);
if(encoderStatus != MteStatus.mte_status_success)
{
// Handle encode failure appropriately
// Below is only an example
throw new Exception("Failed to encode. Status: "
+ MteBase.getStatusName(encoderStatus)+ " / "
+ MteBase.getStatusDescription(encoderStatus));
}
// Encode byte[] to a byte[]
byte[] encodedBytesAsBytes = mkeEncoder.encode(bytesToBeEncoded, out encoderStatus);
if(encoderStatus != MteStatus.mte_status_success)
{
// Handle encode failure appropriately
// Below is only an example
throw new Exception("Failed to encode. Status: "
+ MteBase.getStatusName(encoderStatus)+ " / "
+ MteBase.getStatusDescription(encoderStatus));
}
// Encode string to a byte[]
byte[] encodedStringAsBytes = mkeEncoder.encode(inputString, out encoderStatus);
if(encoderStatus != MteStatus.mte_status_success)
{
// Handle encode failure appropriately
// Below is only an example
throw new Exception("Failed to encode. Status: "
+ MteBase.getStatusName(encoderStatus)+ " / "
+ MteBase.getStatusDescription(encoderStatus));
}
Below are 4 different examples of how to encode. ONLY ONE needs to be used.
// Encode string and return as B64 string
const inputString = "What I want to be encoded goes here.";
const encoderResult = mkeEncoder.encodeStrB64(inputString);
if (encoderResult.status !== MteStatus.mte_status_success) {
const status = mteBase.getStatusName(encoderResult);
const message = mteBase.getStatusDescription(encoderResult);
throw new Error(`Error when MTE encoding data.\n${status}: ${message}`);
}
// encoderResult.str contains encoded result
// Encode string and return as Uint8Array
const inputString = "What I want to be encoded goes here.";
const encoderResult = mkeEncoder.encoderStr(inputString);
if (encoderResult.status !== MteStatus.mte_status_success) {
const status = mteBase.getStatusName(encoderResult);
const message = mteBase.getStatusDescription(encoderResult);
throw new Error(`Error when MTE encoding data.\n${status}: ${message}`);
}
// encoderResult.arr contains encoded result
// Encode Uint8Array and return as b64 string
const inputArray = new Uint8Array([9, 19, 89]);
const encoderResult = mkeEncoder.encodeB64(inputArray);
if (encoderResult.status !== MteStatus.mte_status_success) {
const status = mteBase.getStatusName(encoderResult);
const message = mteBase.getStatusDescription(encoderResult);
throw new Error(`Error when MTE encoding data.\n${status}: ${message}`);
}
// encoderResult.str contains encoded result
// Encode Uint8Array and return as Uint8Array
const inputArray = new Uint8Array([9, 19, 89]);
const encoderResult = mkeEncoder.encode(inputArray);
if (encoderResult.status !== MteStatus.mte_status_success) {
const status = mteBase.getStatusName(encoderResult);
const message = mteBase.getStatusDescription(encoderResult);
throw new Error(`Error when MTE encoding data.\n${status}: ${message}`);
}
// encoderResult.arr contains encoded result
// There are different functions available to use depending on program needs.
// The versions with b64 in the function name involve base 64 conversion,
// suitable for protocols requiring a string representation.
// Otherwise the default will use raw bytes.
// Encode the message.
let encodedRes = encoder.encode(input)
status = encodedRes.status
if (status != mte_status_success) {
print("Encode error (\(MteBase.getStatusName(status))): " +
MteBase.getStatusDescription(status))
return Int32(status.rawValue)
}
The timestamp callback.
func timestampCallback() -> UInt64 {
// Display a prompt.
print("Enter the timestamp (decimal digits only)> ", terminator: "")
// Get the timestamp and ignore the rest of the line.
return UInt64(readLine()!)!
}
# Use MKE Encoder created in previous example.
# Example values to be encoded.
input_string = "What I want to be encoded goes here"
bytes_to_be_encoded = bytes(input_string,'utf-8')
# Below are 4 different examples of how to encode.
# ONLY ONE needs to be used.
# Encode byte[] to a base64 string.
(encoded_bytes_as_string, encoder_status) = mke_encoder.encode_b64(bytes_to_be_encoded)
if encoder_status != MteStatus.mte_status_success:
# Handle encode failure appropriately.
# Below is only an example.
raise Exception("Failed to encode. Status: {0} / {1}\n".format(MteBase.get_status_name(encoder_status),
MteBase.get_status_description(encoder_status)))
# Encode string to a base64 string.
(encoded_string_as_string, encoder_status) = mke_encoder.encode_b64(input_string)
if encoder_status != MteStatus.mte_status_success:
# Handle encode failure appropriately.
# Below is only an example.
raise Exception("Failed to encode. Status: {0} / {1}\n".format(MteBase.get_status_name(encoder_status),
MteBase.get_status_description(encoder_status)))
# Encode byte[] to a byte[].
(encoded_bytes_as_string, encoder_status) = mke_encoder.encode(bytes_to_be_encoded)
if encoder_status != MteStatus.mte_status_success:
# Handle encode failure appropriately.
# Below is only an example.
raise Exception("Failed to encode. Status: {0} / {1}\n".format(MteBase.get_status_name(encoder_status),
MteBase.get_status_description(encoder_status)))
# Encode string to a byte[].
(encoded_string_as_bytes, encoder_status) = mke_encoder.encode(input_string)
if encoder_status != MteStatus.mte_status_success:
# Handle encode failure appropriately.
# Below is only an example.
raise Exception("Failed to encode. Status: {0} / {1}\n".format(MteBase.get_status_name(encoder_status),
MteBase.get_status_description(encoder_status)))
// Example values to be encoded
inputString := "Message we are going to encode"
inputBytes := []byte(inputString)
// initialize status
var encoderStatus mte.Status
// Below are 4 different examples of how to encode
// ONLY ONE needs to be used.
// Encode string to a base64 string
encodedString, encoderStatus := mkeEncoder.EncodeStrB64(inputString)
if(encoderStatus != mte.Status_mte_status_success){
// Handle error -- example below
fmt.Fprintf(os.Stderr, "Encode error (%v): %v\n",
mte.GetStatusName(encoderStatus), mte.GetStatusDescription(encoderStatus))
return int(encoderStatus)
}
// Encode byte[] to a base64 string
encodedString, encoderStatus := mkeEncoder.EncodeB64(inputBytes)
if(encoderStatus != mte.Status_mte_status_success){
// Handle error -- example below
fmt.Fprintf(os.Stderr, "Encode error (%v): %v\n",
mte.GetStatusName(encoderStatus), mte.GetStatusDescription(encoderStatus))
return int(encoderStatus)
}
// Encode string to a byte array
encodedBytes, encoderStatus := mkeEncoder.EncodeStr(inputString)
if(encoderStatus != mte.Status_mte_status_success){
// Handle error -- example below
fmt.Fprintf(os.Stderr, "Encode error (%v): %v\n",
mte.GetStatusName(encoderStatus), mte.GetStatusDescription(encoderStatus))
return int(encoderStatus)
}
// Encode bytes to byte array
encodedBytes, encoderStatus := mkeEncoder.Encode(inputBytes)
if(encoderStatus != mte.Status_mte_status_success){
// Handle error -- example below
fmt.Fprintf(os.Stderr, "Encode error (%v): %v\n",
mte.GetStatusName(encoderStatus), mte.GetStatusDescription(encoderStatus))
return int(encoderStatus)
}
<?php
// Example value to be encoded
$inputString = "What I want to be encoded goes here";
// Below are 2 different examples of how to encode
// ONLY ONE needs to be used!!!
?>
<?php
// Encode String to String
$encoded = $mkeEncoder->encode($inputString);
// Check the status
if (constant($encoded["status"])!=mte_status_success){
// Handle an error here -- below is a sample
throw new Exception("Encoder encode error: "
.$mkeEncoder->getStatusName(constant($encoded["status"])).":"
.$mkeEncoder->getStatusDescription(constant($encoded["status"])));
}
?>
<?php
// Encode string to Base64 String
$base64encoded = $mkeEncoder->encodeB64($inputString);
// Check the status
if (constant($base64encoded["status"])!=mte_status_success){
// Handle an error here -- below is a sample
throw new Exception("Encoder encode error: "
.$mkeEncoder->getStatusName(constant($base64encoded["status"])).":"
.$mkeEncoder->getStatusDescription(constant($base64encoded["status"])));
}
?>
MKE Encoder State
The encoder state can be saved and restored with either byte[] or a base64 string using the following methods. Below are several examples of how to use it, based on your data type you only need to use one of the following examples.
- C
- C++
- CSharp
- Java
- JavaScript
- Swift
- Python
- Go
- PHP
Save state.
/* There are different functions available to use depending on program needs.
* The versions with b64 in the function name involve base 64 conversion,
* suitable for protocols requiring a string representation.
* Otherwise the default will use raw bytes.
*/
/* Save the encoder state. */
/* Saved state. */
MTE_UINT8_T* e_saved = MTE_ALLOCA(mte_mke_enc_save_bytes(encoder));
status = mte_mke_enc_state_save(encoder, e_saved);
if (status != mte_status_success)
{
fputs("Encoder state save error.", stderr);
return mte_status_unsupported;
}
Restore state.
/* Restore the encoder state. */
status = mte_mke_enc_state_restore(encoder, e_saved);
if (status != mte_status_success)
{
fprintf(stderr, "Encoder state restore error (%s): %s\n",
mte_base_status_name(status),
mte_base_status_description(status));
return status;
}
Save state.
// There are different functions available to use depending on program needs.
// The versions with b64 in the function name involve base 64 conversion,
// suitable for protocols requiring a string representation.
// Otherwise the default will use raw bytes.
// Save the encoder state.
size_t eSavedBytes = 0;
const void* esaved = encoder.saveState(eSavedBytes);
if (esaved == NULL)
{
std::cerr << "Encoder state save error." << std::endl;
return mte_status_unsupported;
}
Restore state.
// Restore the encoder state.
status = encoder.restoreState(esaved);
if (status != mte_status_success)
{
std::cerr << "Encoder state restore error." << std::endl;
return status;
}
// Save and restore Encoder state with bytes
// Get byte[] of Encoder state
byte[] encoderByteState = mkeEncoder.SaveState();
// Restore Encoder with byte[] state
MteStatus encoderStatus = mkeEncoder.RestoreState(encoderByteState);
if(encoderStatus != MteStatus.mte_status_success)
{
// Mte cannot continue, handle restore failure appropriately
// Below is only an example
throw new Exception("Failed to restore Encoder state. Status: "
+ mkeEncoder.GetStatusName(encoderStatus)+ " / "
+ mkeEncoder.GetStatusDescription(encoderStatus));
}
// Save and restore Encoder state with string
// Get string of Encoder state
string encoderStrState = mkeEncoder.SaveStateB64();
// Restore Encoder with string state
MteStatus encoderStatus = mkeEncoder.RestoreStateB64(encoderStrState);
if(encoderStatus != MteStatus.mte_status_success)
{
// Mte cannot continue, handle restore failure appropriately
// Below is only an example
throw new Exception("Failed to restore Encoder state. Status: "
+ mkeEncoder.GetStatusName(encoderStatus)+ " / "
+ mkeEncoder.GetStatusDescription(encoderStatus));
}
// Save and restore Encoder state with bytes
// Get byte[] of Encoder state
byte[] encoderByteState = mkeEncoder.saveState();
// Restore Encoder with byte[] state
MteStatus encoderStatus = mkeEncoder.restoreState(encoderByteState);
if(encoderStatus != MteStatus.mte_status_success)
{
// Mte cannot continue, handle restore failure appropriately
// Below is only an example
throw new Exception("Failed to restore Encoder state. Status: "
+ MteBase.getStatusName(encoderStatus)+ " / "
+ MteBase.getStatusDescription(encoderStatus));
}
// Save and restore Encoder state with bytes
// Get string of Encoder state
string encoderStrState = mkeEncoder.saveStateB64();
// Restore Encoder with string state
MteStatus encoderStatus = mkeEncoder.restoreStateB64(encoderStrState);
if(encoderStatus != MteStatus.mte_status_success)
{
// Mte cannot continue, handle restore failure appropriately
// Below is only an example
throw new Exception("Failed to restore Encoder state. Status: "
+ MteBase.getStatusName(encoderStatus)+ " / "
+ MteBase.getStatusDescription(encoderStatus));
}
// Save and restore Encoder state with bytes
// Get Uint8Array of Encoder state
const state = mkeEncoder.saveState();
// Restore Encoder with Uint8Array state
const encoderStatus = mkeEncoder.restoreState(state);
if (encoderStatus !== MteStatus.mte_status_success) {
// MTE cannot continue so handle failure appropriately
// Below is an Example
const status = mteBase.getStatusName(encoderStatus);
const message = mteBase.getStatusDescription(encoderStatus);
throw new Error(`Error instantiating MKE Encoder.\n${status}: ${message}`);
}
// Save and restore Encoder state with string
// Get string of Encoder state
const state = mkeEncoder.saveStateB64();
// Restore Encoder with string state
const encoderStatus = mkeEncoder.restoreStateB64(state);
if (encoderStatus !== MteStatus.mte_status_success) {
// MTE cannot continue so handle failure appropriately
// Below is an Example
const status = mteBase.getStatusName(encoderStatus);
const message = mteBase.getStatusDescription(encoderStatus);
throw new Error(`Error instantiating MKE Encoder.\n${status}: ${message}`);
}
// There are different functions available to use depending on program needs.
// The versions with b64 in the function name involve base 64 conversion,
// suitable for protocols requiring a string representation.
// Otherwise the default will use raw bytes.
// Save the encoder state.
let esaved = encoder.saveState()
if esaved == nil {
print("Encoder state save error.")
return Int32(mte_status_unsupported.rawValue)
}
# Save and restore Encoder state with bytes.
# Get byte[] of Encoder state.
encoder_byte_state = mke_encoder.save_state()
# Restore Encoder with byte[] state.
encoder_status = mke_encoder.restore_state(encoder_byte_state)
if encoder_status != MteStatus.mte_status_success:
# Mte cannot continue, handle restore failure appropriately.
# Below is only an example.
raise Exception("Failed to restore Encoder state. Status: {0} / {1}\n".format(MteBase.get_status_name(encoder_status),
MteBase.get_status_description(encoder_status)))
# Save and restore Encoder state with string.
# Get string of Encoder state.
encoder_str_state = mke_encoder.save_state_b64()
# Restore Encoder with string state.
encoder_status = mke_encoder.restore_state_b64(encoder_str_state)
if encoder_status != MteStatus.mte_status_success:
# Mte cannot continue, handle restore failure appropriately.
# Below is only an example.
raise Exception("Failed to restore Encoder state. Status: {0} / {1}\n".format(MteBase.get_status_name(encoder_status),
MteBase.get_status_description(encoder_status)))
// Save and restore MKE Encoder state with bytes
// Get byte[] of Encoder state
encoderByteState := mkeEncoder.SaveState()
encoderStatus := mkeEncoder.RestoreState(encoderByteState);
if(encoderStatus != mte.Status_mte_status_success){
// Handle Encoder restore state failure appropriately
// Below is only an example
fmt.Fprintf(os.Stderr, "Restore Encoder state error (%v): %v\n",
mte.GetStatusName(encoderStatus), mte.GetStatusDescription(encoderStatus))
return int(encoderStatus)
}
// Save and restore MKE Encoder state with bytes
// Get byte[] of Encoder state
encoderStrState := mkeEncoder.SaveStateB64()
encoderStatus := mkeEncoder.RestoreStateB64(encoderStrState);
if(encoderStatus != mte.Status_mte_status_success){
// Handle Encoder restore state failure appropriately
// Below is only an example
fmt.Fprintf(os.Stderr, "Restore Encoder state error (%v): %v\n",
mte.GetStatusName(encoderStatus), mte.GetStatusDescription(encoderStatus))
return int(encoderStatus)
}
<?php
$encoderStrState = $mkeEncoder->saveState();
$restoreStatus = $mkeEncoder->restoreState($encoderStrState);
if (constant($restoreStatus)!=mte_status_success){
// Handle an error here -- below is a sample
echo "Encoder restore state error: "
.$mkeEncoder->getStatusName(constant($restoreStatus)).":"
.$mkeEncoder->getStatusDescription(constant($restoreStatus));
return $mkeEncoder->getStatusCode(constant($restoreStatus));
}
?>
<?php
$encoderB64State = $mkeEncoder->saveStateB64();
$restoreStatus = $mkeEncoder->restoreStateB64($encoderB64State);
if (constant($restoreStatus)!=mte_status_success){
// Handle an error here -- below is a sample
echo "Encoder restore base64 state error: "
.$mkeEncoder->getStatusName(constant($restoreStatus)).":"
.$mkeEncoder->getStatusDescription(constant($restoreStatus));
return $mkeEncoder->getStatusCode(constant($restoreStatus));
}
?>
Additional options for Encoder State
The Core MTE encoder state and the MTE MKE encoder state are interchangeable. This means, the encoder state can be restored to an MTE Core OR an MTE MKE. The MTE used should be created using the same options for this to work correctly. The security of the MTE Core can be used for a password then the MTE MKE can be used on larger data in the same application without having to create multiple instances of the MTE.
Uninstantiate MKE Encoder
Uninstantiate MKE encoder, this will zeroize the DRBG state and returns the status.
- C
- C++
- CSharp
- Java
- JavaScript
- Swift
- Python
- Go
- PHP
status = mte_mke_enc_uninstantiate(encoder);
if (status != mte_status_success)
{
fprintf(stderr, "Failed to uninstantiate encoder (%s): %s\n",
mte_base_status_name(status),
mte_base_status_description(status));
return status;
}
status = encoder.uninstantiate();
if (status != mte_status_success)
{
std::cerr << "Encoder uninstantiate error ("
<< MteBase::getStatusName(status)
<< "): "
<< MteBase::getStatusDescription(status)
<< std::endl;
return status;
}
// Uninstantiate the MKE Encoder
MteStatus encoderStatus = mkeEncoder.Uninstantiate();
if(encoderStatus != MteStatus.mte_status_success)
{
// MTE was not uninstantiated as desired so handle failure appropriately
// Below is only an example
throw new Exception("Failed to uninstantiate Encoder. Status: "
+ mkeEncoder.GetStatusName(encoderStatus)+ " / "
+ mkeEncoder.GetStatusDescription(encoderStatus));
}
// Uninstantiate the MKE Encoder
MteStatus encoderStatus = mkeEncoder.uninstantiate();
if(encoderStatus != MteStatus.mte_status_success)
{
// MTE was not uninstantiated as desired so handle failure appropriately
// Below is only an example
throw new Exception("Failed to uninstantiate Encoder. Status: "
+ MteBase.getStatusName(encoderStatus)+ " / "
+ MteBase.getStatusDescription(encoderStatus));
}
// Uninstantiate the MKE Encoder
const encoderStatus = mkeEncoder.uninstantiate();
if (encoderStatus !== MteStatus.mte_status_success) {
// MTE cannot continue so handle failure appropriately
// Below is an Example
const status = mteBase.getStatusName(encoderStatus);
const message = mteBase.getStatusDescription(encoderStatus);
throw new Error(`Error uninstantiating MKE Encoder.\n${status}: ${message}`);
}
// Free WASM memory
mkeEncoder.destroy();
// Uninstantiate the Encoder
let status: mte_status = encoder.uninstantiate()
if status != mte_status_success {
// MTE was not uninstantiated as desired so handle failure appropriately
print("Encoder Uninstantiate error: \(MteBase.getStatusName(status))." +
"Description: \(MteBase.getStatusDescription(status))"
}
# Uninstantiate the MKE Encoder.
encoder_status = mke_encoder.uninstantiate()
if encoder_status != MteStatus.mte_status_success:
# MTE was not uninstantiated as desired so handle failure appropriately.
# Below is only an example.
raise Exception("Failed to uninstantiate Encoder. Status: {0} / {1}\n".format(MteBase.get_status_name(encoder_status),
MteBase.get_status_description(encoder_status)))
// Uninstantiate the MKE Encoder
encoderStatus := mkeEncoder.Uninstantiate();
if(encoderStatus != mte.Status_mte_status_success){
// Handle Encoder uninstantiate failure appropriately
// Below is only an example
fmt.Fprintf(os.Stderr, "Encoder uninstantiate error (%v): %v\n",
mte.GetStatusName(encoderStatus), mte.GetStatusDescription(encoderStatus))
return int(encoderStatus)
}
<?php
// Uninstantiate the Encoder
$encoderStatus = $mkeEncoder->uninstantiate();
if (constant($encoderStatus) != mte_status_success) {
//----------------------------------------------------
// Handle Encoder uninstantiate failure appropriately
// Below is only an example
echo "Encoder uninstantiate error: ".$mkeEncoder->getStatusName(constant($encoderStatus)).":"
.$mkeEncoder->getStatusDescription(constant($encoderStatus));
return $mkeEncoder->getStatusCode(constant($encoderStatus));
}
// Clear out $mteEncoder variable
unset($mkeEncoder);
?>
MTE Managed Key Encryption (MKE) Decoder
Create MTE MKE Decoder
The MTE MKE Decoder will be created using default options. The default options will set preferred security options recommended by Eclypses. Custom options should only be used in special circumstances and after reading and understanding how to select the best options for a given situation. More information about how to select these options can be found in the official MTE Developer Guides.
Create Default Decoder
- C
- C++
- CSharp
- Java
- JavaScript
- Swift
- Python
- Go
- PHP
/* Create the decoder. */
MTE_HANDLE decoder;
mte_mke_dec_init_info d_info = MTE_MKE_DEC_INIT_INFO_INIT(
MTE_DRBG_ENUM, MTE_TOKBYTES, MTE_VERIFIERS_ENUM,
MTE_CIPHER_ENUM, MTE_HASH_ENUM, 1, 0, NULL, NULL, NULL, NULL, NULL, NULL);
mte_dec_args d_args = MTE_DEC_ARGS_INIT(NULL, 0, NULL, &t_cb, NULL);
decoder = MTE_ALLOCA(mte_mke_dec_state_bytes(&d_info));
status = mte_mke_dec_state_init(decoder, &d_info);
if (status != mte_status_success)
{
fprintf(stderr, "Decoder init error (%s): %s\n",
mte_base_status_name(status),
mte_base_status_description(status));
return status;
}
status = mte_mke_dec_instantiate(decoder, &i_info);
if (status != mte_status_success)
{
fprintf(stderr, "Decoder instantiate error (%s): %s\n",
mte_base_status_name(status),
mte_base_status_description(status));
return status;
}
The entropy and nonce callbacks.
static mte_status ei_cb(void* context, mte_drbg_ei_info* info)
{
MTE_SIZE_T input_bytes;
(void)context;
/* Get the entropy. */
printf("Enter %u-%lu bytes of entropy> ",
(unsigned)info->min_length,
(unsigned long)info->max_length);
fflush(stdout);
(void)!fgets(ei_buff, sizeof(ei_buff), stdin);
input_bytes = (MTE_SIZE_T)(strlen(ei_buff) - 1);
/* If the entropy is less than the minimum required, we must return an
error. */
if (input_bytes < info->min_length)
{
return mte_status_drbg_catastrophic;
}
else if (input_bytes > info->bytes)
{
/* If the entropy is longer than the provided buffer, point at our buffer
instead. */
info->buff = (MTE_UINT8_T*)ei_buff;
}
else
{
/* Otherwise copy the entropy to the provided buffer. */
memcpy(info->buff, ei_buff, input_bytes);
}
/* Set the actual entropy length. */
info->bytes = input_bytes;
/* We got it successfully. */
return mte_status_success;
}
static void n_cb(void* context, mte_drbg_nonce_info* info)
{
MTE_SIZE8_T i;
MTE_UINT64_T u64;
char line[80];
(void)context;
/* Get the nonce. */
printf("Enter the nonce (decimal digits only)> ");
fflush(stdout);
(void)!fgets(line, sizeof(line), stdin);
u64 = strtoul(line, NULL, 10);
/* Copy the nonce in little-endian format to the nonce buffer. */
for (i = 0; i < info->max_length && i < sizeof(u64); ++i)
{
info->buff[i] = (MTE_UINT8_T)(u64 >> (i * 8));
}
/* If the minimum length is greater than the size of the nonce we got, fill
up to that length with zeros. */
for (; i < info->min_length; ++i)
{
info->buff[i] = 0;
}
/* Set the actual nonce length. */
info->bytes = i;
}
// Create the decoder.
MteMkeDec decoder;
decoder.setEntropyCallback(&cbs);
decoder.setNonceCallback(&cbs);
decoder.setTimestampCallback(&cbs);
status = decoder.instantiate(personal);
if (status != mte_status_success)
{
std::cerr << "Decoder instantiate error ("
<< MteBase::getStatusName(status)
<< "): "
<< MteBase::getStatusDescription(status)
<< std::endl;
return status;
}
The entropy and nonce callbacks.
mte_status Cbs::entropyCallback(mte_drbg_ei_info& info)
{
// Display a prompt.
std::cout << "Enter "
<< static_cast<size_t>(info.min_length) << '-' << info.max_length
<< " bytes of entropy> " << std::flush;
// Get a line of input.
std::string line;
std::cin >> line;
// If the input was less than the minimum required, we must return an error.
if (line.size() < info.min_length)
{
return mte_status_drbg_catastrophic;
}
// Set the actual entropy length. It cannot exceed the maximum required.
size_t buffBytes = info.bytes;
info.bytes = std::min(static_cast<MTE_SIZE_T>(line.size()), info.max_length);
// If the length is greater than the length of the provided buffer, we have
// to create our own buffer instead.
if (info.bytes > buffBytes)
{
delete [] myEntropy;
myEntropy = new uint8_t[info.bytes];
info.buff = myEntropy;
}
// Copy the entropy to the buffer and we got it successfully.
memcpy(info.buff, line.data(), info.bytes);
return mte_status_success;
}
void Cbs::nonceCallback(mte_drbg_nonce_info& info)
{
// Display a prompt.
std::cout << "Enter the nonce (decimal digits only)> " << std::flush;
// Get the nonce and ignore the rest of the line.
MTE_UINT64_T u64;
std::cin >> u64;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// Copy the nonce in little-endian format to the nonce buffer.
size_t i;
for (i = 0; i < info.max_length && i < sizeof(u64); ++i)
{
info.buff[i] = static_cast<MTE_UINT8_T>(u64 >> (i * 8));
}
// If the minimum length is greater than the size of the nonce we got, fill
// up to that length with zeros.
for (; i < info.min_length; ++i)
{
info.buff[i] = 0;
}
// Set the actual nonce length.
info.bytes = static_cast<MTE_SIZE8_T>(i);
}
// Create MTE MKE Decoder with defaults
MteMkeDec mkeDecoder = new MteMkeDec();
// Need entropy, nonce and personalization string
// *** IMPORTANT NOTE ***
// Entropy is critical to security and should be created and
// handled like encryption keys. To permit decoding of encoded
// value, Encoder and Decoder must use identical Entropy, Nonce and
// Personalization String as well as Options . See Developer Guides for more information.
//-----------------------------------------------------------------
// The following personalization string and nonce values are for
// demonstration only and should not be used in a production environment
string personalizationString = "MySecretPersonalizationStringGoesHere";
long nonce = 12345678;
// Check how long of entropy we need.
// This example fills entropy with at string of zeros
// this should NOT be used in a production environment
int entropyMinBytes = mkeDecoder.GetDrbgsEntropyMinBytes(mkeDecoder.GetDrbg());
string entropy = (entropyMinBytes > 0)
? new String('0', entropyMinBytes)
: string.Empty;
// Set Decoder entropy and nonce
mkeDecoder.SetEntropy(Encoding.UTF8.GetBytes(entropyString));
mkeDecoder.SetNonce(nonce);
// Initialize MTE Decoder
MteStatus decoderStatus = mkeDecoder.Instantiate(personalizationString);
if(decoderStatus !=MteStatus.mte_status_success)
{
// MTE cannot continue so handle failure appropriately
// Below is an Example
throw new ApplicationException($"Failed to initialize the MTE Decoder engine." +
$"Status: {mkeDecoder.GetStatusName(decoderStatus)} / " +
$"{mkeDecoder.GetStatusDescription(decoderStatus)}");
}
// Create the MTE MKE Decoder
MteMkeDec mkeDecoder = new MteMkeDec();
// Need entropy, nonce and personalization string
// *** IMPORTANT NOTE ***
// Entropy is critical to security and should be created and
// handled like encryption keys. To permit decoding of encoded
// value, Encoder and Decoder must use identical Entropy, Nonce and
// Personalization String as well as Options . See Developer Guides for more information.
//-----------------------------------------------------------------
// The following personalization string and nonce values are for
// demonstration only and should not be used in a production environment
String personalizationString = "MySecretPersonalizationStringGoesHere";
long nonce = 12345678;
// Check how long of entropy we need.
// This example fills entropy with at string of zeros
// this should NOT be used in a production environment
int entropyMinBytes = MteBase.getDrbgsEntropyMinBytes(mkeDecoder.getDrbg());
StringBuffer outputBuffer = new StringBuffer(entropyMinBytes);
for (int i = 0; i < entropyMinBytes; i++){
outputBuffer.append("0");
}
String entropy = outputBuffer.toString();
entropy.replace(' ', '0');
// Set encoder entropy and nonce
mkeDecoder.setEntropy(entropy.getBytes());
mkeDecoder.setNonce(nonce);
// Initialize MTE Decoder
MteStatus decoderStatus = mkeDecoder.instantiate(personalizationString.getBytes());
if (decoderStatus != MteStatus.mte_status_success)
{
// MTE cannot continue so handle failure appropriately
// Below is an Example
throw new Exception("Failed to initialize the MTE Decoder engine. Status: "
+ MteBase.getStatusName(decoderStatus)+ " / "
+ MteBase.getStatusDescription(decoderStatus));
}
// Create MTE MKE Decoder with defaults
const mkeDecoder = MteMkeDec.fromdefault(mteWasm);
// Need entropy, nonce and personalization string
// *** IMPORTANT NOTE ***
// Entropy is critical to security and should be created and
// handled like encryption keys. To permit decoding of encoded
// value, Encoder and Decoder must use identical Entropy, Nonce and
// Personalization String as well as Options . See Developer Guides for more information.
//-----------------------------------------------------------------
// The following personalization string and nonce values are for
// demonstration only and should not be used in a production environment
const personalizationString = "MySecretPersonalizationStringGoesHere";
const nonce = 12345678;
// Check how long of entropy we need.
// This example fills entropy with at string of zeros
// this should NOT be used in a production environment
const entropyMinBytes = mkeDecoder.getDrbgsEntropyMinBytes(
mkeDecoder.getDrbg(),
);
const decoderEntropy =
entropyMinBytes > 0 ? "0".repeat(entropyMinBytes) : decoderEntropy;
// Set Decoder entropy and nonce
mkeDecoder.setEntropyStr(entropy);
mkeDecoder.setNonce(nonce);
// Instantiate MTE MKE Decoder
const decoderStatus = mkeDecoder.instantiate(personalizationString);
if (decoderStatus !== MteStatus.mte_status_success) {
// MTE cannot continue so handle failure appropriately
// Below is an Example
const status = mteBase.getStatusName(decoderStatus);
const message = mteBase.getStatusDescription(decoderStatus);
throw new Error(`Error instantiating MKE Decoder.\n${status}: ${message}`);
}
// Create the decoder.
let decoder = try! MteMkeDec()
decoder.setEntropyCallback(cbs)
decoder.setNonceCallback(cbs)
decoder.setTimestampCallback(cbs)
status = decoder.instantiate(personal)
if status != mte_status_success {
print("decoder instantiate error (\(MteBase.getStatusName(status))): " +
MteBase.getStatusDescription(status))
return Int32(status.rawValue)
}
The entropy and nonce callbacks.
class Cbs: MteEntropyCallback, MteNonceCallback, MteTimestampCallback {
func entropyCallback(_ minEntropy: Int,
_ minLength: Int,
_ maxLength: UInt64,
_ entropyInput: inout [UInt8],
_ eiBytes: inout UInt64,
_ entropyLong: inout UnsafeMutableRawPointer?) -> mte_status {
// Display a prompt.
print("Enter \(minLength)-\(maxLength) bytes of entropy> ", terminator: "")
// Get a line of input.
let line = readLine()!
// If the input was less than the minimum required, we must return an error.
if line.utf8.count < minLength {
return mte_status_drbg_catastrophic
}
// Set the actual entropy length. It cannot exceed the maximum required.
let buffBytes = eiBytes
eiBytes = min(UInt64(line.utf8.count), maxLength)
// If the length is greater than the length of the provided buffer, we have
// to create our own buffer instead.
if eiBytes > buffBytes {
// Get the entropy input as an array.
let ei = [UInt8](line.utf8)
// If there is previous raw entropy, deallocate it.
if myEntropyRaw != nil {
myEntropyRaw!.deallocate()
}
// Allocate unsafe memory for the entropy.
myEntropyRaw =
UnsafeMutableRawPointer.allocate(byteCount: ei.count, alignment: 16)
// Copy from the entropy array to the unsafe memory.
ei.withUnsafeBytes { buff in
let raw = myEntropyRaw!.assumingMemoryBound(to: UInt8.self)
let ei = buff.bindMemory(to: UInt8.self)
raw.assign(from: ei.baseAddress!, count: ei.count)
}
// Set the raw pointer to point at the unsafe memory.
entropyLong = myEntropyRaw
}
else {
// Copy the entropy to the buffer.
entropyInput.replaceSubrange(Range(uncheckedBounds: (0, Int(eiBytes))),
with: line.utf8.prefix(Int(eiBytes)))
}
// Success.
return mte_status_success
}
func nonceCallback(_ minLength: Int,
_ maxLength: Int,
_ nonce: inout [UInt8],
_ nBytes: inout Int) {
// Display a prompt.
print("Enter the nonce (decimal digits only)> ", terminator: "")
// Get the nonce and ignore the rest of the line.
let u64 = UInt64(readLine()!)!
// Copy the nonce in little-endian format to the nonce buffer.
let nCopied = min(nonce.count, MemoryLayout.size(ofValue: u64))
for i in 0..<nCopied {
nonce[i] = UInt8(UInt64(u64 >> (i * 8)) & 0xFF)
}
// If the minimum length is greater than the size of the nonce we got, fill
// up to that length with zeros.
if nCopied < minLength {
for i in nCopied..<minLength {
nonce[i] = 0
}
nBytes = minLength
}
else {
nBytes = nCopied
}
}
# Create MTE MKE Decoder with defaults.
mke_decoder = MteMkeDec.fromdefault()
## Need entropy, nonce and personalization string.
# *** IMPORTANT NOTE ***
# Entropy is critical to security and should be created and
# handled like encryption keys. To permit decoding of encoded
# value, Encoder and Decoder must use identical Entropy, Nonce and
# Personalization String as well as Options . See Developer Guides for more information.
#-----------------------------------------------------------------
# The following personalization string and nonce values are for
# demonstration only and should not be used in a production environment.
personalization_string = "MySecretPersonalizationStringGoesHere"
nonce = 12345678
# Check how long of entropy we need.
# This example fills entropy with at string of zeros
# this should NOT be used in a production environment.
entropy_min_bytes = mke_decoder.get_drbgs_entropy_min_bytes(mke_decoder.get_drbg())
entropy = bytes("0" * entropy_min_bytes, 'utf-8')
# Set Decoder entropy and nonce.
mke_decoder.set_entropy(entropy)
mke_decoder.set_nonce(nonce)
# Initialize MTE Decoder.
decoder_status = mke_decoder.instantiate(personalization_string)
if decoder_status != MteStatus.mte_status_success:
# MTE cannot continue so handle failure appropriately.
# Below is an Example.
raise Exception("Failed to initialize the MTE Decoder engine. Status: {0} / {1}\n".format(MteBase.get_status_name(decoder_status),
MteBase.get_status_description(decoder_status)))
// Create MKE Decoder with default options
mkeDecoder := mte.NewMkeDecDef()
defer mkeDecoder.Destroy()
// Need entropy, nonce and personalization string
// These values should be unique and entropy must be treated like encryption keys!
// The following personalization string and nonce values are for
// demonstration only and should not be used in a production environment
personalizationString := "MySecretPersonalizationStringGoesHere";
nonce := 12345678;
// *** IMPORTANT NOTE ***
// Entropy is critical to security and should be created and handled like encryption keys.
// To permit decoding of encoded value, Encoder and Decoder must use identical Entropy, Nonce and
// Personalization String as well as Options . See Developer Guides for more information.
// Check how long of entropy we need.
// This example fills entropy with at string of zeros
// this should NOT be used in a production environment
entropyBytes := mte.GetDrbgsEntropyMinBytes(mkeDecoder.GetDrbg())
entropy := make([]byte, entropyBytes)
// Set entropy and nonce
mkeDecoder.SetEntropy(entropy)
mkeDecoder.SetNonceInt(nonce)
// Instantiate the Decoder.
decoderStatus := mkeDecoder.InstantiateStr(personalizationString)
if status != mte.Status_mte_status_success {
// Handle an error here -- below is a sample
fmt.Fprintf(os.Stderr, "MKE Decoder instantiate error (%v): %v\n",
mte.GetStatusName(decoderStatus), mte.GetStatusDescription(decoderStatus))
return int(decoderStatus)
}
<?php
// Create MTE MKE Decoder with defaults
$mkeDecoder = new mteMkeDec();
// Need entropy, nonce and personalization string
// *** IMPORTANT NOTE ***
// Entropy is critical to security and should be created and
// handled like encryption keys. To permit decoding of encoded
// value, Encoder and Decoder must use identical Entropy, Nonce and
// Personalization String as well as Options . See Developer Guides for more information.
//-----------------------------------------------------------------
// The following personalization string and nonce values are for
// demonstration only and should not be used in a production environment
$personalizationString = "MySecretPersonalizationStringGoesHere";
$nonce = 12345678;
// Check how long of entropy we need.
// This example fills entropy with at string of zeros
// this should NOT be used in a production environment
$entropyBytes = $mkeDecoder->getDrbgEntropyMinBytes(constant($mkeDecoder->getDrbg()));
$entropy = "";
$entropy = str_pad($entropy, $entropyBytes);
// Set entropy and nonce
$mkeDecoder->setEntropy($entropy);
$mkeDecoder->setNonce($nonce);
// Instantiate the Decoder.
$decoded = $mkeDecoder->instantiate($personalizationString);
if (constant($decoded["status"])==mte_status_success) {
// Handle an error here -- below is a sample
echo "Decoder instantiate error: "
.$mkeDecoder->getStatusName(constant($decoded["status"])).":"
.$mkeDecoder->getStatusDescription(constant($decoded["status"]));
return $mkeDecoder->getStatusCode(constant($decoded["status"]));
}
?>
Decoding string or byte[]
Use the following methods to decode a string or a byte[] to the original value. The samples below display all the options that can be used to decode, only one method needs to be used to decode the data. The developer should select the method that works with the type of data that is used.
- C
- C++
- CSharp
- Java
- JavaScript
- Swift
- Python
- Go
- PHP
/* There are different functions available to use depending on program needs.
* The versions with b64 in the function name involve base 64 conversion,
* suitable for protocols requiring a string representation.
* Otherwise the default will use raw bytes.
*/
/* Decode the message. */
MTE_SET_DEC_IO(d_args, e_args.encoded, e_args.bytes, decoded);
status = mte_mke_dec_decode_b64(decoder, &d_args);
if (mte_base_status_is_error(status))
{
fprintf(stderr, "Decode error (%s): %s\n",
mte_base_status_name(status),
mte_base_status_description(status));
return status;
}
else if (status != mte_status_success)
{
fprintf(stderr, "Decode warning (%s): %s\n",
mte_base_status_name(status),
mte_base_status_description(status));
}
The timestamp callback.
static MTE_UINT64_T t_cb(void* context)
{
char line[80];
(void)context;
/* Get the timestamp. */
printf("Enter the timestamp (decimal digits only)> ");
fflush(stdout);
(void)!fgets(line, sizeof(line), stdin);
return strtoul(line, NULL, 10);
}
// There are different functions available to use depending on program needs.
// The versions with b64 in the function name involve base 64 conversion,
// suitable for protocols requiring a string representation.
// Otherwise the default will use raw bytes.
size_t decodedBytes = 0;
// Decode the message.
const void* decoded = decoder.decode(encoded, encodedBytes, decodedBytes, status);
if (MteBase::statusIsError(status))
{
std::cerr << "Decode error ("
<< MteBase::getStatusName(status)
<< "): "
<< MteBase::getStatusDescription(status)
<< std::endl;
return status;
}
else if (status != mte_status_success)
{
std::cerr << "Decode warning ("
<< MteBase::getStatusName(status)
<< "): "
<< MteBase::getStatusDescription(status)
<< std::endl;
}
The timestamp callback.
MTE_UINT64_T Cbs::timestampCallback()
{
// Display a prompt.
std::cout << "Enter the timestamp (decimal digits only)> " << std::flush;
// Get the timestamp and ignore the rest of the line.
MTE_UINT64_T u64;
std::cin >> u64;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
return u64;
}
// Use MKE Decoder created in previous example
// Initialize MteStatus
MteStatus decoderStatus;
// Below are 4 different examples of how to decode
// ONLY ONE needs to be used.
// Decode byte[] to a base64 string
string decodedBytesAsString = mkeDecoder.DecodeStr(encodedBytes, out decoderStatus);
if (mkeDecoder.StatusIsError(decoderStatus)) {
// Unable to decode, this checks for errors, handle failure appropriately
// Below is only an example
Console.Error.WriteLine("Decode error ({0}): {1}",
mkeDecoder.GetStatusName(decoderStatus),
mkeDecoder.GetStatusDescription(decoderStatus));
return (int)status;
// This catches Decoder warnings, the decode process was successful
// But depending on the type of security needed these may be ignored
// Please see Developer Guide for more details.
} else if (status != MteStatus.mte_status_success) {
Console.Error.WriteLine("Decode warning ({0}): {1}",
mkeDecoder.GetStatusName(decoderStatus),
mkeDecoder.GetStatusDescription(decoderStatus));
}
// Decode string to a base64 string
string decodedStringAsString = mkeDecoder.DecodeStrB64(encodedBase64String, out decoderStatus);
if (mkeDecoder.StatusIsError(decoderStatus)) {
// Unable to decode, this checks for errors, handle failure appropriately
// Below is only an example
Console.Error.WriteLine("Decode error ({0}): {1}",
mkeDecoder.GetStatusName(decoderStatus),
mkeDecoder.GetStatusDescription(decoderStatus));
return (int)status;
// This catches Decoder warnings, the decode process was successful
// But depending on the type of security needed these may be ignored
// Please see Developer Guide for more details.
} else if (status != MteStatus.mte_status_success) {
Console.Error.WriteLine("Decode warning ({0}): {1}",
mkeDecoder.GetStatusName(decoderStatus),
mkeDecoder.GetStatusDescription(decoderStatus));
}
// Decode byte[] to a byte[]
byte[] decodedBytes = mkeDecoder.Decode(encodedBytes, out decoderStatus);
if (mkeDecoder.StatusIsError(decoderStatus)) {
// Unable to decode, this checks for errors, handle failure appropriately
// Below is only an example
Console.Error.WriteLine("Decode error ({0}): {1}",
mkeDecoder.GetStatusName(decoderStatus),
mkeDecoder.GetStatusDescription(decoderStatus));
return (int)status;
// This catches Decoder warnings, the decode process was successful
// But depending on the type of security needed these may be ignored
// Please see Developer Guide for more details.
} else if (status != MteStatus.mte_status_success) {
Console.Error.WriteLine("Decode warning ({0}): {1}",
mkeDecoder.GetStatusName(decoderStatus),
mkeDecoder.GetStatusDescription(decoderStatus));
}
// Decode string to a byte[]
byte[] decodedStringAsBytes = mkeDecoder.DecodeB64(encodedBase64String, out decoderStatus);
if (mkeDecoder.StatusIsError(decoderStatus)) {
// Unable to decode, this checks for errors, handle failure appropriately
// Below is only an example
Console.Error.WriteLine("Decode error ({0}): {1}",
mkeDecoder.GetStatusName(decoderStatus),
mkeDecoder.GetStatusDescription(decoderStatus));
return (int)status;
// This catches Decoder warnings, the decode process was successful
// But depending on the type of security needed these may be ignored
// Please see Developer Guide for more details.
} else if (status != MteStatus.mte_status_success) {
Console.Error.WriteLine("Decode warning ({0}): {1}",
mkeDecoder.GetStatusName(decoderStatus),
mkeDecoder.GetStatusDescription(decoderStatus));
}
// Use MKE Decoder created in previous example
// Initialize MteStatus
MteStatus decoderStatus;
// Below are 4 different examples of how to decode
// ONLY ONE needs to be used.
// Decode byte[] to a base64 string
MteBase.StrStatus decoded = mkeDecoder.decodeStr(encodedBytes);
if (MteBase.statusIsError(decoded.status))
{
// Unable to decode, this checks for errors, handle failure appropriately
// Below is only an example
throw new Exception("Failed to decode. Status: "
+ MteBase.getStatusName(decoded.status)+ " / "
+ MteBase.getStatusDescription(decoded.status));
}
else if (decoded.status != MteStatus.mte_status_success)
{
// This catches Decoder warnings, the decode process was successful
// But depending on the type of security needed these may be ignored
// Please see Developer Guide for more details.
System.err.println("Decode warning ("
+ MteBase.getStatusName(decoded.status) + "): "
+ MteBase.getStatusDescription(decoded.status));
}
String decodedBytesAsString = decoded.str;
// Decode string to a base64 string
MteBase.StrStatus decoded = mkeDecoder.decodeStrB64(encodedBase64String);
if (MteBase.statusIsError(decoded.status))
{
// Unable to decode, this checks for errors, handle failure appropriately
// Below is only an example
throw new Exception("Failed to decode. Status: "
+ MteBase.getStatusName(decoded.status)+ " / "
+ MteBase.getStatusDescription(decoded.status));
}
else if (decoded.status != MteStatus.mte_status_success)
{
// This catches Decoder warnings, the decode process was successful
// But depending on the type of security needed these may be ignored
// Please see Developer Guide for more details.
System.err.println("Decode warning ("
+ MteBase.getStatusName(decoded.status) + "): "
+ MteBase.getStatusDescription(decoded.status));
}
String decodedBytesAsString = decoded.str;
// Decode byte[] to a byte[]
MteBase.ArrStatus decoded = mkeDecoder.decode(encodedBytes);
if (MteBase.statusIsError(decoded.status))
{
// Unable to decode, this checks for errors, handle failure appropriately
// Below is only an example
throw new Exception("Failed to decode. Status: "
+ MteBase.getStatusName(decoded.status)+ " / "
+ MteBase.getStatusDescription(decoded.status));
}
else if (decoded.status != MteStatus.mte_status_success)
{
// This catches Decoder warnings, the decode process was successful
// But depending on the type of security needed these may be ignored
// Please see Developer Guide for more details.
System.err.println("Decode warning ("
+ MteBase.getStatusName(decoded.status) + "): "
+ MteBase.getStatusDescription(decoded.status));
}
bytes[] decodedBytesAsBytes = decoded.arr;
// Decode string to a byte[]
MteBase.ArrStatus decoded = mkeDecoder.decodeB64(encodedBase64String, out decoderStatus);
if (MteBase.statusIsError(decoded.status))
{
// Unable to decode, this checks for errors, handle failure appropriately
// Below is only an example
throw new Exception("Failed to decode. Status: "
+ MteBase.getStatusName(decoded.status)+ " / "
+ MteBase.getStatusDescription(decoded.status));
}
else if (decoded.status != MteStatus.mte_status_success)
{
// This catches Decoder warnings, the decode process was successful
// But depending on the type of security needed these may be ignored
// Please see Developer Guide for more details.
System.err.println("Decode warning ("
+ MteBase.getStatusName(decoded.status) + "): "
+ MteBase.getStatusDescription(decoded.status));
}
byte[] decodedStringAsBytes = decoded.arr;
Below are 4 different examples of how to encode. ONLY ONE needs to be used.
// Decode string and return as B64 string
const decoderResult = mkeDecoder.decodeStrB64(str);
if (mkeDecoder.statusIsError(decoderResult.status)) {
// Unable to decode, this checks for errors, handle failure appropriately
// Below is only an example
const status = mkeDecoder.getStatusName(decoderResult.status);
const message = mkeDecoder.getStatusDescription(decoderResult.status);
throw new Error(`Error when MTE decoding data.\n${status}: ${message}`);
return;
} else if (decoderResult.status != MteStatus.mte_status_success) {
// This catches Decoder warnings, the decode process was successful
// But depending on the type of security needed these may be ignored
// Please see Developer Guide for more details.
alert(
"Decode warning (" +
mkeDecoder.getStatusName(decoderResult.status) +
"): " +
mkeDecoder.getStatusDescription(decoderResult.status),
);
}
console.log(`Encode result is: ${decoderResult.str}`);
// Decode string and return as Uint8Array
const decoderResult = mkeDecoder.decoderStr(str);
if (mkeDecoder.statusIsError(decoderResult.status)) {
// Unable to decode, this checks for errors, handle failure appropriately
// Below is only an example
const status = mkeDecoder.getStatusName(decoderResult.status);
const message = mkeDecoder.getStatusDescription(decoderResult.status);
throw new Error(`Error when MTE decoding data.\n${status}: ${message}`);
return;
} else if (decoderResult.status != MteStatus.mte_status_success) {
// This catches Decoder warnings, the decode process was successful
// But depending on the type of security needed these may be ignored
// Please see Developer Guide for more details.
alert(
"Decode warning (" +
mkeDecoder.getStatusName(decoderResult.status) +
"): " +
mkeDecoder.getStatusDescription(decoderResult.status),
);
}
console.log(`Encode result is: ${decoderResult.arr}`);
// Decode Uint8Array and return as b64 string
const decoderResult = mkeDecoder.decodeB64(arr);
if (mkeDecoder.statusIsError(decoderResult.status)) {
// Unable to decode, this checks for errors, handle failure appropriately
// Below is only an example
const status = mkeDecoder.getStatusName(decoderResult.status);
const message = mkeDecoder.getStatusDescription(decoderResult.status);
throw new Error(`Error when MTE decoding data.\n${status}: ${message}`);
return;
} else if (decoderResult.status != MteStatus.mte_status_success) {
// This catches Decoder warnings, the decode process was successful
// But depending on the type of security needed these may be ignored
// Please see Developer Guide for more details.
alert(
"Decode warning (" +
mkeDecoder.getStatusName(decoderResult.status) +
"): " +
mkeDecoder.getStatusDescription(decoderResult.status),
);
}
console.log(`Encode result is: ${decoderResult.str}`);
// Decode Uint8Array and return as Uint8Array
const decoderResult = mkeDecoder.decode(arr);
if (mkeDecoder.statusIsError(decoderResult.status)) {
// Unable to decode, this checks for errors, handle failure appropriately
// Below is only an example
const status = mkeDecoder.getStatusName(decoderResult.status);
const message = mkeDecoder.getStatusDescription(decoderResult.status);
throw new Error(`Error when MTE decoding data.\n${status}: ${message}`);
return;
} else if (decoderResult.status != MteStatus.mte_status_success) {
// This catches Decoder warnings, the decode process was successful
// But depending on the type of security needed these may be ignored
// Please see Developer Guide for more details.
alert(
"Decode warning (" +
mkeDecoder.getStatusName(decoderResult.status) +
"): " +
mkeDecoder.getStatusDescription(decoderResult.status),
);
}
console.log(`Encode result is: ${decoderResult.arr}`);
// There are different functions available to use depending on program needs.
// The versions with b64 in the function name involve base 64 conversion,
// suitable for protocols requiring a string representation.
// Otherwise the default will use raw bytes.
// Decode the message.
let decoded = decoder.decode(Array(encodedRes.encoded))
status = decoded.status
if (MteBase.statusIsError(status)) {
print("Decode error (\(MteBase.getStatusName(status))): " +
MteBase.getStatusDescription(status))
return Int32(status.rawValue)
} else if (status != mte_status_success) {
print("Decode warning (\(MteBase.getStatusName(status))): " +
MteBase.getStatusDescription(status))
}
The timestamp callback.
func timestampCallback() -> UInt64 {
// Display a prompt.
print("Enter the timestamp (decimal digits only)> ", terminator: "")
// Get the timestamp and ignore the rest of the line.
return UInt64(readLine()!)!
}
# Use MKE Decoder created in previous example.
# Below are 4 different examples of how to decode.
# ONLY ONE needs to be used.
# Decode byte[] to a base64 string.
(decoded_bytes_as_string, decoder_status) = mke_decoder.decode_str(encoded_bytes)
if MteBase.status_is_error(decoder_status):
# Handle decode failure appropriately.
# Below is only an example.
raise Exception("Failed to decode. Status: {0} / {1}\n".format(MteBase.get_status_name(decoder_status),
MteBase.get_status_description(decoder_status)))
elif decoder_status != MteStatus.mte_status_success:
# This catches Decoder warnings, the decode process was successful
# But depending on the type of security needed these may be ignored
# Please see Developer Guide for more details.
print("Decode warning ({0}): {1}".format(
MteBase.get_status_name(status),
MteBase.get_status_description(status)),
file=sys.stderr)
# Decode string to a base64 string.
(decoded_string_as_string, decoder_status) = mke_decoder.decode_str_b64(encoded_base64_string)
if MteBase.status_is_error(decoder_status):
# Handle decode failure appropriately.
# Below is only an example.
raise Exception("Failed to decode. Status: {0} / {1}\n".format(MteBase.get_status_name(decoder_status),
MteBase.get_status_description(decoder_status)))
elif decoder_status != MteStatus.mte_status_success:
# This catches Decoder warnings, the decode process was successful
# But depending on the type of security needed these may be ignored
# Please see Developer Guide for more details.
print("Decode warning ({0}): {1}".format(
MteBase.get_status_name(status),
MteBase.get_status_description(status)),
file=sys.stderr)
# Decode byte[] to a byte[].
(decoded_bytes, decoder_status) = mke_decoder.decode(encoded_bytes)
if MteBase.status_is_error(decoder_status):
# Handle decode failure appropriately.
# Below is only an example.
raise Exception("Failed to decode. Status: {0} / {1}\n".format(MteBase.get_status_name(decoder_status),
MteBase.get_status_description(decoder_status)))
elif decoder_status != MteStatus.mte_status_success:
# This catches Decoder warnings, the decode process was successful
# But depending on the type of security needed these may be ignored
# Please see Developer Guide for more details.
print("Decode warning ({0}): {1}".format(
MteBase.get_status_name(status),
MteBase.get_status_description(status)),
file=sys.stderr)
# Decode string to a byte[].
(decoded_string_as_bytes, decoder_status) = mke_decoder.decode_b64(encoded_base64_string)
if MteBase.status_is_error(decoder_status):
# Handle decode failure appropriately.
# Below is only an example.
raise Exception("Failed to decode. Status: {0} / {1}\n".format(MteBase.get_status_name(decoder_status),
MteBase.get_status_description(decoder_status)))
elif decoder_status != MteStatus.mte_status_success:
# This catches Decoder warnings, the decode process was successful
# But depending on the type of security needed these may be ignored
# Please see Developer Guide for more details.
print("Decode warning ({0}): {1}".format(
MteBase.get_status_name(status),
MteBase.get_status_description(status)),
file=sys.stderr)
// initialize status
var decoderStatus mte.Status
// Below are 4 different examples of how to decode data
// ONLY ONE needs to be used!!!
// decode byte[] to base64 string
decodedBytesAsString, decodedStatus := mkeDecoder.DecodeStr(encodedBytes)
if mte.StatusIsError(decodedStatus) {
// Handle error correctly
// Below is an example
fmt.Fprintf(os.Stderr, "Decode error (%v): %v\n",
mte.GetStatusName(decodedStatus), mte.GetStatusDescription(decodedStatus))
return int(status)
} else if decodedStatus != mte.Status_mte_status_success {
// Handle warning correctly
// Below is an example
fmt.Fprintf(os.Stderr, "Decode warning (%v): %v\n",
mte.GetStatusName(decodedStatus), mte.GetStatusDescription(decodedStatus))
}
// decode string to base64 string
decodedStringAsString, decodedStatus := mkeDecoder.DecodeStrB64(encodedString)
if mte.StatusIsError(decodedStatus) {
// Handle error correctly
// Below is an example
fmt.Fprintf(os.Stderr, "Decode error (%v): %v\n",
mte.GetStatusName(decodedStatus), mte.GetStatusDescription(decodedStatus))
return int(status)
} else if decodedStatus != mte.Status_mte_status_success {
// Handle warning correctly
// Below is an example
fmt.Fprintf(os.Stderr, "Decode warning (%v): %v\n",
mte.GetStatusName(decodedStatus), mte.GetStatusDescription(decodedStatus))
}
// decode bytes to byte
decodedBytes, decodedStatus := mkeDecoder.Decode(encodedBytes)
if mte.StatusIsError(decodedStatus) {
// Handle error correctly
// Below is an example
fmt.Fprintf(os.Stderr, "Decode error (%v): %v\n",
mte.GetStatusName(decodedStatus), mte.GetStatusDescription(decodedStatus))
return int(status)
} else if decodedStatus != mte.Status_mte_status_success {
// Handle warning correctly
// Below is an example
fmt.Fprintf(os.Stderr, "Decode warning (%v): %v\n",
mte.GetStatusName(decodedStatus), mte.GetStatusDescription(decodedStatus))
}
// decode string to bytes
decodedBytes, decodedStatus := mkeDecoder.DecodeB64(encodedString)
if mte.StatusIsError(decodedStatus) {
// Handle error correctly
// Below is an example
fmt.Fprintf(os.Stderr, "Decode error (%v): %v\n",
mte.GetStatusName(decodedStatus), mte.GetStatusDescription(decodedStatus))
return int(status)
} else if decodedStatus != mte.Status_mte_status_success {
// Handle warning correctly
// Below is an example
fmt.Fprintf(os.Stderr, "Decode warning (%v): %v\n",
mte.GetStatusName(decodedStatus), mte.GetStatusDescription(decodedStatus))
}
<?php
// Decode String to String
$decoded = $mkeDecoder->decode($encoded["str"]);
// Check the status
if (constant($decoded["status"])!=mte_status_success){
// Handle an error here -- below is a sample
throw new Exception("Decoder decode error: "
.$mkeDecoder->getStatusName(constant($decoded["status"])).":"
.$mkeDecoder->getStatusDescription(constant($decoded["status"])));
}
?>
<?php
// Decode Base64 string to string
$decoded = $mkeDecoder->decodeB64($encoded["str"]);
// Check the status
if (constant($decoded["status"])!=mte_status_success){
// Handle an error here -- below is a sample
throw new Exception("Decoder encode error: "
.$mkeDecoder->getStatusName(constant($decoded["status"])).":"
.$mkeDecoder->getStatusDescription(constant($decoded["status"])));
}
?>
Decoder State
The decoder state can be saved and restored with either byte[] or a base64 string using the following methods. Below are several examples of how to use it, based on your data type you only need to use one of the following examples.
- C
- C++
- CSharp
- Java
- JavaScript
- Swift
- Python
- Go
- PHP
Save state.
/* There are different functions available to use depending on program needs.
* The versions with b64 in the function name involve base 64 conversion,
* suitable for protocols requiring a string representation.
* Otherwise the default will use raw bytes.
*/
/* Save the decoder state. */
/* Saved state. */
MTE_UINT8_T* d_saved = MTE_ALLOCA(mte_mke_dec_save_bytes(decoder));
status = mte_mke_dec_state_save(decoder, d_saved);
if (status != mte_status_success)
{
fputs("Decoder state save error.", stderr);
return mte_status_unsupported;
}
Restore state.
/* Restore the decoder state. */
status = mte_mke_dec_state_restore(decoder, d_saved);
if (status != mte_status_success)
{
fprintf(stderr, "Decoder state restore error (%s): %s\n",
mte_base_status_name(status),
mte_base_status_description(status));
return status;
}
Save state.
// There are different functions available to use depending on program needs.
// The versions with b64 in the function name involve base 64 conversion,
// suitable for protocols requiring a string representation.
// Otherwise the default will use raw bytes.
// Save the decoder state.
size_t dSavedBytes = 0;
const void* dsaved = decoder.saveState(dSavedBytes);
if (dsaved == NULL)
{
std::cerr << "Decoder state save error." << std::endl;
return mte_status_unsupported;
}
Restore state.
// Restore the decoder state.
status = decoder.restoreState(dsaved);
if (status != mte_status_success)
{
std::cerr << "Decoder state restore error." << std::endl;
return status;
}
// Save and restore Decoder state with bytes
// Get byte[] of decoder state
byte[] decoderByteState = mkeDecoder.SaveState();
// Restore Decoder with byte[] state
MteStatus decoderStatus = mkeDecoder.RestoreState(decoderByteState);
if(decoderStatus != MteStatus.mte_status_success)
{
// Mte cannot continue, handle restore failure appropriately
// Below is only an example
throw new Exception("Failed to restore Decoder state. Status: "
+ mkeDecoder.GetStatusName(decoderStatus)+ " / "
+ mkeDecoder.GetStatusDescription(decoderStatus));
}
// Save and restore Decoder state with string
// Get string of Decoder state
string decoderStrState = mkeDecoder.SaveStateB64();
// Restore Decoder with string state
MteStatus decoderStatus = mkeDecoder.RestoreStateB64(decoderStrState);
if(decoderStatus != MteStatus.mte_status_success)
{
// Mte cannot continue, handle restore failure appropriately
// Below is only an example
throw new Exception("Failed to restore Decoder state. Status: "
+ mkeDecoder.GetStatusName(decoderStrStatus)+ " / "
+ mkeDecoder.GetStatusDescription(decoderStrStatus));
}
// Save and restore Decoder state with bytes
// Get byte[] of Decoder state
byte[] decoderByteState = mkeDecoder.saveState();
// Restore Decoder with byte[] state
MteStatus decoderStatus = mkeDecoder.restoreState(decoderByteState);
if(decoderStatus != MteStatus.mte_status_success)
{
// Mte cannot continue, handle restore failure appropriately
// Below is only an example
throw new Exception("Failed to restore Decoder state. Status: "
+ MteBase.getStatusName(decoderStatus)+ " / "
+ MteBase.getStatusDescription(decoderStatus));
}
// Save and restore Decoder state with string
// Get string of Decoder state
string decoderStrState = mkeDecoder.saveStateB64();
// Restore Decoder with string state
MteStatus decoderStatus = mkeDecoder.restoreStateB64(decoderStrState);
if(decoderStatus != MteStatus.mte_status_success)
{
// Mte cannot continue, handle restore failure appropriately
// Below is only an example
throw new Exception("Failed to restore Decoder state. Status: "
+ MteBase.getStatusName(decoderStrStatus)+ " / "
+ MteBase.getStatusDescription(decoderStrStatus));
}
// Save and restore Decoder state with bytes
// Get Uint8Array of Decoder state
const state = mkeDecoder.saveState();
// Restore Decoder with Uint8Array state
const decoderStatus = mkeDecoder.restoreState(state);
if (decoderStatus !== MteStatus.mte_status_success) {
// MTE cannot continue so handle failure appropriately
// Below is an Example
const status = mteBase.getStatusName(decoderStatus);
const message = mteBase.getStatusDescription(decoderStatus);
throw new Error(`Error instantiating MKE Decoder.\n${status}: ${message}`);
}
// Save and restore Decoder state with bytes
// Get Uint8Array of Decoder state
const state = mkeDecoder.saveStateB64();
// Restore Decoder with Uint8Array state
const decoderStatus = mkeDecoder.restoreStateB64(state);
if (decoderStatus !== MteStatus.mte_status_success) {
// MTE cannot continue so handle failure appropriately
// Below is an Example
const status = mteBase.getStatusName(decoderStatus);
const message = mteBase.getStatusDescription(decoderStatus);
throw new Error(`Error instantiating MKE Decoder.\n${status}: ${message}`);
}
// There are different functions available to use depending on program needs.
// The versions with b64 in the function name involve base 64 conversion,
// suitable for protocols requiring a string representation.
// Otherwise the default will use raw bytes.
// Save the decoder state.
let dsaved = decoder.saveState()
if dsaved == nil {
print("Decoder state save error.")
return Int32(mte_status_unsupported.rawValue)
}
# Save and restore Decoder state with bytes.
decoder_byte_state = mke_decoder.save_state()
# Restore Decoder with byte[] state.
decoder_status = mke_decoder.restore_state(decoder_byte_state)
if decoder_status != MteStatus.mte_status_success:
# Mte cannot continue, handle restore failure appropriately.
# Below is only an example.
raise Exception("Failed to restore Decoder state. Status: {0} / {1}\n".format(MteBase.get_status_name(decoder_status),
MteBase.get_status_description(decoder_status)))
# Save and restore Decoder state with string.
# Get string of Decoder state.
decoder_str_state = mke_decoder.save_state_b64()
# Restore Decoder with string state.
decoder_status = mke_decoder.restore_state_b64(decoder_str_state)
if decoder_status != MteStatus.mte_status_success:
# Mte cannot continue, handle restore failure appropriately.
# Below is only an example.
raise Exception("Failed to restore Decoder state. Status: {0} / {1}\n".format(MteBase.get_status_name(decoder_status),
MteBase.get_status_description(decoder_status)))
// Save and restore Decoder state with bytes
// Get byte[] of Decoder state
decoderByteState := mkeDecoder.SaveState()
decoderStatus := mkeDecoder.RestoreState(decoderByteState);
if(decoderStatus != mte.Status_mte_status_success){
// Handle deocder restore state failure appropriately
// Below is only an example
fmt.Fprintf(os.Stderr, "Restore Decoder state error (%v): %v\n",
mte.GetStatusName(decoderStatus), mte.GetStatusDescription(decoderStatus))
return int(decoderStatus)
}
// Save and restore Decoder state with bytes
// Get byte[] of Decoder state
decoderStrState := mkeDecoder.SaveStateB64()
decoderStatus := mkeDecoder.RestoreStateB64(decoderStrState);
if(decoderStatus != mte.Status_mte_status_success){
// Handle Decoder restore state failure appropriately
// Below is only an example
fmt.Fprintf(os.Stderr, "Restore Decoder state error (%v): %v\n",
mte.GetStatusName(decoderStatus), mte.GetStatusDescription(decoderStatus))
return int(decoderStatus)
}
<?php
$decoderStrState = $mkeDecoder->saveState();
$restoreStatus = $mkeDecoder->restoreState($decoderStrState);
if (constant($restoreStatus)!=mte_status_success){
// Handle an error here -- below is a sample
echo "Decoder restore state error: "
.$mkeDecoder->getStatusName(constant($restoreStatus)).":"
.$mkeDecoder->getStatusDescription(constant($restoreStatus));
return $mkeDecoder->getStatusCode(constant($restoreStatus));
}
?>
<?php
$decoderB64State = $mkeDecoder->saveStateB64();
$restoreStatus = $mkeDecoder->restoreStateB64($decoderB64State);
if (constant($restoreStatus)!=mte_status_success){
// Handle an error here -- below is a sample
echo "Decoder restore base64 state error: "
.$mkeDecoder->getStatusName(constant($restoreStatus)).":"
.$mkeDecoder->getStatusDescription(constant($restoreStatus));
return $mkeDecoder->getStatusCode(constant($restoreStatus));
}
?>
Additional options for Decoder State
The Core MTE decoder state and the MTE MKE decoder state are interchangeable. This means, the decoder state can be restored to an MTE Core OR an MTE MKE. The MTE used should be created using the same options for this to work correctly. The security of the MTE Core can be used for a password then the MTE MKE can be used on larger data in the same application without having to create multiple instances of the MTE.
Uninstantiate Decoder
Uninstantiate decoder, this will zeroize the DRBG state and returns the status.
- C
- C++
- CSharp
- Java
- JavaScript
- Swift
- Python
- Go
- PHP
status = mte_mke_dec_uninstantiate(decoder);
if (status != mte_status_success)
{
fprintf(stderr, "Failed to uninstantiate decoder (%s): %s\n",
mte_base_status_name(status),
mte_base_status_description(status));
return status;
}
status = decoder.uninstantiate();
if (status != mte_status_success)
{
std::cerr << "Decoder uninstantiate error ("
<< MteBase::getStatusName(status)
<< "): "
<< MteBase::getStatusDescription(status)
<< std::endl;
return status;
}
// Uninstantiate the Decoder
MteStatus decoderStatus = mkeDecoder.Uninstantiate();
if(decoderStatus != MteStatus.mte_status_success)
{
// MTE was not uninstantiated as desired so handle failure appropriately
// Below is only an example
throw new Exception("Failed to uninstantiate Decoder. Status: "
+ mkeDecoder.GetStatusName(decoderStatus)+ " / "
+ mkeDecoder.GetStatusDescription(decoderStatus));
}
// Uninstantiate the Decoder
MteStatus decoderStatus = mkeDecoder.uninstantiate();
if(decoderStatus != MteStatus.mte_status_success)
{
// MTE was not uninstantiated as desired so handle failure appropriately
// Below is only an example
throw new Exception("Failed to uninstantiate Decoder. Status: "
+ MteBase.getStatusName(decoderStatus)+ " / "
+ MteBase.getStatusDescription(decoderStatus));
}
// Uninstantiate the MKE Decoder
const decoderStatus = mkeDecoder.uninstantiate();
if (decoderStatus !== MteStatus.mte_status_success) {
// MTE cannot continue so handle failure appropriately
// Below is an Example
const status = mteBase.getStatusName(decoderStatus);
const message = mteBase.getStatusDescription(decoderStatus);
throw new Error(`Error uninstantiating MKE Decoder.\n${status}: ${message}`);
}
// Free WASM memory
mkeDecoder.destroy();
// Uninstantiate the Decoder
let status: mte_status = decoder.uninstantiate()
if status != mte_status_success {
// MTE was not uninstantiated as desired so handle failure appropriately
print("Decoder Uninstantiate error: \(MteBase.getStatusName(status))." +
"Description: \(MteBase.getStatusDescription(status))"
}
# Uninstantiate the Decoder.
decoder_status = mke_decoder.uninstantiate()
if decoder_status != MteStatus.mte_status_success:
# MTE was not uninstantiated as desired so handle failure appropriately.
# Below is only an example.
raise Exception("Failed to uninstantiate Decoder. Status: {0} / {1}\n".format(MteBase.get_status_name(decoder_status),
MteBase.get_status_description(decoder_status)))
// Uninstantiate the Decoder
decoderStatus := mkeDecoder.Uninstantiate();
if(decoderStatus != mte.Status_mte_status_success){
// Handle Decoder uninstantiate failure appropriately
// Below is only an example
fmt.Fprintf(os.Stderr, "Decoder uninstantiate error (%v): %v\n",
mte.GetStatusName(decoderStatus), mte.GetStatusDescription(decoderStatus))
return int(decoderStatus)
}
<?php
// Uninstantiate the Decoder
$decoderStatus = $mkeDecoder->uninstantiate();
if (constant($decoderStatus) != mte_status_success) {
//----------------------------------------------------
// Handle Decoder uninstantiate failure appropriately
// Below is only an example
echo "Decoder uninstantiate error: "
.$mkeDecoder->getStatusName(constant($decoderStatus)).":"
.$mkeDecoder->getStatusDescription(constant($decoderStatus));
return $mkeDecoder->getStatusCode(constant($decoderStatus));
}
// Clear out $mkeDecoder variable
unset($mkeDecoder);
?>
MTE MKE Chunk Methods
If the data is large and must be split in order to be sent or is already being transferred via chunks the MTE MKE has a chunking method that can be used. The MTE MKE Chunking methods allow the user to break the output down into smaller more manageable pieces and encode or decode the data a chunk at a time.
MTE MKE Encode Chunking
Here is a short example of how to use the MKE Encode Chunking methods. For a full working sample please see the MKE Samples Page Here.
- C
- C++
- CSharp
- Java
- JavaScript
- Swift
- Python
- Go
- PHP
/* Status. */
mte_status status;
/* Licensing. */
const char* company;
const char* license;
/* Suppress unused args. */
(void)argc;
(void)argv;
/* Initialize MTE. */
if (!mte_init(NULL, NULL))
{
fputs("MTE init error.", stderr);
return -1;
}
/* Initialize MTE license. If a license code is not required (e.g., trial
mode), this can be skipped. This demo attempts to load the license info
from the environment if required. */
if (!mte_license_init("YOUR_COMPANY", "YOUR_LICENSE"))
{
company = getenv("MTE_COMPANY");
license = getenv("MTE_LICENSE");
if (company == NULL || license == NULL ||
!mte_license_init(company, license))
{
fprintf(stderr, "License init error (%s): %s\n",
mte_base_status_name(mte_status_license_error),
mte_base_status_description(mte_status_license_error));
return mte_status_license_error;
}
}
/* Retrieve block size of the cipher. If greater than 1, this demo may not
work as expected. */
size_t block_size = mte_base_ciphers_block_bytes(MTE_CIPHER_ENUM);
if (block_size > 1)
{
printf("The block size must be set to 1.");
return 1;
}
/* Get the input data. */
printf("Enter the data to encode> ");
fflush(stdout);
(void)!fgets(input, sizeof(input), stdin);
input[strlen(input) - 1] = '\0';
input_bytes = (MTE_SIZE_T)strlen(input);
/* Get the personalization string. */
printf("Enter the personalization> ");
fflush(stdout);
(void)!fgets(personal, sizeof(personal), stdin);
personal[strlen(personal) - 1] = '\0';
mte_drbg_inst_info i_info = { &ei_cb, NULL, &n_cb, NULL, personal, 0 };
i_info.ps_bytes = (MTE_SIZE_T)strlen(personal);
/* Create the encoder. */
MTE_HANDLE encoder;
mte_mke_enc_init_info e_info = MTE_MKE_ENC_INIT_INFO_INIT(
MTE_DRBG_ENUM, MTE_TOKBYTES, MTE_VERIFIERS_ENUM,
MTE_CIPHER_ENUM, MTE_HASH_ENUM, NULL, NULL, NULL, NULL, NULL, NULL);
mte_enc_args e_args = MTE_ENC_ARGS_INIT(NULL, 0, NULL, &t_cb, NULL);
encoder = MTE_ALLOCA(mte_mke_enc_state_bytes(&e_info));
status = mte_mke_enc_state_init(encoder, &e_info);
if (status != mte_status_success)
{
fprintf(stderr, "Encoder init error (%s): %s\n",
mte_base_status_name(status),
mte_base_status_description(status));
return status;
}
status = mte_mke_enc_instantiate(encoder, &i_info);
if (status != mte_status_success)
{
fprintf(stderr, "Encoder instantiate error (%s): %s\n",
mte_base_status_name(status),
mte_base_status_description(status));
return status;
}
/* This sample works with the MKE add-on that uses a cipher block size of 1. Any other
cipher block sizes are not guaranteed to work.
The encryption and decryption chunk sizes can be the same or different. */
const size_t encrypt_chunk_size = 10;
/* Create buffer to hold encrypt chunk size. */
char* encrypt_chunk_buf;
encrypt_chunk_buf = malloc(encrypt_chunk_size);
/* Get the chunk state size requirement. */
size_t enc_buff_bytes = mte_mke_enc_encrypt_state_bytes(encoder);
/* Create buffer to hold MTE encryption state. */
unsigned char* mke_encryption_state_buffer;
mke_encryption_state_buffer = malloc(enc_buff_bytes);
/* Start chunking session. */
status = mte_mke_enc_encrypt_start(encoder, mke_encryption_state_buffer);
if (status != mte_status_success)
{
fprintf(stderr, "Error starting encryption: (%s): %s\n",
mte_base_status_name(status),
mte_base_status_description(status));
return status;
}
/* Create buffer to hold the encoded result. */
char* encoded_input = malloc(1);
mte_enc_args encoding_args = MTE_ENC_ARGS_INIT(NULL, 0, NULL, &t_cb, NULL);
/* Loop through input one chunk at a time. */
size_t amount_encoded = 0;
while (amount_encoded < input_bytes)
{
/* Encrypt a chunk of the input to the encrypt chunk buffer. Use encrypt chunk size, or the size of the input, whichever is smaller. */
MTE_SET_ENC_IO(encoding_args, input + amount_encoded, min(encrypt_chunk_size, input_bytes - amount_encoded), encrypt_chunk_buf);
status = mte_mke_enc_encrypt_chunk(encoder, mke_encryption_state_buffer, &encoding_args);
if (status != mte_status_success)
{
fprintf(stderr, "Error encrypting chunk: Status: %s/%s\n",
mte_base_status_name(status),
mte_base_status_description(status));
return status;
}
/* Check if there were more than 0 bytes encoded. Zero bytes does not
mean there is an error, just that there is not anything to write for this pass. */
if (encoding_args.bytes > 0)
{
/* Reallocate the encoded input buffer to fit the size of how much has already been encrypted. */
encoded_input = realloc(encoded_input, amount_encoded + encoding_args.bytes);
/* Copy the encoded result to the buffer. */
memcpy(encoded_input + amount_encoded, encoding_args.encoded, encoding_args.bytes);
/* Add the size of the encoded amount to the total amount. */
amount_encoded = amount_encoded + encoding_args.bytes;
}
}
/* Finish the encryption with the encryption buffer.
If the original input is short enough, this finish call can be much larger than original input size. */
MTE_SET_ENC_IO(encoding_args, NULL, 0, NULL);
status = mte_mke_enc_encrypt_finish(encoder, mke_encryption_state_buffer, &encoding_args);
if (status != mte_status_success)
{
fprintf(stderr, "Error finishing encryption: (%s): %s\n",
mte_base_status_name(status),
mte_base_status_description(status));
return status;
}
/* This will include any bytes left over from the input, as well as data needed by the decryption engine. */
if (encoding_args.bytes > 0)
{
/* Reallocate the encoded input buffer to fit the size of how much has already been encrypted. */
encoded_input = realloc(encoded_input, amount_encoded + encoding_args.bytes);
/* Copy the encoded result to the buffer. */
memcpy(encoded_input + amount_encoded, encoding_args.encoded, encoding_args.bytes);
/* Add the size of the encoded amount to the total amount. */
amount_encoded = amount_encoded + encoding_args.bytes;
}
// Status.
mte_status status;
// Licensing.
const char* company;
const char* license;
/* Suppress unused args. */
(void)argc;
(void)argv;
// Initialize MTE license. If a license code is not required (e.g., trial
// mode), this can be skipped. This demo attempts to load the license info
// from the environment if required.
if (!MteBase::initLicense("YOUR_COMPANY", "YOUR_LICENSE"))
{
company = getenv("MTE_COMPANY");
license = getenv("MTE_LICENSE");
if (company == NULL || license == NULL ||
!MteBase::initLicense(company, license))
{
std::cerr << "License init error ("
<< MteBase::getStatusName(mte_status_license_error)
<< "): "
<< MteBase::getStatusDescription(mte_status_license_error)
<< std::endl;
return mte_status_license_error;
}
}
// Retrieve block size of the cipher. If greater than 1, this demo may not
// work as expected.
size_t blockSize = MteBase::getCiphersBlockBytes(MTE_CIPHER_ENUM);
if (blockSize > 1)
{
std::cout << "The block size must be set to 1." << std::endl;
return 1;
}
// Get the input data.
std::cout << "Enter the data to encode> ";
std::getline(std::cin, input);
inputBytes = input.length();
// Convert input to void pointer to pass in to encrypt chunk function.
void* inputVoidPointer = static_cast<char*>(malloc(inputBytes));
memcpy(inputVoidPointer, input.c_str(), inputBytes);
// Get the personalization string.
std::cout << "Enter the personalization> ";
std::getline(std::cin, personal);
// Create the callbacks to get entropy, nonce, and timestamp from stdin.
Cbs cbs;
// Create the encoder.
MteMkeEnc encoder;
encoder.setEntropyCallback(&cbs);
encoder.setNonceCallback(&cbs);
encoder.setTimestampCallback(&cbs);
status = encoder.instantiate(personal);
if (status != mte_status_success)
{
std::cerr << "Encoder instantiate error ("
<< MteBase::getStatusName(status)
<< "): "
<< MteBase::getStatusDescription(status)
<< std::endl;
return status;
}
// This sample works with the MKE add-on that uses a cipher block size of 1. Any other
// cipher block sizes are not guaranteed to work.
// The encryption and decryption chunk sizes can be the same or different.
const size_t encryptChunkSize = 10;
// Create buffer to hold the encoded result.
char* encodedInput = static_cast<char*>(malloc(1));
// Create buffer to hold encrypt chunk size.
char* encryptChunkBuf = static_cast<char*>(malloc(encryptChunkSize));
// Start chunking session.
status = encoder.startEncrypt();
if (status != mte_status_success)
{
std::cerr << "Error starting encryption: ("
<< MteBase::getStatusName(status)
<< "): "
<< MteBase::getStatusDescription(status)
<< std::endl;
return status;
}
// Loop through input one chunk at a time.
size_t amountEncoded = 0;
while (amountEncoded < inputBytes)
{
// Encrypt a chunk of the input to the encrypt chunk buffer. Use encrypt chunk size, or the size of the input, whichever is smaller.
// Note that the input will get overwritten with the encoded result.
size_t minAmount = std::min(encryptChunkSize, inputBytes - amountEncoded);
status = encoder.encryptChunk(static_cast<char*>(inputVoidPointer) + amountEncoded, minAmount);
if (status != mte_status_success)
{
std::cerr << "Error encrypting chunk: ("
<< MteBase::getStatusName(status)
<< "): "
<< MteBase::getStatusDescription(status)
<< std::endl;
return status;
}
// Reallocate the encoded input buffer to fit the size of what needs to be encoded.
encodedInput = static_cast<char*>(realloc(encodedInput, amountEncoded + minAmount));
// Copy the encoded result to the buffer. Note that earlier, this is the same as the original input.
memcpy(encodedInput + amountEncoded, static_cast<char*>(inputVoidPointer) + amountEncoded, minAmount);
// Add the size of the encoded amount to the total amount.
amountEncoded += minAmount;
}
// Finish the encryption with the encryption buffer.
// If the original input is short enough, this finish call can be much larger than original input size.
size_t finishBytes;
const void* finishBuffer = encoder.finishEncrypt(finishBytes, status);
if (status != mte_status_success)
{
std::cerr << "Error finishing encryption: ("
<< MteBase::getStatusName(status)
<< "): "
<< MteBase::getStatusDescription(status)
<< std::endl;
return status;
}
// This will include any bytes left over from the input, as well as data needed by the decryption engine.
if (finishBytes > 0)
{
// Reallocate the encoded input buffer to fit the size of what needs to be encoded.
encodedInput = static_cast<char*>(realloc(encodedInput, amountEncoded + finishBytes));
// Copy the encoded result to the buffer.
memcpy(encodedInput + amountEncoded, finishBuffer, finishBytes);
// Add the size of the encoded amount to the total amount.
amountEncoded += finishBytes;
}
//---------------------------------------
// Create MTE MKE Encoder as shown above
//---------------------------------------
// Initialize chunking session
MteStatus encoderStatus = mkeEncoder.StartEncrypt();
if(encoderStatus != MteStatus.mte_status_success)
{
// MTE was not successful so handle failure appropriately
// Below is only an example
throw new Exception("Failed to start encode chunk. Status: "
+ mkeEncoder.GetStatusName(encoderStatus)+ " / "
+ mkeEncoder.GetStatusDescription(encoderStatus));
}
//---------------------------------------------------------
// For each chunk of data one of two options are available
//---------------------------------------------------------
// When the byte[] buffer that is passed in is NOT the size of
// the amount of data inside of it use the full method
// encryptChunk(byte[] dataToBeEncoded, int offset, int sizeOfDataToBeEncoded)
//--------------------
// Option one
//--------------------
// byteData --> contains data to be Encoder
// 0 --> starting position
// byteData.Length --> length of the actual byte data
MteStatus chunkStatus = mkeEncoder.EncryptChunk(byteData, 0, byteData.Length);
if(chunkStatus != MteStatus.mte_status_success)
{
// Encode chunk unsuccessful and cannot continue, handle failure appropriately
// Below is only an example
throw new Exception("Failed to encode chunk. Status: "
+ mkeEncoder.GetStatusName(chunkStatus)+ " / "
+ mkeEncoder.GetStatusDescription(chunkStatus));
}
//--------------------
// Option two
//--------------------
// When the byte[] is the exact size of the data inside this may be called
MteStatus chunkStatus = mkeEncoder.EncryptChunk(byteData);
if(chunkStatus != MteStatus.mte_status_success)
{
// Encode chunk unsuccessful and cannot continue, handle failure appropriately
// Below is only an example
throw new Exception("Failed to encode chunk. Status: "
+ mkeEncoder.GetStatusName(chunkStatus)+ " / "
+ mkeEncoder.GetStatusDescription(chunkStatus));
}
// Once all data has been processed call finish method
// This method will ALWAYS have additional data that will need to be included
byte[] finalEncodedChunk = mkeEncoder.FinishEncrypt(out MteStatus finishStatus);
if(finishStatus != MteStatus.mte_status_success)
{
// Encode finish unsuccessful and cannot continue, handle failure appropriately
// Below is only an example
throw new Exception("Failed to finish encode chunk. Status: "
+ mkeEncoder.GetStatusName(finishStatus)+ " / "
+ mkeEncoder.GetStatusDescription(finishStatus));
}
//---------------------------------------
// Create MTE MKE Encoder as shown above
//---------------------------------------
// Initialize chunking session
MteStatus encoderStatus = mkeEncoder.startEncrypt();
if(encoderStatus != MteStatus.mte_status_success)
{
// MTE was not successful so handle failure appropriately
// Below is only an example
throw new Exception("Failed to start encode chunk. Status: "
+ MteBase.getStatusName(encoderStatus)+ " / "
+ MteBase.getStatusDescription(encoderStatus));
}
//---------------------------------------------------------
// For each chunk of data one of two options are available
//---------------------------------------------------------
// When the byte[] that is passed in is NOT the size of
// the amount of data inside of it use the full method
// encryptChunk(byte[] dataToBeEncoded, int offset, int sizeOfDataToBeEncoded)
//--------------------
// Options one
//--------------------
// byteData --> contains data to be Encoder
// 0 --> starting position
// byteData.Length --> length of the actual byte data
MteStatus chunkStatus = mkeEncoder.encryptChunk(byteData, 0, byteDataSize);
if(chunkStatus != MteStatus.mte_status_success)
{
// Encode chunk unsuccessful and cannot continue, handle failure appropriately
// Below is only an example
throw new Exception("Failed to encode chunk. Status: "
+ MteBase.getStatusName(chunkStatus)+ " / "
+ MteBase.getStatusDescription(chunkStatus));
}
//--------------------
// Options two
//--------------------
// When the byte[] is the exact size of the data inside this may be called
MteStatus chunkStatus = mkeEncoder.encryptChunk(byteData);
if(chunkStatus != MteStatus.mte_status_success)
{
// Encode chunk unsuccessful and cannot continue, handle failure appropriately
// Below is only an example
throw new Exception("Failed to encode chunk. Status: "
+ MteBase.getStatusName(chunkStatus)+ " / "
+ MteBase.getStatusDescription(chunkStatus));
}
// Once all data has been processed call finish method
// This method will ALWAYS have additional data that will need to be included
MteBase.ArrStatus finalEncodedChunk = mkeEncoder.finishEncrypt();
if(finalEncodedChunk.status != MteStatus.mte_status_success)
{
// Encode finish unsuccessful and cannot continue, handle failure appropriately
// Below is only an example
throw new Exception("Failed to finish encode chunk. Status: "
+ MteBase.getStatusName(finalEncodedChunk.status)+ " / "
+ MteBase.getStatusDescription(finalEncodedChunk.status));
}
//---------------------------------------
// Create MTE MKE Encoder as shown above
//---------------------------------------
// Initialize chunking session
const encoderStatus = mkeEncoder.startEncrypt();
if (encoderStatus !== MteStatus.mte_status_success) {
// MTE start chunking was not successful, handle failure appropriately
// Below is only an example
const status = mteBase.getStatusName(encoderStatus);
const message = mteBase.getStatusDescription(encoderStatus);
throw new Error(
`Failed to start encode chunk. Status: \n${status}: ${message}`,
);
}
// byteData --> contains data to be Encoded
const chunkStatus = mkeEncoder.encryptChunk(byteData);
if (chunkStatus !== MteStatus.mte_status_success) {
// Encode chunk unsuccessful and cannot continue, handle failure appropriately
// Below is only an example
const status = mteBase.getStatusName(chunkStatus);
const message = mteBase.getStatusDescription(chunkStatus);
throw new Error(`Failed to encode chunk. Status: \n${status}: ${message}`);
}
// Once all data has been processed call finish method
// This method will ALWAYS have additional data that will need to be included
const finalEncodedChunk = mkeEncoder.finishEncrypt();
if (finalEncodedChunk.status !== MteStatus.mte_status_success) {
// Encode finish unsuccessful and cannot continue, handle failure appropriately
// Below is only an example
const status = mteBase.getStatusName(finalEncodedChunk.status);
const message = mteBase.getStatusDescription(finalEncodedChunk.status);
throw new Error(
`Failed to finish encode chunk. Status: \n${status}: ${message}`,
);
}
// Status.
var status: mte_status
// Initialize MTE license. If a license code is not required (e.g., trial
// mode), this can be skipped.
if !MteBase.initLicense("LicenseCompanyName", "LicenseKey") {
let company = ProcessInfo.processInfo.environment["LicenseCompanyName"]
let license = ProcessInfo.processInfo.environment["LicenseKey"];
if company == nil || license == nil ||
!MteBase.initLicense(company!, license!) {
status = mte_status_license_error
print("License init error (\(MteBase.getStatusName(status))): " +
MteBase.getStatusDescription(status))
return Int32(status.rawValue)
}
}
// Retrieve block size of the cipher. If greater than 1, this demo may not
// work as expected.
let blockSize = MteBase.getCiphersBlockBytes(MteBase.getDefaultCipher())
if (blockSize > 1)
{
print("The chunk size must be set to 1.")
return 1
}
// Get the input data.
print("Enter the data to encode> ")
let input = readLine(strippingNewline: true) ?? ""
let inputBytes = input.count
// Create array of original input that will get encrypted.
var inputArray: [UInt8] = Array(input.utf8)
// Get the personalization string.
print("Enter the personalization>")
let personal = readLine(strippingNewline: true) ?? ""
// Create the callbacks to get entropy, nonce, and timestamp from stdin.
let cbs = Cbs()
// Create the encoder.
let encoder = try! MteMkeEnc()
encoder.setEntropyCallback(cbs)
encoder.setNonceCallback(cbs)
encoder.setTimestampCallback(cbs)
status = encoder.instantiate(personal)
if status != mte_status_success {
print("Encoder instantiate error (\(MteBase.getStatusName(status))): " +
MteBase.getStatusDescription(status))
return Int32(status.rawValue)
}
// The encryption and decryption chunk sizes can be the same or different.
let encryptChunkSize: size_t = 10
// Start chunking session.
status = encoder.startEncrypt()
if status != mte_status_success {
print("Error starting encryption (\(MteBase.getStatusName(status))): " +
MteBase.getStatusDescription(status))
return Int32(status.rawValue)
}
// Loop through input one chunk at a time.
var amountEncoded = 0
while (amountEncoded < inputBytes) {
// Encrypt a chunk of the input to the encrypt chunk buffer. Use encrypt chunk size, or the size of the input, whichever is smaller.
// Note that the input will get overwritten with the encoded result.
let minAmount = min(encryptChunkSize, inputBytes - amountEncoded)
status = encoder.encryptChunk(&inputArray, amountEncoded, minAmount)
if status != mte_status_success {
print("Error encrypting chunk (\(MteBase.getStatusName(status))): " +
MteBase.getStatusDescription(status))
return Int32(status.rawValue)
}
// Add the size of the encoded amount to the total amount.
amountEncoded += minAmount
}
// Finish the encryption.
// If the original input is short enough, this finish call can be much larger than original input size.
// Append the result to the input array.
let finishBuffer = encoder.finishEncrypt()
status = finishBuffer.status
if status != mte_status_success {
print("Error finishing encryption (\(MteBase.getStatusName(status))): " +
MteBase.getStatusDescription(status))
return Int32(status.rawValue)
}
// This will include any bytes left over from the input, as well as data needed by the decryption engine.
// Append the encoded finish results to the input array.
inputArray.append(contentsOf: finishBuffer.encoded)
amountEncoded += finishBuffer.encoded.count
#---------------------------------------
# Create MTE MKE Encoder as shown above
#---------------------------------------
# Initialize the chunking session
encoder_status = mke_encoder.start_encrypt()
if encoder_status != MteStatus.mte_status_success:
# MTE was not successful so handle failure appropriately.
# Below is only an example.
raise Exception("Failed to start encode chunk. Status: {0} / {1}\n".format(MteBase.get_status_name(encoder_status),
MteBase.get_status_description(encoder_status)))
#------------------------------------------------------
# Pass each chunk of data into the encrypt_chunk method.
# The data is encoded in place and the encoded data
# will replace the data put in the method
# IMPORTANT - The data length must be a multiple of the chosen ciphers block size.
chunk_status = mke_encoder.encrypt_chunk(byte_data)
if chunk_status != MteStatus.mte_status_success:
# Encode chunk unsuccessful and cannot continue, handle failure appropriately.
# Below is only an example.
raise Exception("Failed to encode chunk. Status: {0} / {1}\n".format(MteBase.get_status_name(chunk_status),
MteBase.get_status_description(chunk_status)))
# Once all data has been processed call finish method.
# This method will ALWAYS have additional data that will need to be included.
final_encoded_chunk,finish_status = mke_encoder.finish_encrypt()
if finish_status != MteStatus.mte_status_success:
# Encode finish unsuccessful and cannot continue, handle failure appropriately.
# Below is only an example.
raise Exception("Failed to finish encode chunk. Status: {0} / {1}\n".format(MteBase.get_status_name(finish_status),
MteBase.get_status_description(finish_status)))
//---------------------------------------
// Create MTE MKE Encoder as shown above
//---------------------------------------
// Initialize chunking session
encoderstatus := mkeEncoder.StartEncrypt()
if encoderstatus != mte.Status_mte_status_success {
// Handle error appropriately
// Example below
fmt.Fprintf(os.Stderr, "MTE Encoder StartEncrypt error (%v): %v\n",
mte.GetStatusName(encoderstatus), mte.GetStatusDescription(encoderstatus))
retcode = int(encoderstatus)
return
}
//------------------------------------------------------
// pass each chunk of data into the EncryptChunk method
// the data is encoded in place and the encoded data
// will replace the data put in the method
encoderStatus := mkeEncoder.EncryptChunk(byteData);
if encoderstatus != mte.Status_mte_status_success {
// Handle error appropriately
// Example below
fmt.Fprintf(os.Stderr, "MTE Encoder chunk error (%v): %v\n",
mte.GetStatusName(encoderstatus), mte.GetStatusDescription(encoderstatus))
retcode = int(encoderstatus)
return
}
// Once all data has been processed call finish method
// This method will ALWAYS have additional data that will need to be included
finalEncodedChunk, encodeStatus := encoder.FinishEncrypt()
if encodeStatus != mte.Status_mte_status_success {
// Handle error appropriately
// Example below
fmt.Fprintf(os.Stderr, "Encode finish error (%v): %v\n",
mte.GetStatusName(encodeStatus), mte.GetStatusDescription(encodeStatus))
break
}
<?php
//---------------------------------------
// Create MTE MKE Encoder as shown above
//---------------------------------------
// Initialize chunking session
$encoderStatus = $mkeEncoder->startEncrypt();
if(constant($encoderStatus) != mte_status_success)
{
// MTE was not successful so handle failure appropriately
// Below is only an example
throw new Exception("Failed to start encode chunk. Status: "
.$mkeEncoder->getStatusName(constant($encoderStatus))+ " / "
.$mkeEncoder->getStatusDescription(constant($encoderStatus));
}
//---------------------------------------------------------
// For each chunk of data process using encryptChunk
//---------------------------------------------------------
?>
<?php
// Process the chunk of data
$chunkStatus = $mkeEncoder->encryptChunk($data);
if(constant($chunkStatus["status"]) != mte_status_success)
{
// Encode chunk unsuccessful and cannot continue, handle failure appropriately
// Below is only an example
throw new Exception("Failed to encode chunk. Status: "
.$mkeEncoder->getStatusName(constant($chunkStatus["status"]))+ " / "
.$mkeEncoder->getStatusDescription(constant($chunkStatus["status"])));
}
$encodedString .= $chunkStatus["str"];
?>
<?php
// Once all data has been processed call finish method
// This method will ALWAYS have additional data that will need to be included
$finalEncodedChunk = $mkeEncoder->finishEncrypt();
if(constant($finalEncodedChunk["status"]) != mte_status_success)
{
// Encode finish unsuccessful and cannot continue, handle failure appropriately
// Below is only an example
throw new Exception("Failed to finish encode chunk. Status: "
.$mkeEncoder->getStatusName(constant($finalEncodedChunk["status"]))+ " / "
.$mkeEncoder->getStatusDescription(constant($finalEncodedChunk["status"])));
}
if(strlen($finalEncodedChunk["str"]) > 0){
$encodedString .= $finalEncodedChunk["str"];
}
?>
MTE MKE Decode Chunking
The decoding is slightly different than the encoding. Because each decoded chunk may not be the same size as the encoded chunk, the amount is returned instead of left in the same variable. Here are short examples of how to use the MKE Decode Chunking methods. For a full working sample please see the MKE Samples Page Here.
- C
- C++
- CSharp
- Java
- JavaScript
- Swift
- Python
- Go
- PHP
/* Create the decoder. */
MTE_HANDLE decoder;
mte_mke_dec_init_info d_info = MTE_MKE_DEC_INIT_INFO_INIT(
MTE_DRBG_ENUM, MTE_TOKBYTES, MTE_VERIFIERS_ENUM,
MTE_CIPHER_ENUM, MTE_HASH_ENUM, 1, 0, NULL, NULL, NULL, NULL, NULL, NULL);
mte_dec_args d_args = MTE_DEC_ARGS_INIT(NULL, 0, NULL, &t_cb, NULL);
decoder = MTE_ALLOCA(mte_mke_dec_state_bytes(&d_info));
status = mte_mke_dec_state_init(decoder, &d_info);
if (status != mte_status_success)
{
fprintf(stderr, "Decoder init error (%s): %s\n",
mte_base_status_name(status),
mte_base_status_description(status));
return status;
}
status = mte_mke_dec_instantiate(decoder, &i_info);
if (status != mte_status_success)
{
fprintf(stderr, "Decoder instantiate error (%s): %s\n",
mte_base_status_name(status),
mte_base_status_description(status));
return status;
}
/* This sample works with the MKE add-on that uses a cipher block size of 1. Any other
cipher block sizes are not guaranteed to work.
The encryption and decryption chunk sizes can be the same or different.
Note that the size of the encrypted output may be very large compared
to the original input. */
const size_t decrypt_chunk_size = 5;
/* Get the chunk state size requirement. */
size_t dec_buff_bytes = mte_mke_dec_decrypt_state_bytes(decoder);
/* Create buffer to hold MTE decryption state. */
unsigned char* mke_decryption_state_buffer;
mke_decryption_state_buffer = malloc(dec_buff_bytes);
/* Start chunking session. */
status = mte_mke_dec_decrypt_start(decoder, mke_decryption_state_buffer);
if (status != mte_status_success)
{
fprintf(stderr, "Error starting decryption: (%s): %s\n",
mte_base_status_name(status),
mte_base_status_description(status));
return status;
}
/* Create buffer to hold decoded data, to be the size of the decrypt chunk
plus the block size. */
char* decoded_data_buf;
decoded_data_buf = malloc(decrypt_chunk_size + block_size);
mte_dec_args decoding_args = MTE_DEC_ARGS_INIT(NULL, 0, NULL, &t_cb, NULL);
/* Create buffer to hold the decoded result. */
char* decoded_input = malloc(1);
/* For this demo, the buffer that holds the encoded input will be used directly to decrypt by chunk. */
size_t amount_decoded = 0;
size_t amount_processed = 0;
while (amount_processed < amount_encoded)
{
/* Decrypt a chunk of the encoded input to the decrypt chunk buffer.
Use decrypt chunk size, or the size of what is left to process,
whichever is smaller. */
MTE_SET_DEC_IO(decoding_args, encoded_input + amount_processed, min(decrypt_chunk_size, amount_encoded - amount_processed), decoded_data_buf);
status = mte_mke_dec_decrypt_chunk(decoder, mke_decryption_state_buffer, &decoding_args);
if (status != mte_status_success)
{
fprintf(stderr, "Error decrypting chunk: Status: %s/%s\n",
mte_base_status_name(status),
mte_base_status_description(status));
return status;
}
/* The amount processed will always increment by the decrypt chunk size,
or how much has been decrypted, whichever is smaller. */
amount_processed += min(decrypt_chunk_size, amount_encoded - amount_decoded);
/* Check if there were more than 0 bytes decoded. Zero bytes does not
mean there is an error, just that there is not anything to write for this pass. */
if (decoding_args.bytes > 0)
{
/* Reallocate the decoded input buffer to fit the size of how much has already been decrypted. */
decoded_input = realloc(decoded_input, amount_decoded + decoding_args.bytes);
/* Copy the decoded result to the buffer. */
memcpy(decoded_input + amount_decoded, decoding_args.decoded, decoding_args.bytes);
/* Add the size of the decoded amount to the total amount. */
amount_decoded = amount_decoded + decoding_args.bytes;
}
}
/* Finish the decryption with the decryption buffer. */
MTE_SET_DEC_IO(decoding_args, NULL, 0, NULL);
status = mte_mke_dec_decrypt_finish(decoder, mke_decryption_state_buffer, &decoding_args);
if (mte_base_status_is_error(status))
{
fprintf(stderr, "Error finishing decryption: (%s): %s\n",
mte_base_status_name(status),
mte_base_status_description(status));
return status;
}
/* This will include any remaining bytes left over after all chunks have been processed. */
if (decoding_args.bytes > 0)
{
/* Reallocate the decoded input buffer to fit the size of how much has already been decrypted. */
decoded_input = realloc(decoded_input, amount_decoded + decoding_args.bytes);
/* Copy the decoded result to the buffer. */
memcpy(decoded_input + amount_decoded, decoding_args.decoded, decoding_args.bytes);
}
/* Compare the original input with the decoded result. */
if (memcmp(input, decoded_input, input_bytes) == 0)
{
exitCode = 0;
puts("The original data and decoded data match.");
}
else
{
exitCode = -1;
puts("The original data and decoded data DO NOT match.");
}
/* Free the buffers. */
if (encrypt_chunk_buf != NULL)
{
free(encrypt_chunk_buf);
}
if (mke_encryption_state_buffer != NULL)
{
free(mke_encryption_state_buffer);
}
if (encoded_input != NULL)
{
free(encoded_input);
}
if (mke_decryption_state_buffer != NULL)
{
free(mke_decryption_state_buffer);
}
if (decoded_data_buf != NULL)
{
free(decoded_data_buf);
}
if (decoded_input != NULL)
{
free(decoded_input);
}
/* Uninstantiate the encoder and decoder. */
mte_mke_enc_uninstantiate(encoder);
mte_mke_dec_uninstantiate(decoder);
// Create the decoder.
MteMkeDec decoder;
decoder.setEntropyCallback(&cbs);
decoder.setNonceCallback(&cbs);
decoder.setTimestampCallback(&cbs);
status = decoder.instantiate(personal);
if (status != mte_status_success)
{
std::cerr << "Decoder instantiate error ("
<< MteBase::getStatusName(status)
<< "): "
<< MteBase::getStatusDescription(status)
<< std::endl;
return status;
}
// This sample works with the MKE add-on that uses a cipher block size of 1. Any other
// cipher block sizes are not guaranteed to work.
// The encryption and decryption chunk sizes can be the same or different.
// Note that the size of the encrypted output may be very large compared
// to the original input.
const size_t decryptChunkSize = 5;
// Start chunking session.
status = decoder.startDecrypt();
if (status != mte_status_success)
{
std::cerr << "Error starting decryption: ("
<< MteBase::getStatusName(status)
<< "): "
<< MteBase::getStatusDescription(status)
<< std::endl;
return status;
}
// Create buffer to hold decoded data, to be the size of the decrypt chunk
// plus the block size.
char* decodedDataBuf = static_cast<char*>(malloc(decryptChunkSize + blockSize));
// Create buffer to hold the decoded result.
char* decodedInput = static_cast<char*>(malloc(1));
// For this demo, the buffer that holds the encoded input will be used directly to decrypt by chunk.
size_t amountDecoded = 0;
size_t amountProcessed = 0;
while (amountProcessed < amountEncoded)
{
// Decrypt a chunk of the encoded input to the decrypt chunk buffer.
// Use decrypt chunk size, or the size of what is left to process,
// whichever is smaller.
size_t minAmount = std::min(decryptChunkSize, amountEncoded - amountProcessed);
size_t decryptedBytes = 0;
const void* decryptedChunk = decoder.decryptChunk(encodedInput + amountProcessed, minAmount, decryptedBytes);
// The amount processed will always increment by the decrypt chunk size,
// or how much has been decrypted, whichever is smaller.
amountProcessed += std::min(decryptChunkSize, amountEncoded - amountDecoded);
// Check if there were more than 0 bytes decoded. Zero bytes does not
// mean there is an error, just that there is not anything to write for this pass.
if (decryptedBytes > 0)
{
// Reallocate the decoded input buffer to fit the size of how much has already been decrypted.
decodedInput = static_cast<char*>(realloc(decodedInput, amountDecoded + decryptedBytes));
// Copy the decoded result to the buffer.
memcpy(decodedInput + amountDecoded, decryptedChunk, decryptedBytes);
// Add the size of the decoded amount to the total amount.
amountDecoded += decryptedBytes;
}
}
// Finish the decryption with the decryption buffer.
size_t decryptedBytes = 0;
const void* decryptedChunk = decoder.finishDecrypt(decryptedBytes, status);
// If there are any bytes decrypted, write that to the decoded file.
if (decryptedBytes > 0)
{
// Reallocate the decoded input buffer to fit the size of how much has already been decrypted.
decodedInput = static_cast<char*>(realloc(decodedInput, amountDecoded + decryptedBytes));
// Copy the decoded result to the buffer.
memcpy(decodedInput + amountDecoded, decryptedChunk, decryptedBytes);
// Add the size of the decoded amount to the total amount.
amountDecoded += decryptedBytes;
}
// Compare the original input with the decoded result.
if (memcmp(input.c_str(), decodedInput, inputBytes) == 0)
{
exitCode = 0;
std::cout << "The original data and decoded data match." << std::endl;
}
else
{
exitCode = -1;
std::cerr << "The original data and decoded data DO NOT match." << std::endl;
}
// Free the buffers.
if (inputVoidPointer != NULL)
{
free(inputVoidPointer);
}
if (encodedInput != NULL)
{
free(encodedInput);
}
if (encryptChunkBuf != NULL)
{
free(encryptChunkBuf);
}
if (decodedDataBuf != NULL)
{
free(decodedDataBuf);
}
if (decodedInput != NULL)
{
free(decodedInput);
}
// Uninstantiate the encoder and decoder.
status = encoder.uninstantiate();
if (status != mte_status_success)
{
std::cerr << "Error attempting to uninstantiate encoder: ("
<< MteBase::getStatusName(status)
<< "): "
<< MteBase::getStatusDescription(status)
<< std::endl;
return status;
}
status = decoder.uninstantiate();
if (status != mte_status_success)
{
std::cerr << "Error attempting to uninstantiate decoder: ("
<< MteBase::getStatusName(status)
<< "): "
<< MteBase::getStatusDescription(status)
<< std::endl;
return status;
}
//---------------------------------------
// Create MTE MKE Decoder as shown above
//---------------------------------------
// Initialize chunking session
MteStatus decoderStatus = mkeDecoder.StartDecrypt();
if(decoderStatus != MteStatus.mte_status_success)
{
// MTE start chunking was not successful, handle failure appropriately
// Below is only an example
throw new Exception("Failed to start decode chunk. Status: "
+ mkeDecoder.GetStatusName(decoderStatus)+ " / "
+ mkeDecoder.GetStatusDescription(decoderStatus));
}
//------------------------------------------------------------------
// For each chunk of data to decode there are two options available
//------------------------------------------------------------------
// When the byte[] that is passed in is NOT the size of
// the amount of data inside of it use the full method
// DecryptChunk(byte[] dataToBeDecoded,
// int offset,
// int sizeOfDataToBeDecoded,
// byte[] returnedDecodedData,
// int offset)
//--------------------------------------------------------------------
// Option One
// Get what the decoded data size max will be to allocate byte[] for return data
var cipherBlocks = mkeDecoder.GetCiphersBlockBytes(mkeDecoder.GetCipher());
int buffBytes = bytesRead - cipherBlocks;
byte[] decodedData = new byte[buffBytes];
// Decode chunk, if int returned is -1 there was an error
int decryptError = mkeDecoder.DecryptChunk(encodedBytes, 0, encodedBytesSize, decodedData, 0);
if (decryptError < 0)
{
// Decoding chunk unsuccessful and cannot continue, handle failure appropriately
// Below is only an example
throw new ApplicationException("Error decoding data.");
}
//----------------------------------------------------------------------
// Option Two
// When encodedBytes byte[] same size as data inside
byte[] decodedData = mkeDecoder.DecryptChunk(encodedBytes);
// Finish the chunking session, this may or may not have data returned
// If no data is returned "finishDecrypt" will be null
byte[] finalDecodedChunk = mkeDecoder.FinishDecrypt(out MteStatus finishStatus);
if(finishStatus != MteStatus.mte_status_success)
{
// Decode chunk unsuccessful and cannot continue, handle failure appropriately
// Below is only an example
throw new Exception("Failed to finish decode chunk. Status: "
+ mkeDecoder.GetStatusName(finishStatus)+ " / "
+ mkeDecoder.GetStatusDescription(finishStatus));
}
//---------------------------------------
// Create MTE MKE Decoder as shown above
//---------------------------------------
// Initialize chunking session
MteStatus decoderStatus = mkeDecoder.startDecrypt();
if(decoderStatus != MteStatus.mte_status_success)
{
// MTE start chunking was not successful, handle failure appropriately
// Below is only an example
throw new Exception("Failed to start decode chunk. Status: "
+ MteBase.getStatusName(decoderStatus)+ " / "
+ MteBase.getStatusDescription(decoderStatus));
}
//------------------------------------------------------------------
// For each chunk of data to decode there are two options available
//------------------------------------------------------------------
// When the byte[] that is passed in is NOT the size of
// the amount of data inside of it use the full method
// decryptChunk(byte[] dataToBeDecoded,
// int offset,
// int sizeOfDataToBeDecoded,
// byte[] returnedDecodedData,
// int offset)
//--------------------------------------------------------------------
// Option One
// find out the size of decoded data
int cipherBlock = mkeDecoder.getCiphersBlockBytes(mkeDecoder.getCipher());
int chunkSize = sizeOfEncodedBytes - cipherBlock;
byte[] decodedChunk = new byte[chunkSize];
// Get what the decoded data size max will be to allocate byte[] for return data
int decodedWorked = mkeDecoder.decryptChunk(encodedBytes, 0, encodedByteSize, decodedChunk, 0);
if(decodedWorked < 0) {
// Decoding chunk unsuccessful and cannot continue, handle failure appropriately
// Below is only an example
throw new IllegalArgumentException("decrypt chunk error.");
}
//----------------------------------------------------------------------
// Option Two
// When encodedBytes byte[] same size as data inside
byte[] decodedData = mkeDecoder.decryptChunk(encodedBytes);
// Finish the chunking session, this may or may not have data returned
// If no data is returned "finishDecrypt" will be null
MteBase.ArrStatus finalEncodedChunk = mkeDecoder.finishDecrypt();
if(finalEncodedChunk.status != MteStatus.mte_status_success)
{
// Decode chunk unsuccessful and cannot continue, handle failure appropriately
// Below is only an example
throw new Exception("Failed to finish decode chunk. Status: "
+ MteBase.getStatusName(finalEncodedChunk.status)+ " / "
+ MteBase.getStatusDescription(finalEncodedChunk.status));
}
//---------------------------------------
// Create MTE MKE Decoder as shown above
//---------------------------------------
// Initialize chunking session
const decoderStatus = mkeDecoder.startDecrypt();
if (decoderStatus !== MteStatus.mte_status_success) {
// MTE start chunking was not successful, handle failure appropriately
// Below is only an example
const status = mteBase.getStatusName(decoderStatus);
const message = mteBase.getStatusDescription(decoderStatus);
throw new Error(
`Failed to start decode chunk. Status: \n${status}: ${message}`,
);
}
// Decode chunk, if returned as null, there was an error
const decryptChunkResult = mkeDecoder.decryptChunk(encodedBytes);
if (!decryptChunkResult) {
// Decoding chunk unsuccessful and cannot continue, handle failure appropriately
// Below is only an example
throw new Error("Error decoding data.");
}
// Create the decoder.
let decoder = try! MteMkeDec()
decoder.setEntropyCallback(cbs)
decoder.setNonceCallback(cbs)
decoder.setTimestampCallback(cbs)
status = decoder.instantiate(personal)
if status != mte_status_success {
print("Decoder instantiate error (\(MteBase.getStatusName(status))): " +
MteBase.getStatusDescription(status))
return Int32(status.rawValue)
}
// The encryption and decryption chunk sizes can be the same or different.
// Note that the size of the encrypted output may be very large compared
// to the original input.
let decryptChunkSize: size_t = 5
// Start chunking session.
status = decoder.startDecrypt()
if status != mte_status_success {
print("Error starting decryption (\(MteBase.getStatusName(status))): " +
MteBase.getStatusDescription(status))
return Int32(status.rawValue)
}
var decodedArray: [UInt8] = [UInt8](repeating: 0, count: 0)
var amountDecoded = 0
var amountProcessed = 0
while (amountProcessed < amountEncoded) {
// Decrypt a chunk of the encoded input to the decrypt chunk buffer.
// Use decrypt chunk size, or the size of what is left to process,
// whichever is smaller.
let minAmount = min(decryptChunkSize, amountEncoded - amountProcessed)
let decryptChunkBuf = [UInt8](inputArray[amountProcessed..<amountProcessed + minAmount])
let decryptedResult = decoder.decryptChunk(decryptChunkBuf)
if (decryptedResult.status != mte_status_success) {
print("Error decrypting chunk (\(MteBase.getStatusName(status))): " +
MteBase.getStatusDescription(status))
return Int32(status.rawValue)
}
// The amount processed will always increment by the decrypt chunk size,
// or how much has been decrypted, whichever is smaller.
amountProcessed += min(decryptChunkSize, amountEncoded - amountDecoded)
// Check if there were more than 0 bytes decoded. Zero bytes does not
// mean there is an error, just that there is not anything to write for this pass.
if (decryptedResult.data.count > 0) {
// Append the decoded result to the decoded array.
decodedArray.append(contentsOf: decryptedResult.data)
// Add the size of the decoded amount to the total amount.
amountDecoded += decryptedResult.data.count
}
}
// Finish the decryption with the decryption buffer.
let decryptedResult = decoder.finishDecrypt()
if (MteBase.statusIsError(decryptedResult.status)) {
print("Error finishing decryption (\(MteBase.getStatusName(status))): " +
MteBase.getStatusDescription(status))
return Int32(status.rawValue)
}
// This will include any remaining bytes left over after all chunks have been processed.
if (decryptedResult.data.count > 0) {
// Append the decoded result to the decoded array.
decodedArray.append(contentsOf: decryptedResult.data)
}
// Compare the original input with the decoded result.
let decodedString = String(bytes: decodedArray, encoding: .utf8)
if (input == decodedString) {
print("The original data and decoded data match.")
} else {
print("The original data and decoded data DO NOT match.")
}
// Uninstantiate the encoder and decoder.
_ = encoder.uninstantiate()
_ = decoder.uninstantiate()
#---------------------------------------
# Create MTE MKE Decoder as shown above.
#---------------------------------------
# Initialize chunking session.
decoder_status = mke_decoder.start_decrypt()
if decoder_status != MteStatus.mte_status_success:
# MTE start chunking was not successful, handle failure appropriately.
# Below is only an example
raise Exception("Failed to start decode chunk. Status: {0} / {1}\n".format(MteBase.get_status_name(decoder_status),
MteBase.get_status_description(decoder_status)))
#----------------------------------
# For each chunk of data to ensure
# the buffer passed in is the
# size of the data being passed in.
#----------------------------------
decoded_chunk = mke_decoder.decrypt_chunk(encoded_bytes)
# Finish the chunking session, this may or may not have data returned.
# If no data is returned "finish_decrypted_chunk" will be null.
final_decoded_chunk,finish_status = mke_decoder.finish_decrypt()
if finish_status != MteStatus.mte_status_success:
# Decode chunk unsuccessful and cannot continue, handle failure appropriately.
# Below is only an example.
raise Exception("Failed to finish decode chunk. Status: {0} / {1}\n".format(MteBase.get_status_name(encoder_status),
MteBase.get_status_description(encoder_status)))
//---------------------------------------
// Create MTE MKE Decoder as shown above
//---------------------------------------
// Initialize chunking session
decoderStatus := decoder.StartDecrypt()
if decoderStatus != mte.Status_mte_status_success {
// MTE start chunking was not successful, handle failure appropriately
// Below is only an example
fmt.Fprintf(os.Stderr, "MTE Decoder startDecrypt error (%v): %v\n",
mte.GetStatusName(decoderStatus), mte.GetStatusDescription(decoderStatus))
retcode = int(decoderStatus)
return
}
//----------------------------------
// For each chunk of data to ensure
// the buffer passed in is the
// size of the data being passed in
//----------------------------------
decodedData := mkeDecoder.DecryptChunk(encodedBytes);
if decodedData == nil {
fmt.Fprintf(os.Stderr, "Decode error.\n")
break
}
//---------------------------------------------------------------------
// Finish the chunking session, this may or may not have data returned
// If no data is returned "finishDecrypt" will be null
//---------------------------------------------------------------------
finishDecodeChunk, status := decoder.FinishDecrypt()
if status != mte.Status_mte_status_success {
// Decode finish decrypt unsuccessful and cannot continue, handle failure appropriately
// Below is only an example
fmt.Fprintf(os.Stderr, "MTE Decoder finishDecrypt error (%v): %v\n",
mte.GetStatusName(status), mte.GetStatusDescription(status))
retcode = int(status)
return
}
<?php
//---------------------------------------
// Create MTE MKE Decoder as shown above
//---------------------------------------
$decoderStatus = $mkeDecoder->startDecrypt();
if(constant($decoderStatus) != mte_status_success)
{
// MTE was not successful so handle failure appropriately
// Below is only an example
throw new Exception("Failed to start decode chunk. Status: "
.$mkeDecoder->getStatusName(constant($decoderStatus)). " / "
.$mkeDecoder->getStatusDescription(constant($decoderStatus)));
}
?>
<?php
// Decode chunk, returns "bytes" and "str"
// If bytes is less than 0 there was an error
// Otherwise bytes will be the number of bytes returned
$chunkDecode = $mkeDecoder->decryptChunk($encode);
if($chunkDecode["bytes"] < 0)
{
// Decode chunk unsuccessful and cannot continue, handle failure appropriately
// Below is only an example
echo "Error decoding chunk";
}
$decodedString .= $chunkDecode["str"];
?>
<?php
// Once all data has been processed call finish method
// This method will not always have additional data that will need to be included
$finalDecodedChunk = $mkeDecoder->finishDecrypt();
if(constant($finalDecodedChunk["status"]) != mte_status_success)
{
// Decode finish unsuccessful and cannot continue, handle failure appropriately
// Below is only an example
throw new Exception("Failed to finish decode chunk. Status: "
.$mkeDecoder->getStatusName(constant($finalDecodedChunk["status"])). " / "
.$mkeDecoder->getStatusDescription(constant($finalDecodedChunk["status"])));
}
if(strlen($finalDecodedChunk["str"]) > 0){
$decodedString .= $finalDecodedChunk["str"];
}
?>