Skip to content
Chrono edited this page Sep 10, 2021 · 11 revisions

This section will be describing on all the possible ephemeral TLS(Transport Layer Security) operations with the server.

API Root URL: https://mrchewitsoftware.com.my:5001/api/ECDH_ECDSA_TempSession

Prerequisites:

  1. You must know how to convert data into/from Base64 encoding
  2. You must know how to convert data into URL encoded format
  3. You must know how to generate a random password without special characters as an ASCII ID (will be useful later)
  4. You must know how to use query string in HttpGet
  5. You must know how to convert data into/from JSON string
https://mrchewitsoftware.com.my:5001/api/ECDH_ECDSA_TempSession/byID?
https://mrchewitsoftware.com.my:5001/api/ECDH_ECDSA_TempSession/DeleteByClientCryptographicID?
https://mrchewitsoftware.com.my:5001/api/ECDH_ECDSA_TempSession/ByHandshake?
https://mrchewitsoftware.com.my:5001/api/ECDH_ECDSA_TempSession/BySharedSecret?

These 4 different endpoint acts differently and have different purposes.

1st Endpoint: Initiating ETLS session

https://mrchewitsoftware.com.my:5001/api/ECDH_ECDSA_TempSession/byID?

This endpoint was responsible for initiating an ETLS session with the server.

Here's an example on how to do it.

        public void InitializeNewSession()
        {
            //refers to the SecureIDGenerator in Helper
            String MySession_ID = MySecureIDGenerator.GenerateUniqueString();
            ECDH_ECDSA_Models MyECDH_ECDSA_Models = new ECDH_ECDSA_Models();
            Boolean CheckServerOnline = true;
            Boolean CreateShareSecretStatus = true;
            Boolean CheckSharedSecretStatus = true;
            Byte[] ServerECDSAPKByte = new Byte[] { };
            Byte[] ServerECDHSPKByte = new Byte[] { };
            Byte[] ServerECDHPKByte = new Byte[] { };
            Boolean VerifyBoolean = true;
            String SessionStatus = "";
            String ExceptionString = "";
            using (var InitializeHandShakeHttpclient = new HttpClient())
            {
                InitializeHandShakeHttpclient.BaseAddress = new Uri("https://mrchewitsoftware.com.my:5001/api/");
                InitializeHandShakeHttpclient.DefaultRequestHeaders.Accept.Clear();
                InitializeHandShakeHttpclient.DefaultRequestHeaders.Accept.Add(
                    new MediaTypeWithQualityHeaderValue("application/json"));
                var response = InitializeHandShakeHttpclient.GetAsync("ECDH_ECDSA_TempSession/byID?ClientPathID=" + MySession_ID);
                try
                {
                    response.Wait();
                }
                catch
                {
                    CheckServerOnline = false;
                }
                if (CheckServerOnline == true)
                {
                    var result = response.Result;
                    if (result.IsSuccessStatusCode)
                    {
                        var readTask = result.Content.ReadAsStringAsync();
                        readTask.Wait();

                        var ECDH_ECDSA_Models_Result = readTask.Result;
                        MyECDH_ECDSA_Models = JsonConvert.DeserializeObject<ECDH_ECDSA_Models>(ECDH_ECDSA_Models_Result);
                        if (MyECDH_ECDSA_Models.ID_Checker_Message.CompareTo("You still can use the exact same client ID...") == 0 || MyECDH_ECDSA_Models.ID_Checker_Message.CompareTo("You have an exact client ID great~") == 0)
                        {
                            ServerECDSAPKByte = Convert.FromBase64String(MyECDH_ECDSA_Models.ECDSA_PK_Base64String);
                            ServerECDHSPKByte = Convert.FromBase64String(MyECDH_ECDSA_Models.ECDH_SPK_Base64String);
                            try
                            {
                                ServerECDHPKByte = SodiumPublicKeyAuth.Verify(ServerECDHSPKByte, ServerECDSAPKByte);
                            }
                            catch (Exception exception)
                            {
                                VerifyBoolean = false;
                                ExceptionString = exception.ToString();
                                SessionStatus += ExceptionString + Environment.NewLine;
                            }
                            if (VerifyBoolean == true)
                            {
                                //Do something here... as the system able to verify the server signed ECDHPK or X25519PK
                                //Please store the verified server ECDHPK or X25519 PK as it will be useful later
                            }
                            else
                            {
                                //Do something here as the system unable to verify the server signed ECDHPK or X25519PK
                            }
                            //These might not be necessary but I leave it there for clearing the server public key material on the client
                            //side through cryptography secure way
                            SodiumSecureMemory.SecureClearBytes(ServerECDSAPKByte);
                            SodiumSecureMemory.SecureClearBytes(ServerECDHSPKByte);
                            SodiumSecureMemory.SecureClearBytes(ServerECDHPKByte);
                            SodiumSecureMemory.SecureClearString(MyECDH_ECDSA_Models.ECDSA_PK_Base64String);
                            SodiumSecureMemory.SecureClearString(MyECDH_ECDSA_Models.ECDH_SPK_Base64String);
                        }
                        else
                        {
                            //Do something..
                        }
                    }
                    else
                    {
                        //Do something..
                    }
                }
                else
                {
                    //Do something..
                }
            }
        }

