public MessageClientIdentity(string systemName, string clientName, ECDiffieHellmanCurve curve)
        {
            ECDiffieHellman dh;

            var dhCurve = curve switch
            {
                ECDiffieHellmanCurve.P256 => ECCurve.NamedCurves.nistP256,
                ECDiffieHellmanCurve.P384 => ECCurve.NamedCurves.nistP384,
                ECDiffieHellmanCurve.P521 => ECCurve.NamedCurves.nistP521,
                _ => throw new ArgumentOutOfRangeException(nameof(curve))
            };

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                dh    = new ECDiffieHellmanCng(dhCurve);
                ECDsa = new ECDsaCng();
            }
            else
            {
#if (!NET48)
                dh = new ECDiffieHellmanOpenSsl();
#else
                throw new NotSupportedException("ECDiffieHellmanOpenSsl is not supported in .NET 4.8");
#endif

                ECDsa = new ECDsaOpenSsl();
            }

            SystemName      = systemName;
            Name            = clientName;
            ECDiffieHellman = dh;

            ECDsa.ImportParameters(dh.ExportExplicitParameters(true));
        }
Exemple #2
0
        protected override AsymmetricAlgorithm LoadKey(ReadOnlyMemory <byte> pkcs8)
        {
            PrivateKeyInfoAsn   privateKeyInfo = PrivateKeyInfoAsn.Decode(pkcs8, AsnEncodingRules.BER);
            AsymmetricAlgorithm key;

            switch (privateKeyInfo.PrivateKeyAlgorithm.Algorithm.Value)
            {
            case Oids.Rsa:
                key = new RSAOpenSsl();
                break;

            case Oids.Dsa:
                key = new DSAOpenSsl();
                break;

            case Oids.EcDiffieHellman:
            case Oids.EcPublicKey:
                key = new ECDiffieHellmanOpenSsl();
                break;

            default:
                throw new CryptographicException(
                          SR.Cryptography_UnknownAlgorithmIdentifier,
                          privateKeyInfo.PrivateKeyAlgorithm.Algorithm.Value);
            }

            key.ImportPkcs8PrivateKey(pkcs8.Span, out int bytesRead);

            if (bytesRead != pkcs8.Length)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }

            return(key);
        }
 public Bob()
 {
     using (ECDiffieHellmanOpenSsl bob = new ECDiffieHellmanOpenSsl())
     {
         BobPublicKey   = bob.PublicKey;
         _bobPrivateKey = bob.DeriveKeyMaterial(Alice.AlicePublicKey);
     }
 }
Exemple #4
0
 public void DefaultCtor()
 {
     using (var e = new ECDiffieHellmanOpenSsl())
     {
         int keySize = e.KeySize;
         Assert.Equal(521, keySize);
         e.Exercise();
     }
 }
Exemple #5
0
 public void VerifyDuplicateKey_DistinctHandles()
 {
     using (var first = new ECDiffieHellmanOpenSsl())
         using (SafeEvpPKeyHandle firstHandle = first.DuplicateKeyHandle())
             using (SafeEvpPKeyHandle firstHandle2 = first.DuplicateKeyHandle())
             {
                 Assert.NotSame(firstHandle, firstHandle2);
             }
 }
Exemple #6
0
        public void LookupCurveByOidValue()
        {
            var          ec    = new ECDiffieHellmanOpenSsl(ECCurve.CreateFromValue(ECDSA_P256_OID_VALUE)); // Same as nistP256
            ECParameters param = ec.ExportParameters(false);

            param.Validate();
            Assert.Equal(256, ec.KeySize);
            Assert.True(param.Curve.IsNamed);
            Assert.Equal("ECDSA_P256", param.Curve.Oid.FriendlyName);
            Assert.Equal(ECDSA_P256_OID_VALUE, param.Curve.Oid.Value);
        }
Exemple #7
0
        public void Ctor521()
        {
            int expectedKeySize = 521;

            using (var e = new ECDiffieHellmanOpenSsl(expectedKeySize))
            {
                int keySize = e.KeySize;
                Assert.Equal(expectedKeySize, keySize);
                e.Exercise();
            }
        }
