chunk-decoding
- 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"];
}
?>