public void CheckServerEncryption_RM()
        {
            GenerateClientSessionKeys(out _, out var encryptedSessionKeys);
            List <byte[]> decryptedSessionKeys = new List <byte[]>();

            foreach (string key in encryptedSessionKeys)
            {
                decryptedSessionKeys.Add(ServerEncryption.RsaDecryptCipher(key));
            }

            Assert.That(decryptedSessionKeys.Count > 0);
            for (int i = 0; i < decryptedSessionKeys.Count; i++)
            {
                string plainText = GenerateRandomString(36);
                Assert.That(plainText.Length == 36);

                // Encrypt and prepare the message.
                string cipher  = ServerEncryption.EncryptPlainText(plainText, decryptedSessionKeys[i], out string initialisationVector).ToHexString();
                string message = $"{initialisationVector}{cipher}";

                // Decrypt the message [ClientDecryption_RM]
                byte[] initialisationVectorBytes = ClientEncryption.ParseIvFromMessage(message);
                byte[] cipherBytes = ClientEncryption.ParseCipherFromMessage(message);
                string decipher    = ClientEncryption.DecryptCipher(cipherBytes, decryptedSessionKeys[i], initialisationVectorBytes);

                Assert.AreEqual(plainText, decipher);
            }
        }
        public void CheckServerDecryption_RSA()
        {
            GenerateClientSessionKeys(out var unencryptedSessionKeys, out var encryptedSessionKeys);
            List <byte[]> decryptedSessionKeys = new List <byte[]>();

            Assert.That(encryptedSessionKeys.Count > 0);
            foreach (string key in encryptedSessionKeys)
            {
                decryptedSessionKeys.Add(ServerEncryption.RsaDecryptCipher(key));
            }
            Assert.AreEqual(encryptedSessionKeys.Count, decryptedSessionKeys.Count);

            // Ensuring that there is equivalence between unencrypted and decrypted session keys.
            for (int i = 0; i < decryptedSessionKeys.Count; i++)
            {
                Assert.AreEqual(decryptedSessionKeys[i].ToHexString(), unencryptedSessionKeys[i]);
            }
        }
        public static void Main(string[] args)
        {
            // T0
            // -- CLIENT --
            // Simulating a client-server relationship, the first step required is for the client to
            // generate a session key and encrypt it by virtue of the server's public key.
            // (Because the encryption libraries are static, this first step is automatically completed.)
            string sessionKey = ClientEncryption.RsaEncryptCipher().ToHexString();

            Console.WriteLine($"Client session key is: {sessionKey}");
            // At this point, the client sends this session key to the server.
            // -- END CLIENT --

            // T1
            // -- SERVER --
            // Once the server receives this session key, it must decrypt it by virtue of its private key.
            // Now actual messages can be sent.
            byte[] decryptedSessionKey = ServerEncryption.RsaDecryptCipher(sessionKey);
            Console.WriteLine($"Client session key length is: {decryptedSessionKey.Length}");
            // -- END SERVER --

            while (true)
            {
                // T2
                // At this stage, your program will send whatever information to the server or client.
                Console.WriteLine("Please enter some plain text: ");
                string plainText = Console.ReadLine();

                // T3
                // -- CLIENT --
                // Now the session key can be itself used for encryption.
                // Hex string is convenient for sending data because its characters are wide-spread.
                string initialisationVector = ClientEncryption.InitialisationVector;
                Console.WriteLine($"The current initialisation vector is: {initialisationVector}");

                // Encrypt the plain text.
                string cipher = ClientEncryption.EncryptPlainText(plainText, sessionKey.ToByteArray()).ToHexString();
                Console.WriteLine($"Your plain text ({plainText}) encrypted is: {cipher}");

                // Then send the cipher to the server.
                // Remember to send the initialisation vector, if using it, along with the message, like so:
                string message = $"{initialisationVector}{cipher}";
                Console.WriteLine($"The complete message (IV and cipher) is: {message}");
                // -- END CLIENT --

                // T4
                // -- SERVER --
                // The server then receives an encrypted (hex) string. However, it first needs to organise the
                // information before decrypting it, by discerning the IV and cipher (i.e., the actual message).
                // Of course, this step is not necessary if you decide not to utilise initialisation vectors.
                byte[] initialisationVectorBytes = ServerEncryption.ParseIvFromMessage(message);
                Console.WriteLine($"The length of the initialisation vector is: {initialisationVectorBytes.Length}");
                byte[] decipherBytes = ServerEncryption.ParseCipherFromMessage(message);
                Console.WriteLine($"The length of the (de)cipher is: {decipherBytes.Length}");

                // All that is remaining to do is to decrypt the cipher.
                string decipher = ServerEncryption.DecryptCipher(decipherBytes, decryptedSessionKey, initialisationVectorBytes);
                Console.WriteLine($"The deciphered message is: {decipher}");
                // Decryption complete.
                // -- END SERVER --
            }
        }