Exemple #8
0
        public void VerifyDuplicateKey_InvalidHandle()
        {
            using (var ecdsa = new ECDiffieHellmanOpenSsl())
            {
                SafeEvpPKeyHandle pkey = ecdsa.DuplicateKeyHandle();

                using (pkey)
                {
                }

                AssertExtensions.Throws <ArgumentException>("pkeyHandle", () => new ECDiffieHellmanOpenSsl(pkey));
            }
        }
        public static partial ECDiffieHellman Create(ECParameters parameters)
        {
            ECDiffieHellman ecdh = new ECDiffieHellmanOpenSsl();

            try
            {
                ecdh.ImportParameters(parameters);
                return(new ECDiffieHellmanWrapper(ecdh));
            }
            catch
            {
                ecdh.Dispose();
                throw;
            }
        }
Exemple #10
0
        public void VerifyDuplicateKey_ValidHandle()
        {
            using (var first = new ECDiffieHellmanOpenSsl())
                using (SafeEvpPKeyHandle firstHandle = first.DuplicateKeyHandle())
                    using (ECDiffieHellman second = new ECDiffieHellmanOpenSsl(firstHandle))
                        using (ECDiffieHellmanPublicKey firstPublic = first.PublicKey)
                            using (ECDiffieHellmanPublicKey secondPublic = second.PublicKey)
                            {
                                byte[] firstSecond = first.DeriveKeyFromHash(secondPublic, HashAlgorithmName.SHA256);
                                byte[] secondFirst = second.DeriveKeyFromHash(firstPublic, HashAlgorithmName.SHA256);
                                byte[] firstFirst  = first.DeriveKeyFromHash(firstPublic, HashAlgorithmName.SHA256);

                                Assert.Equal(firstSecond, secondFirst);
                                Assert.Equal(firstFirst, firstSecond);
                            }
        }
        public static void Main(string[] args)
        {
            using (ECDiffieHellmanOpenSsl alice = new ECDiffieHellmanOpenSsl())
            {
                AlicePublicKey = alice.PublicKey;

                Bob bob = new Bob();

                byte[] aliceKey         = alice.DeriveKeyMaterial(bob.BobPublicKey);
                byte[] encryptedMessage = null;
                byte[] iv = null;

                Send(aliceKey, "Secret message", out encryptedMessage, out iv);
                bob.Receive(encryptedMessage, iv);
            }
        }
Exemple #12
0
        public void CtorHandle384()
        {
            IntPtr ecKey = Interop.Crypto.EcKeyCreateByOid(ECDSA_P384_OID_VALUE);

            Assert.NotEqual(IntPtr.Zero, ecKey);
            int success = Interop.Crypto.EcKeyGenerateKey(ecKey);

            Assert.NotEqual(0, success);

            using (var e = new ECDiffieHellmanOpenSsl(ecKey))
            {
                int keySize = e.KeySize;
                Assert.Equal(384, keySize);
                e.Exercise();
            }

            Interop.Crypto.EcKeyDestroy(ecKey);
        }
Exemple #13
0
        public void CtorHandleDuplicate()
        {
            IntPtr ecKey = Interop.Crypto.EcKeyCreateByOid(ECDSA_P521_OID_VALUE);

            Assert.NotEqual(IntPtr.Zero, ecKey);
            int success = Interop.Crypto.EcKeyGenerateKey(ecKey);

            Assert.NotEqual(0, success);

            using (var e = new ECDiffieHellmanOpenSsl(ecKey))
            {
                // Make sure ECDsaOpenSsl did its own ref-count bump.
                Interop.Crypto.EcKeyDestroy(ecKey);

                int keySize = e.KeySize;
                Assert.Equal(521, keySize);
                e.Exercise();
            }
        }
        static void anonym_peer()
        {
            IPAddress  ipAddress       = IPAddress.Parse(local_ip);
            IPEndPoint ipLocalEndPoint = new IPEndPoint(ipAddress, local_port);

            //Connect to server
            TcpClient client = new TcpClient(ipLocalEndPoint);

            client.Connect(server_ip, server_port);
            SslStream sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);

            authenticate_server(sslStream);

            TCPCommunication.send_message_tcp(sslStream, "ANONYM_P");
            TCPCommunication.send_message_tcp(sslStream, HashString.GetHashString(pubKey.ToString()));

            string response = TCPCommunication.recieve_message_tcp(sslStream);

            if (String.Compare(response, "ACCEPT") == 0)
            {
                node = new ECDiffieHellmanOpenSsl();
                ECParameters node_ep = node.ExportParameters(false);

                pubKey = new PublicKeyCoordinates(node_ep.Q.X, node_ep.Q.Y);
                string hash = HashString.GetHashString(pubKey.ToString());

                TCPCommunication.send_message_tcp(sslStream, hash);

                response = TCPCommunication.recieve_message_tcp(sslStream);

                Console.WriteLine(response);

                sslStream.Close();
                client.Close();
            }
            else if (String.Compare(response, "REJECT") == 0)
            {
                Console.WriteLine("Connection rejected");
                sslStream.Close();
                client.Close();
            }
        }