There's a reason why there's a need to use cryptography random number generator to generate random ASCII ID. This was done with a reason that it can avoid possible ID duplication in the server side.

2nd Endpoint: Delete ETLS session

https://mrchewitsoftware.com.my:5001/api/ECDH_ECDSA_TempSession/DeleteByClientCryptographicID?

This endpoint is responsible for deleting ETLS session

Here's an example on how to do it

Boolean ServerOnlineChecker = true;
StreamReader MyStreamReader = new StreamReader(Application.StartupPath + "\\Temp_Session\\" + "SessionID.txt");
String Temp_Session_ID = MyStreamReader.ReadLine();
MyStreamReader.Close();
Byte[] ClientECDSASKByte = new Byte[] { };
Byte[] RandomData = new Byte[240];
RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider();
rngCsp.GetBytes(RandomData);
Byte[] SignedRandomData = new Byte[] { };
String Status = "";
if (Temp_Session_ID != null && Temp_Session_ID.CompareTo("") != 0)
{
    using (var client = new HttpClient())
    {
        ClientECDSASKByte = File.ReadAllBytes(Application.StartupPath + "\\Temp_Session\\" + Temp_Session_ID + "\\ECDSASK.txt");
        SignedRandomData = SodiumPublicKeyAuth.Sign(RandomData, ClientECDSASKByte,true);
        client.BaseAddress = new Uri("https://mrchewitsoftware.com.my:5001/api/");
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(
            new MediaTypeWithQualityHeaderValue("application/json"));
        var response = client.GetAsync("ECDH_ECDSA_TempSession/DeleteByClientCryptographicID?ClientPathID=" + Temp_Session_ID + "&ValidationData=" + HttpUtility.UrlEncode(Convert.ToBase64String(SignedRandomData)));
        SodiumSecureMemory.SecureClearBytes(RandomData);
        SodiumSecureMemory.SecureClearBytes(SignedRandomData);
        try
        {
            response.Wait();
        }
        catch
        {
            ServerOnlineChecker = false;
        }
        if (ServerOnlineChecker == true)
        {
            var result = response.Result;
            if (result.IsSuccessStatusCode)
            {
                var readTask = result.Content.ReadAsStringAsync();
                readTask.Wait();

                Status = readTask.Result;

                if (Status.Contains("Error"))
                {
                    //Do something
                }
                else
                {
                    //Do something..
                }
            }
            else
            {
                //Do something..
            }
        }
    }
}
else
{
    //Do something..
}

Warning: This function can only be call if you had established a working ephemeral TLS session with the server.

In future, this endpoint will work differently as it's still a work in the progress at the moment.. For the time being, this is how you can call it

3rd Endpoint: Establish ETLS session

https://mrchewitsoftware.com.my:5001/api/ECDH_ECDSA_TempSession/ByHandshake?

This endpoint is responsible for establishing ETLS session

Here's an example on how to do it

