restore_save_mte_state
- CSharp
- Java
- Python
- Go
/// <summary>
/// Contacts the server.
/// </summary>
/// <param name="rnd">The random.</param>
/// <param name="currentConversation">The current conversation.</param>
/// <param name="clientNum">The i.</param>
/// <param name="clients">The clients.</param>
/// <exception cref="System.ApplicationException">Error restoring the encoder mte state for
/// Client {i}: {encoder.GetStatusDescription(encoderStatus)}</exception>
/// <exception cref="System.ApplicationException">Error restoring the decoder mte state for
/// Client {i}: {decoder.GetStatusDescription(decoderStatus)}</exception>
/// <exception cref="System.ApplicationException"></exception>
private static async Task ContactServer(Random rnd,
string currentConversation,
int clientNum,
Dictionary<int, string> clients)
{
try
{
//-------------------------------------------------
// Randomly select number of trips between 1 and max number of trips
//-------------------------------------------------
int numberTrips = rnd.Next(1, _maxNumberOfTrips);
//---------------------------------------
// Send message selected number of trips
//---------------------------------------
for (int t = 0; t < numberTrips; t++)
{
//-------------------------------------
// Get the current client encoder state
//-------------------------------------
string encoderState =
Constants.MteClientState.Get($"{Constants.EncoderPrefix}{currentConversation}");
string decryptedEncState =
_enc.Decrypt(encoderState, currentConversation, _encIV);
//-------------------------------------
// Restore the Encoder ensure it works
//-------------------------------------
MteEnc encoder = new MteEnc();
MteStatus encoderStatus = encoder.RestoreStateB64(decryptedEncState);
if (encoderStatus != MteStatus.mte_status_success)
{
Console.WriteLine($"Error restoring the encoder mte state for Client " +
"{clientNum}: {encoder.GetStatusDescription(encoderStatus)}");
throw new ApplicationException($"Error restoring the encoder mte state for Client " +
"{clientNum}: {encoder.GetStatusDescription(encoderStatus)}");
}
//-------------------------------------
// Get the current client decoder state
//-------------------------------------
string decoderState =
Constants.MteClientState.Get($"{Constants.DecoderPrefix}{currentConversation}");
string decryptedDecState =
_enc.Decrypt(decoderState, currentConversation, _encIV);
//-------------------------------------
// Restore the Decoder ensure it works
//-------------------------------------
MteDec decoder = new MteDec();
MteStatus decoderStatus = decoder.RestoreStateB64(decryptedDecState);
if (decoderStatus != MteStatus.mte_status_success)
{
Console.WriteLine($"Error restoring the decoder mte state for Client " +
"{clientNum}: {decoder.GetStatusDescription(decoderStatus)}");
throw new ApplicationException($"Error restoring the decoder mte state for Client " +
"{clientNum}: {decoder.GetStatusDescription(decoderStatus)}");
}
//-------------------------
// Encode message to send
//-------------------------
string message = $"Hello from client {clientNum} for the {t + 1} time.";
string encodedPayload = encoder.EncodeB64(message);
Console.WriteLine($"Sending message '{message}' to multi client server.");
//-----------------------------------------------------------
// Send encoded message to server, putting clientId in header
//-----------------------------------------------------------
string multiClientResponse =
MakeHttpCall($"{_restAPIName}/api/multiclient",
HttpMethod.Post,
currentConversation,
_textContentType,
encodedPayload).Result;
//----------------------
// deserialize response
//----------------------
ResponseModel<string> serverResponse =
JsonSerializer.Deserialize<ResponseModel<string>>(multiClientResponse, _jsonOptions);
if (!serverResponse.Success)
{
if (serverResponse.ResultCode.Equals(Constants.RC_MTE_STATE_NOT_FOUND,
StringComparison.InvariantCultureIgnoreCase))
{
//-------------------------------------------------------------------------
// the server does not have this client's state - we should "re-handshake"
//-------------------------------------------------------------------------
bool handshakeIsSuccessful = HandshakeWithServer(clientNum, clients, currentConversation);
if (!handshakeIsSuccessful)
{
Console.WriteLine($"Error from server for client " +
"{clientNum}: {serverResponse.Message}");
throw new ApplicationException();
}
//-----------------------------------------------------------------
// break out of this loop so we can contact again after handshake
//-----------------------------------------------------------------
return;
}
}
//---------------------------------------------------
// If this was successful save the new encoder state
//---------------------------------------------------
encoderState = encoder.SaveStateB64();
var encryptedEncState = _enc.Encrypt(encoderState, currentConversation, _encIV);
Constants.MteClientState.Store($"{Constants.EncoderPrefix}{currentConversation}",
encryptedEncState,
TimeSpan.FromMinutes(Constants.ExpireMinutes));
//-----------------------------
// decode the incoming message
//-----------------------------
string decodedMessage = decoder.DecodeStrB64(serverResponse.Data, out decoderStatus);
if (decoderStatus != MteStatus.mte_status_success)
{
Console.WriteLine($"Error restoring the decoder mte state for Client " +
"{clientNum}: {decoder.GetStatusDescription(decoderStatus)}");
throw new ApplicationException($"Error restoring the decoder mte state for Client " +
"{clientNum}: {decoder.GetStatusDescription(decoderStatus)}");
}
//----------------------------------------
// If decode is successful save new state
//----------------------------------------
decoderState = decoder.SaveStateB64();
var encryptedDecState = _enc.Encrypt(decoderState, currentConversation, _encIV);
Constants.MteClientState.Store($"{Constants.DecoderPrefix}{currentConversation}",
encryptedDecState,
TimeSpan.FromMinutes(Constants.ExpireMinutes));
//-------------------------------------
// Output incoming message from server
//-------------------------------------
Console.WriteLine($"Received '{decodedMessage}' from multi-client server.\n\n");
// Sleep between each call a random amount of time
// between 10 and 100 milli-seconds
Thread.Sleep(rnd.Next(0, 100));
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw;
}
}
/**
* Contact Server will send an encoded message to the server
* then decode what comes back
* @param rnd -->Random generator for number of trips
* @param currentConversation -->Client conversation
* @param clientNum --> current client number
* @param clients --> client hash map
*/
private static void ContactServer(Random rnd,
String currentConversation,
int clientNum,
HashMap<Integer, String> clients){
try {
//--------------------------
// Create encryption helper
//--------------------------
EncryptionHelper crypt = new EncryptionHelper();
//-------------------------------------------------
// Randomly select number of trips between 1 and max number of trips
//-------------------------------------------------
int numberTrips = rnd.nextInt(1, _maxNumberOfTrips);
//---------------------------------------
// Send message selected number of trips
//---------------------------------------
for (int t = 0; t < numberTrips; t++)
{
//-------------------------------------
// Get the current client encoder state
//-------------------------------------
String encryptedEncState = _mteStateCacheHelper.Get(Constants.EncoderPrefix + currentConversation);
if(encryptedEncState == null || encryptedEncState == "") {
throw new Exception("Cannot find encryted Encoder State for " + currentConversation);
}
String encoderState = crypt.decrypt(encryptedEncState,
EncryptionHelper.SHA256(currentConversation, 64),
_encIV.toString());
//-------------------------------------
// Restore the Encoder ensure it works
//-------------------------------------
MteEnc encoder = new MteEnc();
MteStatus encoderStatus = encoder.restoreStateB64(encoderState);
if (encoderStatus != MteStatus.mte_status_success)
{
System.out.println("Error restoring the encoder mte state for Client " +
clientNum +": " + encoder.getStatusDescription(encoderStatus));
throw new Exception("Error restoring the encoder mte state for Client " +
clientNum + ": " + encoder.getStatusDescription(encoderStatus));
}
//-------------------------
// Encode message to send
//-------------------------
String message = "Hello from client " + clientNum + " for the " + (t + 1) + " time.";
StrStatus encodedPayload = encoder.encodeB64(message);
if(encodedPayload.status != MteStatus.mte_status_success) {
System.out.println("Error encoding the message: " +
encoder.getStatusDescription(encodedPayload.status));
throw new Exception("Error restoring the decoder mte state for Client " +
clientNum + ": " + encoder.getStatusDescription(encodedPayload.status));
}
System.out.println("Sending message " + message + "to multi-client server.");
//-----------------------------------------------------------
// Send encoded message to server, putting clientId in header
//-----------------------------------------------------------
String multipleClientResponse = MakeHttpCall(_restAPIName + "/api/multiclient",
"POST",
currentConversation,
_textContentType,
encodedPayload.str);
//----------------------
// deserialize response
//----------------------
Type multipClientResponseType = new TypeToken<ResponseModel<String>>() {}.getType();
ResponseModel<String> serverResponse = _gson.fromJson(multipleClientResponse, multipClientResponseType);
if(!serverResponse.Success) {
if(serverResponse.ResultCode.equalsIgnoreCase(Constants.RC_MTE_STATE_NOT_FOUND)) {
//-------------------------------------------------------------------------
// the server does not have this client's state - we should "re-handshake"
//-------------------------------------------------------------------------
boolean handshakeIsSuccessful = HandshakeWithServer(clientNum, clients, currentConversation);
if (!handshakeIsSuccessful)
{
System.out.println("Error from server for client " +
clientNum + ": " + serverResponse.Message);
throw new Exception("Error from server for client " +
clientNum + ": " + serverResponse.Message);
}
//-----------------------------------------------------------------
// break out of this loop so we can contact again after handshake
//-----------------------------------------------------------------
return;
}
}
//---------------------------------------------------
// If this was successful save the new encoder state
//---------------------------------------------------
encoderState = encoder.saveStateB64();
encryptedEncState = crypt.encrypt(encoderState,
EncryptionHelper.SHA256(currentConversation, 64),
_encIV.toString());
_mteStateCacheHelper.Store(Constants.EncoderPrefix + currentConversation, encryptedEncState);
//-------------------------------------
// Get the current client decoder state
//-------------------------------------
String encryptedDecState = _mteStateCacheHelper.Get(Constants.DecoderPrefix + currentConversation);
if(encryptedDecState == null || encryptedDecState == "") {
throw new Exception("Cannot find encryted Decoder State for " +
currentConversation);
}
String decoderState = crypt.decrypt(encryptedDecState,
EncryptionHelper.SHA256(currentConversation, 64),
_encIV.toString());
//-------------------------------------
// Restore the Decoder ensure it works
//-------------------------------------
MteDec decoder = new MteDec();
MteStatus decoderStatus = decoder.restoreStateB64(decoderState);
if (decoderStatus != MteStatus.mte_status_success)
{
System.out.println("Error restoring the decoder mte state for Client " +
clientNum +": " + decoder.getStatusDescription(decoderStatus));
throw new Exception("Error restoring the decoder mte state for Client " +
clientNum + ": " + decoder.getStatusDescription(decoderStatus));
}
//-----------------------------
// decode the incoming message
//-----------------------------
StrStatus decodedMessage = decoder.decodeStrB64(serverResponse.Data);
if(decodedMessage.status != MteStatus.mte_status_success) {
System.out.println("Error decoding the message: " +
decoder.getStatusDescription(decodedMessage.status));
throw new Exception("Error decoding the message from the server for " +
clientNum + ": " + decoder.getStatusDescription(decodedMessage.status));
}
//----------------------------------------
// If decode is successful save new state
//----------------------------------------
decoderState = decoder.saveStateB64();
encryptedDecState = crypt.encrypt(decoderState,
EncryptionHelper.SHA256(currentConversation, 64),
_encIV.toString());
_mteStateCacheHelper.Store(Constants.DecoderPrefix + currentConversation, encryptedDecState);
// Sleep between each call a random amount of time
// between 10 and 100 milli-seconds
Thread.sleep(rnd.nextInt(0, 100));
}// end if statement
}catch (Exception ex) {
ex.printStackTrace();
System.out.println("Exception contacting server: "
+ ex.getMessage());
}
return;
}
def contact_server(current_conversation: str, client_num: int):
"""
Contacts the server.
"""
# Randomly select number of trips between 1 and max number of trips.
number_trips = randrange(1, MAX_NUMBER_OF_TRIPS)
# Send message selected number of trips.
for t in range (0, number_trips):
# Get the current client Encoder state.
encoder_state = _mte_client_state.get(Constants().ENCODER_PREFIX + current_conversation)
decrypted_enc_state = _enc.decrypt(encoder_state, current_conversation, _enc_IV)
# Restore the Encoder and ensure it works.
encoder = MteEnc.fromdefault()
encoder_status = encoder.restore_state_b64(decrypted_enc_state)
if encoder_status != MteStatus.mte_status_success:
print("Error restoring the Encoder MTE state for Client {0}: {1}".format(client_num, encoder.get_status_description(encoder_status)))
raise exception("Error restoring the Encoder MTE state for Client {0}: {1}".format(client_num, encoder.get_status_description(encoder_status)))
# Get the current client Decoder state.
decoder_state = _mte_client_state.get(Constants().DECODER_PREFIX + current_conversation)
decrypted_dec_state = _enc.decrypt(decoder_state, current_conversation, _enc_IV)
# Restore the Decoder and ensure it works.
decoder = MteDec.fromdefault()
decoder_status = decoder.restore_state_b64(decrypted_dec_state)
if decoder_status != MteStatus.mte_status_success:
print("Error restoring the Decoder MTE state for Client {0}: {1}".format(client_num, decoder.get_status_description(decoder_status)))
raise exception("Error restoring the Decoder MTE state for Client {0}: {1}".format(client_num, decoder.get_status_description(decoder_status)))
# Encode message to send.
message = "Hello from client {0} for the {1} time.".format(client_num, t+1)
encoded_payload, encode_status = encoder.encode_b64(message)
if encoder_status != MteStatus.mte_status_success:
print ("Error encoding the message for Client {0}: {1}".format(client_num, encoder.get_status_description(encode_status)))
raise exception("Error encoding the message for Client {0}: {1}".format(client_num, encoder.get_status_description(encode_status)))
print ("Sending message {0} to multi client server.\n".format(message))
# Send encoded message to server, putting client_id in header.
url = Constants().REST_API_NAME + "/api/multiclient"
payload = encoded_payload
headers = {
"Content-Type": TEXT_CONTENT_TYPE,
"accept": "*/*",
"Content-Length": str(len(encoded_payload)),
Constants().CLIENT_ID_HEADER: current_conversation
}
multi_client_response = requests.post(
url=url, data=payload, headers=headers)
# Deserialize response.
server_response = multi_client_response.json()
if server_response['Success'] == False:
# Check if we need to re-handshake.
if server_response['ResultCode'] == Constants().RC_MTE_STATE_NOT_FOUND:
# The server does not thave this client's state - we should re-handshake.
handshake_is_successful = handshake_with_server(client_num, current_conversation)
if handshake_is_successful == False:
print ("Error from server for client {0}: {1}".format(client_num, server_response['Message']))
# Break out of loop so we can contact again after handshake.
raise Exception("Error from server for client {0}: {1}".format(client_num, server_response['Message']))
# If this was successful, save the new Encoder state.
encoder_state = encoder.save_state_b64()
encrypted_enc_state = _enc.encrypt(encoder_state, current_conversation, _enc_IV)
_mte_client_state[Constants().ENCODER_PREFIX+current_conversation] = encrypted_enc_state
# Decode the incoming message.
decoded_message, decoder_status = decoder.decode_str_b64(server_response['Data'])
if decoder.status_is_error(decoder_status):
print ("Error decoding the message for Client {0}: {1}".format(client_num, decoder.get_status_description(decoder_status)))
raise exception("Error decoding the message for Client {0}: {1}".format(client_num, decoder.get_status_description(decoder_status)))
# If decode is successful, save the new Decoder state.
decoder_state = decoder.save_state_b64()
encrypted_dec_state = _enc.encrypt(decoder_state, current_conversation, _enc_IV)
_mte_client_state[Constants().DECODER_PREFIX+current_conversation] = encrypted_dec_state
print ("Received {0} from multi-client server.\n".format(decoded_message))
# Sleep between each call a random amount of time.
time.sleep(randrange(0,100)/1000)
/**
* Send MTE Encoded message to server
*/
func SendMultiToServer(clientId string, clientNum int, wg *sync.WaitGroup) {
//-------------------------------------------------
// Make sure done is called when this is finsihed
defer wg.Done()
//--------------------------------------------
// Get random number of times to send messages
randNum := mrand.Intn(maxNumTrips-1) + 1
//-----------------
// Create Encoder
encoder := mte.NewEncDef()
defer encoder.Destroy()
//--------------------------------------------------
// Get the Encoder state from the cache and decrypt
encoderState, err := stateCache.Get([]byte(encPrefix + clientId))
nonceSize := gcm.NonceSize()
if len(encoderState) < nonceSize {
fmt.Println(err)
retcode = errorRetrievingState
return
}
aesNonce, encoderState := encoderState[:nonceSize], encoderState[nonceSize:]
decryptedState, err := gcm.Open(nil, aesNonce, encoderState, nil)
if err != nil {
fmt.Println(err)
retcode = errorDecryptingState
return
}
//---------------------------
// Restore the Encoder state
encoderStatus := encoder.RestoreState(decryptedState)
if encoderStatus != mte.Status_mte_status_success {
errorMessage := "Encoder restore error ("
+ mte.GetStatusName(encoderStatus) + ", "
+ mte.GetStatusDescription(encoderStatus) + ")"
fmt.Println(errorMessage)
retcode = errorRestoringState
return
}
//------------------------
// Create the MTE Decoder
decoder := mte.NewDecDef()
defer decoder.Destroy()
//-----------------------------------
// Get the Decoder state and decrypt
decoderState, err := stateCache.Get([]byte(decPrefix + clientId))
nonceSize = gcm.NonceSize()
if len(decoderState) < nonceSize {
fmt.Println(err)
retcode = errorRetrievingState
return
}
aesNonce, decoderState = decoderState[:nonceSize], decoderState[nonceSize:]
decryptedState, err = gcm.Open(nil, aesNonce, decoderState, nil)
if err != nil {
fmt.Println(err)
retcode = errorDecryptingState
return
}
//---------------------------
// Restore the Decoder state
decoderStatus := decoder.RestoreState(decryptedState)
if decoderStatus != mte.Status_mte_status_success {
errorMessage := "Decoder restore error ("
+ mte.GetStatusName(decoderStatus) + ", "
+ mte.GetStatusDescription(decoderStatus) + ")"
fmt.Println(errorMessage)
retcode = errorRestoringState
return
}
//---------------------------------------------------------------
// Send message to server random number of times for this client
for i := 1; i <= randNum; i++ {
//----------------------
// Set message content
message := "Hello from client " + strconv.Itoa(clientNum) + " : "
+ clientId + " for the " + strconv.Itoa(i) + " time"
//----------------
// Encode message
encoded, encoderStatus := encoder.EncodeStrB64(message)
if encoderStatus != mte.Status_mte_status_success {
errorMessage := "Encode error " + mte.GetStatusName(encoderStatus)
+ " , " + mte.GetStatusDescription(encoderStatus)
fmt.Println(errorMessage)
retcode = errorEncodingData
return
}
//------------------------------------
// Make Http Call to send to server
hsModelString, errorcode, err := MakeHttpCall(restAPIName+multiClientRoute,
"POST",
clientId,
textContent,
encoded)
if err != nil {
errorMessage := "Error making Http call: "
+ err.Error() + " Code: " + strconv.Itoa(errorcode)
fmt.Println(errorMessage)
retcode = errorcode
return
}
//-----------------------------
// Marshal json back to class
hrBytes := []byte(hsModelString)
var serverResponse ResponseModel[string]
json.Unmarshal(hrBytes, &serverResponse)
if !serverResponse.Success {
errorMessage := "Error back from server: "
+ serverResponse.Message + " Code: " + strconv.Itoa(errorFromServer)
fmt.Println(errorMessage)
retcode = errorMarshalJson
return
}
//-----------------------
// Decode return message
decodedMessage, decoderStatus := decoder.DecodeStrB64(serverResponse.Data)
if mte.StatusIsError(decoderStatus) {
errorMessage := "Decode error " + mte.GetStatusName(decoderStatus)
+ " , " + mte.GetStatusDescription(decoderStatus)
fmt.Println(errorMessage)
retcode = errorDecodingData
return
}
//----------------------------------------
// Print out message received from server
fmt.Println("Received '" + decodedMessage + "' from multi-client server.")
}
//--------------------
// save Encoder state
encoderState = encoder.SaveState()
//-------------------------
// Delete from cache first
stateCache.Del([]byte(encPrefix + clientId))
//------------------------------------
// Encrypt state to put back in cache
// Creates a new byte array the size of the nonce
aesNonce = make([]byte, gcm.NonceSize())
//-----------------------------------------------------
// Populates our nonce with a cryptographically secure
// Random sequence
if _, err = io.ReadFull(crRand.Reader, aesNonce); err != nil {
fmt.Println(err)
retcode = errorEncryptingState
return
}
//---------------------------------------
// Seal/Encrpyt the actual Encoder State
encryptedState := gcm.Seal(aesNonce, aesNonce, encoderState, nil)
//-------------------------------------------
// Update cache with encrypted Encoder State
stateCache.Set([]byte(encPrefix+clientId), encryptedState, cacheExpire)
//---------------------
// Save Decoder state
decoderState = decoder.SaveState()
//-------------------------
// Delete from cache first
stateCache.Del([]byte(decPrefix + clientId))
//------------------------------------
// Encrypt state to put back in cache
// Creates a new byte array the size of the nonce
aesNonce = make([]byte, gcm.NonceSize())
//-----------------------------------------------------
// Populates our nonce with a cryptographically secure
// Random sequence
if _, err = io.ReadFull(crRand.Reader, aesNonce); err != nil {
fmt.Println(err)
retcode = errorEncryptingState
return
}
//---------------------------------------
// Seal/Encrpyt the actual Decoder State
encryptedState = gcm.Seal(aesNonce, aesNonce, decoderState, nil)
//-------------------------------------------
// Update cache with encrypted Encoder State
stateCache.Set([]byte(decPrefix+clientId), encryptedState, cacheExpire)
}