Skip to main content

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

// 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)}");
}

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.

// 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));
}

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.

// 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));
}

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.

// 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));
}

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

// 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)}");
}

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.

// 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));
}

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.

// 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));
}

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.

// 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));
}

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.

//---------------------------------------
// 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));
}

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.

//---------------------------------------
// 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));
}