//The MySession_ID is the ASCII ID that was sent to the server during ETLS initialization
//SignedClientSessionECDHPKByte is the client's signed X25519 PK or ECDHPK
//ClientSessionECDSAPKByte is the client's ED25519 PK or ECDSA PK
public void CreateSharedSecret(ref Boolean CheckBoolean, String MySession_ID, Byte[] SignedClientSessionECDHPKByte, Byte[] ClientSessionECDSAPKByte)
{
    CheckBoolean = false;
    String SessionStatus = "";
    var CreateSharedSecretHttpClient = new HttpClient();
    CreateSharedSecretHttpClient.BaseAddress = new Uri("https://mrchewitsoftware.com.my:5001/api/");
    CreateSharedSecretHttpClient.DefaultRequestHeaders.Accept.Clear();
    CreateSharedSecretHttpClient.DefaultRequestHeaders.Accept.Add(
        new MediaTypeWithQualityHeaderValue("application/json"));
    var newresponse = CreateSharedSecretHttpClient.GetAsync("ECDH_ECDSA_TempSession/ByHandshake?ClientPathID=" + MySession_ID + "&SECDHPK=" + 
        HttpUtility.UrlEncode(Convert.ToBase64String(SignedClientSessionECDHPKByte)) + "&ECDSAPK=" + 
        HttpUtility.UrlEncode(Convert.ToBase64String(ClientSessionECDSAPKByte)));
    try
    {
        newresponse.Wait();
        var newresult = newresponse.Result;

        if (newresult.IsSuccessStatusCode)
        {
            var newreadTask = newresult.Content.ReadAsStringAsync();
            newreadTask.Wait();

            SessionStatus += newreadTask.Result;

            if (SessionStatus.Contains("Error")==true)
            {
                CheckBoolean = false;
            }
            else
            {
                CheckBoolean = true;
            }
        }
        else
        {
            //Do something..
        }
    }
    catch
    {
        //Do something..
    }
}

4th Endpoint: Check if created shared secret match with server

https://mrchewitsoftware.com.my:5001/api/ECDH_ECDSA_TempSession/BySharedSecret?

This endpoint is responsible for checking shared secret

Here's an example on how to do it

public void CheckSharedSecret(ref Boolean CheckBoolean, String MySession_ID, Byte[] ServerECDHPKByte, Byte[] SessionECDHPrivateKey, Byte[] SessionECDSAPrivateKey)
{
    CheckBoolean = false;
    Boolean CheckServerOnline = true;
    String CheckSharedSecretStatus = "";
    Byte[] TestData = new Byte[] { 255, 255, 255 };
    Byte[] SharedSecretByte = SodiumScalarMult.Mult(SessionECDHPrivateKey, ServerECDHPKByte,true);
    Byte[] NonceByte = SodiumSecretBox.GenerateNonce();
    Byte[] TestEncryptedData = SodiumSecretBox.Create(TestData, NonceByte, SharedSecretByte);
    var CheckSharedSecretHttpClient = new HttpClient();
    CheckSharedSecretHttpClient.BaseAddress = new Uri("https://mrchewitsoftware.com.my:5001/api/");
    CheckSharedSecretHttpClient.DefaultRequestHeaders.Accept.Clear();
    CheckSharedSecretHttpClient.DefaultRequestHeaders.Accept.Add(
        new MediaTypeWithQualityHeaderValue("application/json"));
    var CheckSharedSecretHttpClientResponse = CheckSharedSecretHttpClient.GetAsync("ECDH_ECDSA_TempSession/BySharedSecret?ClientPathID=" + MySession_ID + "&CipheredData=" + HttpUtility.UrlEncode(Convert.ToBase64String(TestEncryptedData)) + "&Nonce=" + HttpUtility.UrlEncode(Convert.ToBase64String(NonceByte)));
    try
    {
        CheckSharedSecretHttpClientResponse.Wait();
    }
    catch
    {
        CheckServerOnline = false;
    }
    if (CheckServerOnline == true)
    {
        var CheckSharedSecretHttpClientResponseResult = CheckSharedSecretHttpClientResponse.Result;

        if (CheckSharedSecretHttpClientResponseResult.IsSuccessStatusCode)
        {
            var CheckSharedSecretHttpClientResponseResultReadTask = CheckSharedSecretHttpClientResponseResult.Content.ReadAsStringAsync();
            CheckSharedSecretHttpClientResponseResultReadTask.Wait();

            CheckSharedSecretStatus = CheckSharedSecretHttpClientResponseResultReadTask.Result;
            if (CheckSharedSecretStatus.Contains("Error"))
            {
                CheckBoolean = false;
            }
            else
            {
                //Do something here..
                //Make sure to store the ETLS session ID, Shared Secret and ED25519 SK or ECDSA SK
                //These will be prerequisites to communicate with the server API
                CheckBoolean = true;
            }
        }
        else
        {
            //Do something here..
        }
        //Clearing shared secret securely from memory through cryptography functions.
        SodiumSecureMemory.SecureClearBytes(SharedSecretByte);
    }
    else
    {
        //Do something here..
    }
}