Exemple #15
0
        public void KeySizePropWithExercise()
        {
            using (var e = new ECDiffieHellmanOpenSsl())
            {
                e.KeySize = 384;
                Assert.Equal(384, e.KeySize);
                e.Exercise();
                ECParameters p384 = e.ExportParameters(false);
                Assert.Equal(ECCurve.ECCurveType.Named, p384.Curve.CurveType);

                e.KeySize = 521;
                Assert.Equal(521, e.KeySize);
                e.Exercise();
                ECParameters p521 = e.ExportParameters(false);
                Assert.Equal(ECCurve.ECCurveType.Named, p521.Curve.CurveType);

                // ensure the key was regenerated
                Assert.NotEqual(p384.Curve.Oid.Value, p521.Curve.Oid.Value);
            }
        }
        static void init_connection(SslStream sslStream)
        {
            //Authenticate certificate
            authenticate_server(sslStream);

            TCPCommunication.send_message_tcp(sslStream, "INIT_P");
            string response = TCPCommunication.recieve_message_tcp(sslStream);

            Console.WriteLine(response);

            node = new ECDiffieHellmanOpenSsl();
            ECParameters node_ep = node.ExportParameters(false);

            pubKey = new PublicKeyCoordinates(node_ep.Q.X, node_ep.Q.Y);

            Console.WriteLine("My hash key: " + HashString.GetHashString(pubKey.ToString()));

            //Console.WriteLine(pubKey.ToString());

            TCPCommunication.send_message_tcp(sslStream, pubKey.ToString());
        }
Exemple #17
0
        public void VerifyDuplicateKey_RefCounts()
        {
            byte[]          derived;
            ECDiffieHellman second;

            using (var first = new ECDiffieHellmanOpenSsl())
                using (SafeEvpPKeyHandle firstHandle = first.DuplicateKeyHandle())
                    using (ECDiffieHellmanPublicKey firstPublic = first.PublicKey)
                    {
                        derived = first.DeriveKeyFromHmac(firstPublic, HashAlgorithmName.SHA384, null);
                        second  = new ECDiffieHellmanOpenSsl(firstHandle);
                    }

            // Now show that second still works, despite first and firstHandle being Disposed.
            using (second)
                using (ECDiffieHellmanPublicKey secondPublic = second.PublicKey)
                {
                    byte[] derived2 = second.DeriveKeyFromHmac(secondPublic, HashAlgorithmName.SHA384, null);
                    Assert.Equal(derived, derived2);
                }
        }
Exemple #18
0
        public void LookupCurveByOidFriendlyName()
        {
            // prime256v1 is alias for nistP256 for OpenSsl
            var ec = new ECDiffieHellmanOpenSsl(ECCurve.CreateFromFriendlyName("prime256v1"));

            ECParameters param = ec.ExportParameters(false);

            param.Validate();
            Assert.Equal(256, ec.KeySize);
            Assert.True(param.Curve.IsNamed);
            Assert.Equal("ECDSA_P256", param.Curve.Oid.FriendlyName); // OpenSsl maps prime256v1 to ECDSA_P256
            Assert.Equal(ECDSA_P256_OID_VALUE, param.Curve.Oid.Value);

            // secp521r1 is same as nistP521; note Windows uses secP521r1 (uppercase P)
            ec    = new ECDiffieHellmanOpenSsl(ECCurve.CreateFromFriendlyName("secp521r1"));
            param = ec.ExportParameters(false);
            param.Validate();
            Assert.Equal(521, ec.KeySize);
            Assert.True(param.Curve.IsNamed);
            Assert.Equal("ECDSA_P521", param.Curve.Oid.FriendlyName); // OpenSsl maps secp521r1 to ECDSA_P521
            Assert.Equal(ECDSA_P521_OID_VALUE, param.Curve.Oid.Value);
        }
