pairing_handshake
- CSharp
- Java
- Python
- Go
/// <summary>
/// Handshakes the with server.
/// </summary>
/// <param name="clientId">The client identifier.</param>
/// <param name="clients">The client dictionary</param>
/// <param name="currentConversation">The current conversation GUID.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
private static bool HandshakeWithServer(int clientId,
Dictionary<int, string> clients,
string currentConversation = null)
{
try
{
Console.WriteLine($"Performing Handshake for Client {clientId}");
//--------------------------------
// create clientId for this client
//--------------------------------
HandshakeModel handshake = new HandshakeModel {
ConversationIdentifier = Guid.NewGuid().ToString() };
//-------------------------------------------------------------
// If current conversation guid is passed in, update identifier
//-------------------------------------------------------------
if (!string.IsNullOrWhiteSpace(currentConversation))
{
handshake.ConversationIdentifier = currentConversation;
}
//-------------------------------------------------------------
// Add client to dictionary list if this is a new conversation
//-------------------------------------------------------------
if (!clients.ContainsKey(clientId))
{
clients.Add(clientId, handshake.ConversationIdentifier);
}
//-------------------------------------------
// Create eclypses DH containers for handshake
//-------------------------------------------
EclypsesECDH encoderEcdh = new EclypsesECDH();
EclypsesECDH decoderEcdh = new EclypsesECDH();
//-------------------------------------------
// Get the public key to send to other side
//-------------------------------------------
handshake.ClientEncoderPublicKey =
encoderEcdh.GetPublicKey(encoderEcdh.GetTheContainer());
handshake.ClientDecoderPublicKey =
decoderEcdh.GetPublicKey(decoderEcdh.GetTheContainer());
//-------------------
// Perform handshake
//-------------------
string handshakeResponse =
MakeHttpCall($"{_restAPIName}/api/handshake",
HttpMethod.Post, handshake.ConversationIdentifier,
_jsonContentType,
JsonSerializer.Serialize(handshake, _jsonOptions)).Result;
//---------------------------------------
// Deserialize the result from handshake
//---------------------------------------
ResponseModel<HandshakeModel> response =
JsonSerializer.Deserialize<ResponseModel<HandshakeModel>>(handshakeResponse, _jsonOptions);
//---------------------------------------
// If handshake was not successful break
//---------------------------------------
if (!response.Success)
{
Console.WriteLine($"Error making DH handshake for Client " +
"{clientId}: {response.Message}");
return false;
}
//----------------------
// Create shared secret
//----------------------
var encoderSharedSecretModel =
encoderEcdh.ProcessPartnerPublicKey(response.Data.ClientEncoderPublicKey);
var decoderSharedSecretModel =
decoderEcdh.ProcessPartnerPublicKey(response.Data.ClientDecoderPublicKey);
//----------------------------------------------------------
// Create and store MTE Encoder and Decoder for this Client
//----------------------------------------------------------
ResponseModel mteResponse = CreateMteStates(response.Data.ConversationIdentifier,
encoderSharedSecretModel.SharedSecret,
decoderSharedSecretModel.SharedSecret,
Convert.ToUInt64(response.Data.Timestamp));
//----------------------------------------------------------
// Clear container to ensure key is different for each client
//----------------------------------------------------------
encoderEcdh.ClearContainer();
decoderEcdh.ClearContainer();
//-----------------------------------------
// If there was an error break out of loop
//-----------------------------------------
if (!mteResponse.Success)
{
Console.WriteLine($"Error creating mte states for Client {clientId}: {response.Message}");
return false;
}
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw;
}
}
/**
* Handshake with the server and create MTE states
* @param clientId --> Current client id
* @param clients --> Client hash map
* @param currentConversation --> current conversation ID
* @return
*/
private static boolean HandshakeWithServer(int clientId,
HashMap<Integer, String> clients,
String currentConversation)
{
try
{
System.out.println("Performing Handshake for Client " + clientId);
//--------------------------------
// create clientId for this client
//--------------------------------
HandshakeModel handshake = new HandshakeModel();
handshake.ConversationIdentifier = UUID.randomUUID().toString();
//----------------------------------------------------------
// If current conversation id passed in update identifier
//----------------------------------------------------------
if (currentConversation != null && !currentConversation.isEmpty())
{
handshake.ConversationIdentifier = currentConversation;
}
//-------------------------------------------------------------
// Add client to dictionary list if this is a new conversation
//-------------------------------------------------------------
if(!clients.containsKey(clientId)) {
clients.put(clientId, handshake.ConversationIdentifier);
}
//-------------------------------------------
// Create eclypses DH containers for handshake
//-------------------------------------------
EclypsesECDH encoderEcdh = new EclypsesECDH();
EclypsesECDH decoderEcdh = new EclypsesECDH();
//-------------------------------------------
// Get the public key to send to other side
//-------------------------------------------
handshake.ClientEncoderPublicKey = encoderEcdh.getDevicePublicKey();
handshake.ClientDecoderPublicKey = decoderEcdh.getDevicePublicKey();
//-------------------
// Perform handshake
//-------------------
String handshakeString = _gson.toJson(handshake);
String handshakeResponse = MakeHttpCall(_restAPIName + "/api/handshake",
"POST",
handshake.ConversationIdentifier,
_jsonContentType,
handshakeString);
//---------------------------------------
// Deserialize the result from handshake
//---------------------------------------
Type handshakeResponseType = new TypeToken<ResponseModel<HandshakeModel>>() {}.getType();
ResponseModel<HandshakeModel> response =
_gson.fromJson(handshakeResponse, handshakeResponseType);
//---------------------------------------
// If handshake was not successful end
//---------------------------------------
if (!response.Success)
{
System.out.println("Error making DH handshake for Client " + clientId+ ": " +response.Message);
return false;
}
//----------------------
// Create shared secret
//----------------------
var encoderSharedSecret = encoderEcdh.createSharedSecret(response.Data.ClientEncoderPublicKey);
var decoderSharedSecret = decoderEcdh.createSharedSecret(response.Data.ClientDecoderPublicKey);
//----------------------------------------------------------
// Create and store MTE Encoder and Decoder for this Client
//----------------------------------------------------------
ResponseModel mteResponse = CreateMteStates(response.Data.ConversationIdentifier,
encoderSharedSecret,
decoderSharedSecret,
Long.parseLong(response.Data.Timestamp));
//----------------------------------------------------------
// Clear container to ensure key is different for each client
//----------------------------------------------------------
encoderEcdh = null;
decoderEcdh = null;
//-----------------------------------------
// If there was an error break out of loop
//-----------------------------------------
if (!mteResponse.Success)
{
System.out.println("Error creating mte states for Client " + clientId + ": " + response.Message);
return false;
}
return true;
}catch (Exception ex) {
ex.printStackTrace();
throw ex;
}
}
def handshake_with_server(client_id: int, current_conversation: str = NULL) -> bool:
"""
Handshakes with the server.
"""
print ("Performing Handshake for Client {0}".format(client_id))
# Create client_id for this client.
handshake = HandshakeModel()
# If current converation guid passed in, then upate identifier.
if len(current_conversation) > 0:
handshake.conversation_identifier = current_conversation
else:
handshake.conversation_identifier = str(uuid.uuid4())
# Add client to dictionary list if this is a new conversation.
if client_id not in _clients:
_clients[client_id] = handshake.conversation_identifier
# Create Eclypses DH containers for handshake.
encoder_ecdh = EclypsesECDH()
decoder_ecdh = EclypsesECDH()
# Get the public key to send to the other side.
handshake.client_encoder_public_key = encoder_ecdh.get_device_public_key()
handshake.client_decoder_public_key = decoder_ecdh.get_device_public_key()
# Perform handshake.
url = Constants().REST_API_NAME + "/api/handshake"
payload = {
"Timestamp": "null",
"ConversationIdentifier": handshake.conversation_identifier,
"ClientEncoderPublicKey": handshake.client_encoder_public_key.decode(),
"ClientDecoderPublicKey": handshake.client_decoder_public_key.decode()
}
headers = {
"Content-Type": JSON_CONTENT_TYPE,
"accept": "*/*",
Constants().CLIENT_ID_HEADER: handshake.conversation_identifier
}
handshake_response = requests.post(
url=url, data=json.dumps(payload), headers=headers)
# Deserialize the result from handshake.
response = handshake_response.json()
# If handshake was not successful, then break.
if response['Success'] == False:
print ("Error making DH handshake for Client {0}: {1}".format(client_id, response['Message']))
return False
# Create shared secret.
encoder_shared_secret_model = encoder_ecdh.create_shared_secret(
bytes(response['Data']['ClientEncoderPublicKey'], 'utf-8'))
decoder_shared_secret_model = decoder_ecdh.create_shared_secret(
bytes(response['Data']['ClientDecoderPublicKey'], 'utf-8'))
# Create and store MTE Encoder and Decoder for this Client.
mte_response = create_mte_states(personal=response['Data']['ConversationIdentifier'],
encoder_entropy=encoder_shared_secret_model, decoder_entropy=decoder_shared_secret_model,
nonce=int(response['Data']['Timestamp']))
# Clear container to ensure key is different for each client.
encoder_ecdh = NULL
decoder_ecdh = NULL
# If there was an error, break out of loop.
if mte_response.success == False:
print ("Error creating MTE states for Client {0}: {1}".format(client_id, response['Message']))
return False
return True
/**
* Performs Handshake with Server
* Creates the ECDH public keys and sends them to server
* When receives it back generates the shared secret
* then creates the Encoder and Decoder and saves the states
*
* clientId: clientId string
*
* Returns HandshakeResponse: encoderSharedSecret, decoderSharedSecret
*
*/
func PerformHandshakeWithServer(num int, clientId string) (out int, err error) {
fmt.Println("Performing handshake for client: "
+ strconv.FormatInt(int64(num), 10) + " ID: " + clientId)
//--------------------------------------------
// Set default return and response parameters
var handshakeModel HandshakeModel
handshakeModel.ConversationIdentifier = clientId
//----------------------------------------------
// Create eclypses ECDH for Encoder and Decoder
encoderEcdh := eclypsesEcdh.New()
decoderEcdh := eclypsesEcdh.New()
//----------------------------
// Get the Encoder public key
clientEncoderPKBytes, err := encoderEcdh.GetPublicKey()
if err != nil {
fmt.Println("Error creating Encoder public key: "
+ err.Error() + " Code: " + strconv.Itoa(errorCreatingPK))
return errorCreatingPK, err
}
//----------------------------
// Get the Decoder public key
clientDecoderPKBytes, err := decoderEcdh.GetPublicKey()
if err != nil {
fmt.Println("Error creating Decoder public key: "
+ err.Error() + " Code: " + strconv.Itoa(errorCreatingPK))
return errorCreatingPK, err
}
//-----------------------------------------
// Base64 encode keys so we can send them
handshakeModel.ClientEncoderPublicKey =
base64.StdEncoding.EncodeToString(clientEncoderPKBytes)
handshakeModel.ClientDecoderPublicKey =
base64.StdEncoding.EncodeToString(clientDecoderPKBytes)
//----------------------------------
// Json encode our handshake model
handshakeString, err := json.Marshal(handshakeModel)
if err != nil {
fmt.Println("Error marshalling handshakeModel: "
+ err.Error() + " Code: " + strconv.Itoa(errorMarshalJson))
return errorMarshalJson, err
}
//----------------------------------
// Make Http and get return string
hsModelString, errorcode, err := MakeHttpCall(restAPIName+handshakeRoute,
"POST",
clientId,
jsonContent,
string(handshakeString))
if err != nil {
fmt.Println("Error making Http call: "
+ err.Error() + " Code: " + strconv.Itoa(errorcode))
return errorcode, err
}
//-----------------------------
// Marshal json back to class
hrBytes := []byte(hsModelString)
var serverResponse ResponseModel[HandshakeModel]
json.Unmarshal(hrBytes, &serverResponse)
if !serverResponse.Success {
fmt.Println("Error back from server: "
+ serverResponse.Message + " Code: " + strconv.Itoa(errorFromServer))
return errorFromServer, errors.New(serverResponse.Message)
}
//--------------------------------------------
// Base64 Decode Encoder public key to []byte
partnerEncoderPublicKeyb64 :=
make([]byte, base64.StdEncoding.DecodedLen(len(serverResponse.Data.ClientEncoderPublicKey)))
n, err := base64.StdEncoding.Decode(partnerEncoderPublicKeyb64,
[]byte(serverResponse.Data.ClientEncoderPublicKey))
if err != nil {
fmt.Println("Error base64 decode encoderPK: "
+ err.Error() + " Code: " + strconv.Itoa(errorDecodingPK))
return errorDecodingPK, err
}
partnerEncoderPublicKeyBytes := partnerEncoderPublicKeyb64[:n]
//--------------------------------------------
// Base64 Decode Decoder public key to []byte
partnerDecoderPublicKeyb64 :=
make([]byte, base64.StdEncoding.DecodedLen(len(serverResponse.Data.ClientDecoderPublicKey)))
n, err = base64.StdEncoding.Decode(partnerDecoderPublicKeyb64,
[]byte(serverResponse.Data.ClientDecoderPublicKey))
if err != nil {
fmt.Println("Error base64 decode decoderPK: "
+ err.Error() + " Code: " + strconv.Itoa(errorDecodingPK))
return errorDecodingPK, err
}
partnerDecoderPublicKeyBytes := partnerDecoderPublicKeyb64[:n]
//-------------------------------
// Create Encoder shared secret
enSSBytes, err :=
encoderEcdh.CreateSharedSecret(partnerEncoderPublicKeyBytes, nil)
if err != nil {
fmt.Println("Error creating Encoder shared secret: "
+ err.Error() + " Code: " + strconv.Itoa(errorCreatingSS))
return errorCreatingSS, err
}
//-----------------------------
// Create Decoder shared secret
deSSBytes, err := decoderEcdh.CreateSharedSecret(partnerDecoderPublicKeyBytes, nil)
if err != nil {
fmt.Println("Error creating Decoder shared secret: "
+ err.Error() + " Code: " + strconv.Itoa(errorCreatingSS))
return errorCreatingSS, err
}
//-------------------------
// Clear out container
encoderEcdh.ClearContainer()
decoderEcdh.ClearContainer()
//------------------------------------
// Check version and output to screen
//------------------------------------
mteVersion := mte.GetVersion()
fmt.Printf("Using Mte Version %s\n", mteVersion)
//--------------------------------
// Check license -- use constants
// If no license can be blank
//--------------------------------
if !mte.InitLicense(companyName, companyLicense) {
fmt.Println("There was an error attempting to initialize the MTE License.")
retcode = errorMteLicense
return 0, errors.New("There was an error attempting to initialize the MTE License.")
}
//---------------------------------
// Create MTE Encoder and Decoder
retcode, err := CreateMteEncoder(serverResponse.Data.TimeStamp, clientId, enSSBytes)
if err != nil {
fmt.Println("Error creating Encoder: "
+ err.Error() + " Code: " + strconv.Itoa(errorCreatingEncoder))
return retcode, err
}
retcode, err = CreateMteDecoder(serverResponse.Data.TimeStamp, clientId, deSSBytes)
if err != nil {
fmt.Println("Error creating Decoder: "
+ err.Error() + " Code: " + strconv.Itoa(errorCreatingDecoder))
return retcode, err
}
return 0, nil
}