Exemple #19
0
 public SendEcDiffieHelman()
 {
     ecDiffieHellman = new ECDiffieHellmanOpenSsl();
     SenderPublicKey = ecDiffieHellman.PublicKey;
 }
 public ReceiveEcDiffieHelman()
 {
     ecDiffieHellman   = new ECDiffieHellmanOpenSsl();
     ReceiverPublicKey = ecDiffieHellman.PublicKey;
 }
        static void req_connection(SslStream sslStream, TcpClient client, string dest_key)
        {
            myAes     = Aes.Create();
            myAes.Key = new byte[16] {
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16
            };
            myAes.IV = new byte[16] {
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
            };

            TCPCommunication.send_message_tcp(sslStream, "CONNECT_P");
            TCPCommunication.send_message_tcp(sslStream, HashString.GetHashString(pubKey.ToString()));

            string response = TCPCommunication.recieve_message_tcp(sslStream);

            if (String.Compare(response, "ACCEPT") == 0)
            {
                TCPCommunication.send_message_tcp(sslStream, dest_key);

                response = TCPCommunication.recieve_message_tcp(sslStream);
                Console.WriteLine(response);

                if (String.Compare(response, "ACCEPT") == 0)
                {
                    response = TCPCommunication.recieve_message_tcp(sslStream);
                    int dtls_port = Int32.Parse(response);


                    byte[] data = new Byte[256];
                    data = Encoding.UTF8.GetBytes(pubKey.ToString());

                    sslStream.Write(data);
                    sslStream.Flush();

                    data = new Byte[256];
                    sslStream.Read(data, 0, data.Length);
                    response = Encoding.UTF8.GetString(data);
                    PublicKeyCoordinates listen_key = JsonConvert.DeserializeObject <PublicKeyCoordinates>(response);



                    sslStream.Close();
                    client.Close();

                    ECDiffieHellmanOpenSsl temp   = new ECDiffieHellmanOpenSsl();
                    ECParameters           epTemp = temp.ExportParameters(false);

                    epTemp.Q.X = listen_key.X;
                    epTemp.Q.Y = listen_key.Y;

                    ECDiffieHellmanPublicKey servePubKey = ECDiffieHellman.Create(epTemp).PublicKey;
                    byte[] sharedKey = node.DeriveKeyMaterial(servePubKey);
                    Console.WriteLine(BitConverter.ToString(sharedKey).Replace("-", ""));
                    //myAes.Key = sharedKey;
                    //myAes.Key = new byte[16] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 };

                    DTLSClient dtls_client = new DTLSClient(server_ip, dtls_port.ToString(), new byte[] { 0xBA, 0xA0 });

                    if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                    {
                        dtls_client.Unbuffer      = "winpty.exe";
                        dtls_client.Unbuffer_Args = "-Xplain -Xallow-non-tty";
                    }
                    else
                    {
                        dtls_client.Unbuffer      = "stdbuf";
                        dtls_client.Unbuffer_Args = "-i0 -o0";
                    }
                    dtls_client.Start();

                    /*statpair IOStream = new statpair(new StreamReader(Console.OpenStandardInput()), new StreamWriter(Console.OpenStandardOutput()));
                     * new Thread(() => dtls_client.GetStream().CopyTo(IOStream, 16)).Start();*/

                    //new Thread(() => read_relay(dtls_client)).Start();

                    UdpClient receivingUdpClient = new UdpClient(32000);

                    //Creates an IPEndPoint to record the IP Address and port number of the sender.
                    // The IPEndPoint will allow you to read datagrams sent from any source.
                    IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);

                    /*Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                     *
                     * IPAddress broadcast = IPAddress.Parse("127.0.0.1");
                     *
                     * //byte[] sendbuf = Encoding.ASCII.GetBytes(args[0]);
                     * IPEndPoint ep = new IPEndPoint(broadcast, 11000);*/

                    dtls_client.GetStream().Write(Encoding.Default.GetBytes("SUCCESS\n"));
                    dtls_client.GetStream().Write(Encoding.Default.GetBytes("SUCCESS\n"));
                    //dtls_client.GetStream().Write(Encoding.Default.GetBytes("SUCCESS"));

                    while (true)
                    {
                        byte[] receiveBytes = receivingUdpClient.Receive(ref RemoteIpEndPoint);
                        //dtls_client.GetStream().Write(receiveBytes);
                        //dtls_client.GetStream().Flush();

                        string input = BitConverter.ToString(receiveBytes) + '\n';
                        //Console.WriteLine(input);

                        byte[] send = Encoding.Default.GetBytes(input);

                        //Console.WriteLine(receiveBytes);
                        dtls_client.GetStream().Write(send);
                        //Thread.Sleep(50);



                        //byte[] rec = Encoding.Default.GetBytes(cut_str);
                        //Console.WriteLine(bytes);

                        //s.SendTo(bytes, ep);

                        //dtls_client.GetStream().Write(Encoding.Default.GetBytes(input));

                        /*string input = Encoding.Default.GetString(receiveBytes);
                         *
                         * byte[] send = Encoding.Default.GetBytes(input);
                         *
                         * s.SendTo(send, ep);*/

                        /*byte[] out_byte = Encoding.Default.GetBytes(input);
                         *
                         * string out_str = Encoding.Default.GetString(out_byte);
                         *
                         * String[] arr=out_str.Split('-');
                         * byte[] bytes=new byte[arr.Length];
                         * for(int i=0; i<arr.Length; i++) bytes[i]=Convert.ToByte(arr[i],16);
                         *
                         * s.SendTo(bytes, ep);*/

                        /*String[] arr=input.Split('-');
                         * byte[] bytes=new byte[arr.Length];
                         * for(int i=0; i<arr.Length; i++) bytes[i]=Convert.ToByte(arr[i],16);*/

                        /*String[] arr_in=input.Split('-');
                         * byte[] array_in=new byte[arr.Length];
                         * for(int i=0; i<arr.Length; i++) array[i]=Convert.ToByte(arr[i],16);
                         *
                         * string out_str = BitConverter.ToString(out_bt);
                         *
                         * String[] arr=out_str.Split('-');
                         * byte[] bytes=new byte[arr.Length];
                         * for(int i=0; i<arr.Length; i++) bytes[i]=Convert.ToByte(arr[i],16);
                         *
                         * //byte[] bytes = BitConverter.GetBytes(input);
                         *
                         * s.SendTo(bytes, ep);*/


                        //string input = BitConverter.ToString(receiveBytes);

                        //byte[] encryptedData = EncryptStringToBytes_Aes(BitConverter.ToString(receiveBytes), myAes.Key, myAes.IV);

                        //dtls_client.GetStream().Write(encryptedData);

                        //dtls_client.GetStream().Write(receiveBytes);
                        //dtls_client.GetStream().Write(bytes);
                        //dtls_client.GetStream().Write();
                    }

                    dtls_client.WaitForExit();
                }
                else if (String.Compare(response, "REJECT") == 0)
                {
                    Console.WriteLine("Connection rejected");
                }
            }
            else if (String.Compare(response, "REJECT") == 0)
            {
                Console.WriteLine("Connection rejected");
                sslStream.Close();
                client.Close();
            }
        }
        static void listen_connection(SslStream sslStream, TcpClient client)
        {
            myAes     = Aes.Create();
            myAes.Key = new byte[16] {
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16
            };
            myAes.IV = new byte[16] {
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
            };


            TCPCommunication.send_message_tcp(sslStream, "LISTEN_P");
            TCPCommunication.send_message_tcp(sslStream, HashString.GetHashString(pubKey.ToString()));

            string response = TCPCommunication.recieve_message_tcp(sslStream);

            if (String.Compare(response, "ACCEPT") == 0)
            {
                byte[] data = new Byte[256];
                data = Encoding.UTF8.GetBytes(pubKey.ToString());
                sslStream.Write(data);
                sslStream.Flush();


                data = new Byte[256];
                sslStream.Read(data, 0, data.Length);
                response = Encoding.UTF8.GetString(data);
                PublicKeyCoordinates request_key = JsonConvert.DeserializeObject <PublicKeyCoordinates>(response);

                sslStream.Close();
                client.Close();

                ECDiffieHellmanOpenSsl temp   = new ECDiffieHellmanOpenSsl();
                ECParameters           epTemp = temp.ExportParameters(false);

                epTemp.Q.X = request_key.X;
                epTemp.Q.Y = request_key.Y;

                ECDiffieHellmanPublicKey servePubKey = ECDiffieHellman.Create(epTemp).PublicKey;
                byte[] sharedKey = node.DeriveKeyMaterial(servePubKey);
                Console.WriteLine(BitConverter.ToString(sharedKey).Replace("-", ""));

                //myAes.Key = sharedKey;
                //myAes.Key = new byte[16] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 };


                DTLSClient dtls_client = new DTLSClient(server_ip, server_port.ToString(), new byte[] { 0xBA, 0xA0 });

                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    dtls_client.Unbuffer      = "winpty.exe";
                    dtls_client.Unbuffer_Args = "-Xplain -Xallow-non-tty";
                }
                else
                {
                    dtls_client.Unbuffer      = "stdbuf";
                    dtls_client.Unbuffer_Args = "-i0 -o0";
                }
                dtls_client.Start();

                /* statpair IOStream = new statpair(new StreamReader(Console.OpenStandardInput()), new StreamWriter(Console.OpenStandardOutput()));
                 * new Thread(() => dtls_client.GetStream().CopyTo(IOStream, 16)).Start();*/

                read_relay(dtls_client);

                /*while(true)
                 * {
                 *  string input = Console.ReadLine();
                 *  byte[] encryptedData = EncryptStringToBytes_Aes(input, myAes.Key, myAes.IV);
                 *  dtls_client.GetStream().Write(encryptedData);
                 *  //dtls_client.GetStream().Write(Encoding.Default.GetBytes(input+Environment.NewLine));
                 * }*/

                dtls_client.WaitForExit();
            }
            else if (String.Compare(response, "REJECT") == 0)
            {
                Console.WriteLine("Connection rejected");
                sslStream.Close();
                client.Close();
            }
        }
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            string systemName = "";
            string clientName = "";

            byte[]     iv         = null;
            byte[]     salt       = null;
            Encryption encryption = Encryption.None;
            string     curveOid   = "";
            string     d          = null;
            string     qx         = "";
            string     qy         = "";
            string     hash       = "";

            while (reader.Read())
            {
                if (reader.TokenType == JsonToken.PropertyName)
                {
                    string propertyName = (string)reader.Value;

                    reader.Read();

                    switch (propertyName)
                    {
                    case nameof(MessageClientIdentity.SystemName):
                        systemName = (string)reader.Value;
                        break;

                    case nameof(MessageClientIdentity.Name):
                        clientName = (string)reader.Value;
                        break;

                    case "IV":
                        iv = Convert.FromBase64String((string)reader.Value);
                        break;

                    case "Salt":
                        salt = Convert.FromBase64String((string)reader.Value);
                        break;

                    case "Encryption":
                        encryption = (Encryption)Enum.Parse(typeof(Encryption), (string)reader.Value);
                        break;

                    case "CurveOid":
                        curveOid = (string)reader.Value;
                        break;

                    case "D":
                        d = (string)reader.Value;
                        break;

                    case "Q.Y":
                        qy = (string)reader.Value;
                        break;

                    case "Q.X":
                        qx = (string)reader.Value;
                        break;

                    case "Hash":
                        hash = (string)reader.Value;
                        break;
                    }
                }
            }

            byte[] privateKey = null;

            if (d != null)
            {
                privateKey = Decrypt(Convert.FromBase64String(d), encryption, iv, salt, _password);
            }

            ECParameters ecParameters = new ECParameters()
            {
                Curve = ECCurve.CreateFromOid(new Oid(curveOid)),
                D     = d == null ? null : privateKey,
                Q     = new ECPoint()
                {
                    X = Convert.FromBase64String(qx),
                    Y = Convert.FromBase64String(qy)
                }
            };

            ECDiffieHellman dh;

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                dh = new ECDiffieHellmanCng();
            }
            else
            {
#if (!NET48)
                dh = new ECDiffieHellmanOpenSsl();
#else
                throw new NotSupportedException("ECDiffieHellmanOpenSsl is not supported in .NET 4.8");
#endif
            }

            dh.ImportParameters(ecParameters);

            var ident = new MessageClientIdentity(systemName, clientName, dh, !string.IsNullOrEmpty(d));

            if (ident.IdentityHash != hash)
            {
                throw new NotImplementedException();
            }

            return(ident);
        }