Esempio n. 1
0
        public static byte[] GetHash(byte[] input)
        {
            if (null == input)
            {
                throw new System.ArgumentNullException("input", "Unable to calculate hash over null input data");
            }

            //Intitial values defined in RFC 1321
            ABCDStruct abcd = new ABCDStruct();

            abcd.A = 0x67452301;
            abcd.B = 0xefcdab89;
            abcd.C = 0x98badcfe;
            abcd.D = 0x10325476;

            //We pass in the input array by block, the final block of data must be handled specialy for padding & length embeding
            int startIndex = 0;

            while (startIndex <= input.Length - 64)
            {
                MD5Core.GetHashBlock(input, ref abcd, startIndex);
                startIndex += 64;
            }
            // The final data block.
            return(MD5Core.GetHashFinalBlock(input, startIndex, input.Length - startIndex, abcd, (Int64)input.Length * 8));
        }
Esempio n. 2
0
        /// <summary>
        /// Computes the hash value for the specified byte array.
        /// </summary>
        /// <param name="buffer">The input to compute the hash code for.</param>
        /// <returns>
        /// The computed hash code
        /// </returns>
        public byte[] ComputeHash(byte[] buffer)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException("buffer", "The input cannot be null.");
            }

            return(MD5Core.GetHash(this.Combine(this.m_outer, MD5Core.GetHash(this.Combine(this.m_inner, buffer)))));
        }
Esempio n. 3
0
        /// <summary>
        /// Initializes the key.
        /// </summary>
        /// <param name="key">The key.</param>
        private void InitializeKey(byte[] key)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key", "The Key cannot be null.");
            }

            if (key.Length > BLOCK_SIZE)
            {
                this.m_Key = MD5Core.GetHash(key);
            }
            else
            {
                this.m_Key = key;
            }

            this.UpdateIOPadBuffers();
        }
Esempio n. 4
0
        public static void GenerateStuff()
        {
            string strPreMasterSecret = "03 01 7B 4C D6 CC FA A3 B6 52 1B 8B 46 92 25 3D F3 C1 1A F7 9E 99 95 B3 3E 96 B3 F7 90 B4 8D 6E B4 7A 46 C2 F8 7D 71 FE 32 19 E6 96 58 19 3E 78";
            string strClientRandom    = "4f 1b a0 34 2b f8 ad ba f4 97 4c 39 0f e1 e1 dd 4a a9 b1 af 39 f2 e4 25 ad 27 b0 ce a1 43 c4 49";
            string strServerRandom    = "4f 1b a0 6b 88 c1 1a 57 96 dd 83 79 aa ab 4f 99 0c c8 e2 31 74 9a af 16 a1 46 c7 da 88 d6 27 b5";

            byte[] bPreMasterSecret = ByteHelper.ByteFromHexString(strPreMasterSecret);
            byte[] bClientRandom    = ByteHelper.ByteFromHexString(strClientRandom);
            byte[] bServerRandom    = ByteHelper.ByteFromHexString(strServerRandom);

            xmedianet.socketserver.TLS.ConnectionState trans = new xmedianet.socketserver.TLS.ConnectionState();

            ByteBuffer buf = new ByteBuffer();

            buf.AppendData(bClientRandom);
            buf.AppendData(bServerRandom);
            byte[] bCSRandom = buf.GetAllSamples();

            // Do it in reverse order for different algorithms
            buf.AppendData(bServerRandom);
            buf.AppendData(bClientRandom);
            byte[] bSCRandom = buf.GetAllSamples();


            byte[] MasterSecret = trans.PRF(bPreMasterSecret, "master secret", bCSRandom, 48);
            System.Diagnostics.Debug.WriteLine("Master Secret found is:\r\n{0}", ByteHelper.HexStringFromByte(MasterSecret, true, 16));
/// check... our master secret calulation matches what we see in wireshark, so all is well up to this point

            trans.SecurityParameters.Cipher = Cipher.FindCipher(CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA);
            trans.ComputeKeys(MasterSecret, bSCRandom);


            string strClientHello = "0100003103014f1ba0342bf8adbaf4974c390fe1e1dd4aa9b1af39f2e425ad27b0cea143c449000004002f00ff0100000400230000";
            string strServerHello = "0200003103014f1ba06b88c11a5796dd8379aaab4f990cc8e231749aaf16a146c7da88d627b500002f000009ff0100010000230000";
            string strServerCert  = "0b00029a00029700029430820290308201f9a00302010202090086c664416cd7cd31300d06092a864886f70d01010505003061310b3009060355040613025553310b300906035504080c025458310f300d06035504070c0644616c6c61733121301f060355040a0c18496e7465726e6574205769646769747320507479204c74643111300f06035504030c086d656c6c6c766172301e170d3132303132313138343235385a170d3132303232303138343235385a3061310b3009060355040613025553310b300906035504080c025458310f300d06035504070c0644616c6c61733121301f060355040a0c18496e7465726e6574205769646769747320507479204c74643111300f06035504030c086d656c6c6c76617230819f300d06092a864886f70d010101050003818d0030818902818100b393188b70c857fc0f7511f7322e6f91d2761f335de29c488416d82a091b428d315321cb44c7970a7618f5d6e84b0cdd5dbda847cd819ed98dae5c5dec79994b1ad76989150ca551dcbf6a9876e417558eceb78aa094f8c645a6898270a6402a038ad5e7e90303632455b7a1adf07d02633cb56bada5a1a22a0a8f3d842f40f30203010001a350304e301d0603551d0e0416041456326c3cb4f1d784c483fe7e167b80a67e421b63301f0603551d2304183016801456326c3cb4f1d784c483fe7e167b80a67e421b63300c0603551d13040530030101ff300d06092a864886f70d0101050500038181000e38924f5b9f57562bf95b163d0611b512d458866d4de9db94ce56efab9f198ef81247277612b4758728f4aececb54a122641fa0396792fe3f945d99dbc75de378f381071ae3bb11b53d18235f36cedab94670816b1c0b53f0a62daa0850cc368adadb3335d4bebff111e9fbba76ac5be7175279680ebb62e640927e3f6074fe";
            string strServerDone  = "0e000000";
            string strClientKE    = "1000008200809f6af68a96205955bfa0a8b793cb78720f063ef7c3ef82aa10a4f306bfdd8ace898eb5546b873e7b80a7ec95a817b3acf7cf64b45058deaf498bc270ad2901fd921a566c0ddc68c59225350b89f4289aa6f30cb5944cdebc62ed75a9907aee36687b5882fc4bbe9a571137ea2142a465f5278168319cca1646e33706be614091";

            string strEncryptedHS = "59 09 86 f1 79 de 71 f4 b4 14 b1 ad 1a 70 c0 81 d5 24 32 8b 18 1a c4 a6 63 3a 27 d8 31 ad 54 5f 0d 85 37 a2 0f 6c 7b 9c 4b fc 83 18 e6 88 a6 67";

            ByteBuffer objHandShakeBuffer = new ByteBuffer();

            objHandShakeBuffer.AppendData(ByteHelper.ByteFromHexString(strClientHello));
            objHandShakeBuffer.AppendData(ByteHelper.ByteFromHexString(strServerHello));
            objHandShakeBuffer.AppendData(ByteHelper.ByteFromHexString(strServerCert));
            objHandShakeBuffer.AppendData(ByteHelper.ByteFromHexString(strServerDone));
            objHandShakeBuffer.AppendData(ByteHelper.ByteFromHexString(strClientKE));

            /// Example says handshake has read 976 bytes of data and written 256... let's check with wireshark
            /// Sent: 53 + 134            170
            /// Recv: 53 + 670 + 4        48

            SHA1Managed sha1 = new SHA1Managed();

            byte[]     bAllHandShakeData        = objHandShakeBuffer.GetAllSamples();
            byte[]     bmd5OfHandshakeMessages  = MD5Core.GetHash(bAllHandShakeData);
            byte[]     bsha1OfHandshakeMessages = sha1.ComputeHash(bAllHandShakeData);
            ByteBuffer bSum = new ByteBuffer();

            bSum.AppendData(bmd5OfHandshakeMessages);
            bSum.AppendData(bsha1OfHandshakeMessages);

            byte[] bCombinedHashes = bSum.GetAllSamples();

            /// No use in writing out this debug, only a few of the characters get seen, the rest are dropped
            ///System.Diagnostics.Debug.WriteLine("**** Start all handshake data ****\r\n{0}\r\n**** End all handshake data ****", ByteHelper.HexStringFromByte(bAllHandshakeData, true, 32));
            /// verify_data
            ///     PRF(master_secret, finished_label, MD5(handshake_messages) + SHA-1(handshake_messages)) [0..11];

            TLSHandShakeMessage msgFinished = new TLSHandShakeMessage();

            msgFinished.HandShakeMessageType          = HandShakeMessageType.Finished;
            msgFinished.HandShakeFinished.verify_data = trans.PRF(MasterSecret, "client finished", bCombinedHashes, 12);

            TLSRecord recordFinished = new TLSRecord();

            recordFinished.MajorVersion = 3;
            recordFinished.MinorVersion = 1;
            recordFinished.ContentType  = TLSContentType.Handshake;
            recordFinished.Messages.Add(msgFinished);

            trans.WriteSequenceNumber = 0;
            byte[] bEncryptedGenericBlockCipher = trans.CompressEncryptOutgoingData(recordFinished);

            /// Check.  The value here is the same as strEncryptedHS above
            System.Diagnostics.Debug.WriteLine("Encrypted Client Done is:\r\n{0}", ByteHelper.HexStringFromByte(bEncryptedGenericBlockCipher, true, 16));
        }
Esempio n. 5
0
        public static void GenerateStuff2()
        {
            string strPreMasterSecret = "03 01 9A 04 0E DA 89 8C 97 01 53 0D DE 42 EE CF 69 09 8A D1 99 D2 B8 93 1B DA 4C 01 BA 1C A0 B6 01 B5 5F 5B 7A A0 F5 5B 3C B1 7D 72 96 33 BC DC";
            string strClientRandom    = "4f1c89f895eb17b8419927796ce5b6f20401a6e96262031f0b37a7872665f9ab";
            string strServerRandom    = "4f1c89cd4170867e7a5a2d6daa4e8d01237096c70bf891d7ff650554433b7ba5";

            byte[] bPreMasterSecret = ByteHelper.ByteFromHexString(strPreMasterSecret);
            byte[] bClientRandom    = ByteHelper.ByteFromHexString(strClientRandom);
            byte[] bServerRandom    = ByteHelper.ByteFromHexString(strServerRandom);

            xmedianet.socketserver.TLS.ConnectionState trans = new xmedianet.socketserver.TLS.ConnectionState();

            ByteBuffer buf = new ByteBuffer();

            buf.AppendData(bClientRandom);
            buf.AppendData(bServerRandom);
            byte[] bCSRandom = buf.GetAllSamples();

            // Do it in reverse order for different algorithms
            buf.AppendData(bServerRandom);
            buf.AppendData(bClientRandom);
            byte[] bSCRandom = buf.GetAllSamples();


            byte[] MasterSecret = trans.PRF(bPreMasterSecret, "master secret", bCSRandom, 48);
            System.Diagnostics.Debug.WriteLine("Master Secret found is:\r\n{0}", ByteHelper.HexStringFromByte(MasterSecret, true, 16));
            /// check... our master secret calulation matches what we see in wireshark, so all is well up to this point

            trans.SecurityParameters.Cipher = Cipher.FindCipher(CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA);
            trans.ComputeKeys(MasterSecret, bSCRandom);


            string strClientHello = "0100002903014f1c89f895eb17b8419927796ce5b6f20401a6e96262031f0b37a7872665f9ab000002002f0100";
            string strServerHello = "0200004603014f1c89cd4170867e7a5a2d6daa4e8d01237096c70bf891d7ff650554433b7ba520880100006ddf3cb09c0eb6e40d0167000f03ca81ac58eec4c3c760a70143524d002f00";
            string strServerCert  = "0b0004ba0004b70004b4308204b030820298a003020102021062be99f31b21039a47bcad3b019383c0300d06092a864886f70d0101050500301431123010060355040313096c6f63616c686f7374301e170d3132303130383036303030305a170d3232303131353036303030305a301431123010060355040313096c6f63616c686f737430820222300d06092a864886f70d01010105000382020f003082020a0282020100a0c647622204207c3948269a4338eba9b86e9494e5f18f3f024ef6850da59045f09ec8f55ed13d0407adb0f0eef2ea99c5ff6f2078a47b27a64eab77b4a1a709af8255d2b2bfd859149296dc5d93c91728165d484ec55ded72d34828ad43d782bcb81b4e3966b7cdccc88bb41355b42e0fd3ed8b24dbc99903ffb73d27d2f26bce18dd2712a84105eb6a0f4152e7a01ad7e8f1ad6d32c3b21ca3a0a6206398fbb1ac7e85f4586f5535ff35e693b5094bf7360a7a33fc9c2693087ae5777aa761a1fa016f02c320eacb51ea879f6a1dc078daab3e134bf0ae5bba774c6bdb95efe35ea7f8d8b0736ec2e28369b457b3d1c1522b810c2e7340a61b6a8c830af7c8de8047eb5f4b624d782a41e330d983515118182c6709ff41373f74d601aa5c9cb8c6a940549ab6f1f8ca11c945d17d2625acb7fe8a10109afddb9cd495da1f3e88261a063273344efb865e6d86fb0f6384f97685fb992af866616da81499a3223a2a557849c0507f27932063b73d9d2d47a2725c28dbce7b32f7f85d568142cad7c1a9cb9132a977b6e6c164a16fa0b77af027afc6dfb28a5d9e8a4babccac66e569f74a4689158a299100540230c9fdfcddc4649232e0af348d4f833f0a9344eb8f64b48f572cf9653280c2b26e6ea3fecb214ace7643e61f4c74dc79373505352f22408ed883252628b557ad749c80445d8acbe97cf9395c1897deb30dea850203010001300d06092a864886f70d010105050003820201004089ae88bd71245d1863b96505aa1342047088680f2078ca79b733eb542a4c1c267055de24210adc682f48f4d18d27d06100179a85bba5b21749cb8e71b200fb97c37b3e9ad64c197a4d4b7befdfceb67a69a80a7be24ac4cc6307ea3241f55b6800ecedee86b5fe8a21869cf8653cc0b653b71b5132c51ad2e334c16c1247155e82d744d0fdb9546d5c14bdbd9b8952d575e34335d85bd2c6079cf2adba910f98dc48a51217b617cf78ca91f57fe2b7ff88e2e78f5882530d55d63ec466a9d02e72f2a4269779880c66136a3dac96a26f334771e59cc89f3c66ddf5d21492b5d40565dbfdc0a9833d57c68728e969088612dbe655dc98a4d2449b2cf06208a4f26d831fa4d90eb79ea59d1934e61029a81c4795f28ec91df7b82b8f2ab85783f12e334d98e2313a7829f73630edd47a891de3b241ecf6aa3afd1d6c6e43db1d177a31b306bf7b05fb4fd56f462179e0efc439fa10391ce010c12607336e6379aa192bb106e86eb875a66919cc5a08692aefaebddbd92736f21b2410889530b8ceeded969624e1f9ab08957254d0029b20881f820276ede7987e86d705f88715e21e950e45624add2ee6cb682f2e9ecd37839ccda82290c5b6638981c45270f75a6c786fa734877a560e7d48c8abc122070ae0792a213de33ccfe0456f31e91c3be4833e50463e2a97ce828bbaae8324482bc07181ba7ee50fb87c65be66bb56";
            string strServerDone  = "0e000000";
            string strClientKE    = "1000020202000fab10111b3822b4fd32d0a73046b8d4f605eadf98bbf89bbd6924fea2e545e6ecbf2844f98de744edda195b73a4f10f9d473808697d03b3d34b947256f0f9395d914eb6a570091c559d27100c5897b8d66f4572955bc242f01d9328fe052f1e240aad72dece482aadb5440931d8271db0f59d558392013522f83c2cc9b11db4f654997f0293decd9a1a2ec950cfb2f2264158a7112ad3626fb51b368497fa4d5ef93b637b95b93b533ae9decd26e22d85a5f5d8b8ac1d151e7b11be23ff1cf341d78c42e281a536da9be3e4560a78fa428d9e44ee200504ba4d4146cbd64b5fb0179f8e015e64ccb13c5581119eb953b44f9d7081266d88fcfed08d632297fe2a94a98f2f930c5f8e564b89598e805bc3b143ea0acc1faa0e7d1d0799cb925b0f6d04f3c68b5d0cff0838ec881575b7aece5b481b17f193e9ad559c1426fa5f7407ba80e81b50ab6c5e589335fdb0861d6b351715cde0b13746b664928d640f1883760623ef867c4dd0568ffd08f03837f511abbc2821fe2d676bf2f742eeb50f27fadacbd211649a7889f0b38aedaab331747c424add3a13fe4575fffb120cbdd544b5d353b1dfbf5dd5be16545d70b436fac29fe12942b63a9dae438e0a5d3f3b116b39317161943474c477371001b3be844908799ec44aeab0f82607cf0e0ba86561c1d8a49298a17b6f2733c1340d185d337e349c58526d8407d3b38498";

            string strEncryptedHS = "35275a481265bd929ede8056ed23ad42bebd2da9d8bc841b813ce8fae921b044fb37f03604fec9de92e1873155212143";

            ByteBuffer objHandShakeBuffer = new ByteBuffer();

            objHandShakeBuffer.AppendData(ByteHelper.ByteFromHexString(strClientHello));
            objHandShakeBuffer.AppendData(ByteHelper.ByteFromHexString(strServerHello));
            objHandShakeBuffer.AppendData(ByteHelper.ByteFromHexString(strServerCert));
            objHandShakeBuffer.AppendData(ByteHelper.ByteFromHexString(strServerDone));
            objHandShakeBuffer.AppendData(ByteHelper.ByteFromHexString(strClientKE));

            /// Example says handshake has read 976 bytes of data and written 256... let's check with wireshark
            /// Sent: 53 + 134            170
            /// Recv: 53 + 670 + 4        48

            SHA1Managed sha1 = new SHA1Managed();

            byte[]     bAllHandShakeData        = objHandShakeBuffer.GetAllSamples();
            byte[]     bmd5OfHandshakeMessages  = MD5Core.GetHash(bAllHandShakeData);
            byte[]     bsha1OfHandshakeMessages = sha1.ComputeHash(bAllHandShakeData);
            ByteBuffer bSum = new ByteBuffer();

            bSum.AppendData(bmd5OfHandshakeMessages);
            bSum.AppendData(bsha1OfHandshakeMessages);

            byte[] bCombinedHashes = bSum.GetAllSamples();

            /// No use in writing out this debug, only a few of the characters get seen, the rest are dropped
            ///System.Diagnostics.Debug.WriteLine("**** Start all handshake data ****\r\n{0}\r\n**** End all handshake data ****", ByteHelper.HexStringFromByte(bAllHandshakeData, true, 32));
            /// verify_data
            ///     PRF(master_secret, finished_label, MD5(handshake_messages) + SHA-1(handshake_messages)) [0..11];

            TLSHandShakeMessage msgFinished = new TLSHandShakeMessage();

            msgFinished.HandShakeMessageType          = HandShakeMessageType.Finished;
            msgFinished.HandShakeFinished.verify_data = trans.PRF(MasterSecret, "client finished", bCombinedHashes, 12);

            TLSRecord recordFinished = new TLSRecord();

            recordFinished.MajorVersion = 3;
            recordFinished.MinorVersion = 1;
            recordFinished.ContentType  = TLSContentType.Handshake;
            recordFinished.Messages.Add(msgFinished);

            trans.WriteSequenceNumber = 0;
            byte[] bEncryptedGenericBlockCipher = trans.CompressEncryptOutgoingData(recordFinished);

            /// Check.  The value here is the same as strEncryptedHS above
            System.Diagnostics.Debug.WriteLine("Encrypted Client Done is:\r\n{0}", ByteHelper.HexStringFromByte(bEncryptedGenericBlockCipher, true, 16));
        }
Esempio n. 6
0
        void HandleHandshakeMessage(TLSHandShakeMessage msg)
        {
            /// Append all our handshake data because we'll need it later for some stupid reason

            if (msg.HandShakeMessageType == HandShakeMessageType.ServerHello)
            {
                ClientTLSState = TLS.ClientTLSState.ReceivedServerHello;
            }
            else if (msg.HandShakeMessageType == HandShakeMessageType.ServerHelloDone)
            {
                if (m_bSendClientCertificate == true) /// got a certificate request from the server, but we don't have any, so send an empty one
                {
                    TLSHandShakeMessage msgclientcert = new TLSHandShakeMessage();
                    msgclientcert.HandShakeMessageType = HandShakeMessageType.Certificate;
                    TLSRecord recordclientcert = new TLSRecord();
                    recordclientcert.MajorVersion = 3;
                    recordclientcert.MinorVersion = 1;
                    recordclientcert.ContentType  = TLSContentType.Handshake;
                    recordclientcert.Messages.Add(msgclientcert);

                    SendTLSRecord(recordclientcert, true);
                }

                /// Server has sent the algorithm they want us to use, certificates, parameters,
                /// and any request for certificates from us.  Now let's respond
                /// First generate, encrypt, and send the PreMasterSecret

                byte [] bKey             = state.SecurityParameters.PeerCertificate.GetPublicKey();
                byte [] bPreMasterSecret = new byte[48];
                RNGCryptoServiceProvider.GetBytes(bPreMasterSecret); /// Get some random bytes
                bPreMasterSecret[0] = 0x03;                          /// first two bytes get set to the version
                bPreMasterSecret[1] = 0x01;

                /// Openssl is showing our modulus as having an extra 00 on the front when using this command
                /// (ignore this, the modulus lower in the output doesn't show the 0)
                /// rsa -in test_key.pem -text

                if (SocketClient.ShowDebug == true)
                {
                    System.Diagnostics.Debug.WriteLine("Client Random: +++++++++++\r\n{0}\r\n++++++++++++", ByteHelper.HexStringFromByte(state.SecurityParameters.ClientRandom, true, 16));
                    System.Diagnostics.Debug.WriteLine("Server Random: +++++++++++\r\n{0}\r\n++++++++++++", ByteHelper.HexStringFromByte(state.SecurityParameters.ServerRandom, true, 16));
                    System.Diagnostics.Debug.WriteLine("PreMasterSecret: +++++++++++\r\n{0}\r\n++++++++++++", ByteHelper.HexStringFromByte(bPreMasterSecret, true, 16));
                }

                RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
                // Need to use this guys' class to parse the DER encoded ASN.1 described certificate to
                // extract the modulus and e from the certificate - these two are the public key
                RSAParameters rsaparams = Kishore.X509.Parser.X509PublicKeyParser.GetRSAPublicKeyParameters(bKey);
                provider.ImportParameters(rsaparams);

                //System.Diagnostics.Debug.WriteLine("Public key modulus: +++++++++++\r\n{0}\r\n++++++++++++", ByteHelper.HexStringFromByte(rsaparams.Modulus, true, 16));
                //System.Diagnostics.Debug.WriteLine("Public key exponent: +++++++++++\r\n{0}\r\n++++++++++++", ByteHelper.HexStringFromByte(rsaparams.Exponent, true, 16));
                //System.Diagnostics.Debug.WriteLine("Key Exchange Algorithm: {0}, KeySize: {1}", provider.KeyExchangeAlgorithm, provider.KeySize);
                byte[] EncryptedPreMasterSecret = provider.Encrypt(bPreMasterSecret, false);
                provider.Dispose();

                /// Send a Client Key Exchange method with our PreMasterSecret
                ///
                TLSHandShakeMessage msgsend = new TLSHandShakeMessage();
                msgsend.HandShakeMessageType = HandShakeMessageType.ClientKeyExchange;
                msgsend.HandShakeClientKeyExchange.EncryptedPreMasterSecret = EncryptedPreMasterSecret;
                msgsend.HandShakeClientKeyExchange.KeyExchangeAlgorithm     = KeyExchangeAlgorithm.rsa;
                msgsend.HandShakeClientKeyExchange.PublicValueEncoding      = PublicValueEncoding.explicit_en;
                TLSRecord record = new TLSRecord();
                record.MajorVersion = 3;
                record.MinorVersion = 1;
                record.ContentType  = TLSContentType.Handshake;
                record.Messages.Add(msgsend);

                SendTLSRecord(record, true);



                /// Now generate all our keys, etc
                /// Section 8.1
                /// master_secret = PRF(pre_master_secret, "master secret",ClientHello.random + ServerHello.random) [0..47];

                // Combine ClientHello.Random and ServerHello.Random
                ByteBuffer buf = new ByteBuffer();
                buf.AppendData(state.SecurityParameters.ClientRandom);
                buf.AppendData(state.SecurityParameters.ServerRandom);
                byte [] bCSRandom = buf.GetAllSamples();

                // Do it in reverse order for different algorithms
                buf.AppendData(state.SecurityParameters.ServerRandom);
                buf.AppendData(state.SecurityParameters.ClientRandom);
                byte [] bSCRandom = buf.GetAllSamples();

                state.SecurityParameters.MasterSecret = state.PRF(bPreMasterSecret, "master secret", bCSRandom, 48);

                if (SocketClient.ShowDebug == true)
                {
                    System.Diagnostics.Debug.WriteLine("MasterSecret: +++++++++++\r\n{0}\r\n++++++++++++", ByteHelper.HexStringFromByte(state.SecurityParameters.MasterSecret, true, 16));
                }

                /// Verified that we are computing all our keys correctly by using the same input into the Mentalis library
                /// If we coded ours independently and get the same answers, it has to be correct, or we made the same mistakes :)
                state.ComputeKeys(state.SecurityParameters.MasterSecret, bSCRandom);



                /// Now send out a change cipher-spec, followed by a client finished message that is encrypted
                ///
                TLSChangeCipherSpecMessage msgChangeCipherSpec = new TLSChangeCipherSpecMessage();
                msgChangeCipherSpec.CCSProtocolType = CCSProtocolType.Default;
                TLSRecord recordccs = new TLSRecord();
                recordccs.MajorVersion = 3;
                recordccs.MinorVersion = 1;
                recordccs.ContentType  = TLSContentType.ChangeCipherSpec;
                recordccs.Messages.Add(msgChangeCipherSpec);
                SendTLSRecord(recordccs, false);

                state.SendEncryptionActive = true;
                state.WriteSequenceNumber  = 0; /// reset on changecipherspec

                /// Now send a finished method, encrypted with our generated things
                /// RFC2246 section 7.4.9

                if (SocketClient.ShowDebug == true)
                {
                    System.Diagnostics.Debug.WriteLine("FINAL:  AllHandShakeMessages Length is now {0}", AllHandShakeMessages.Size);
                }

                SHA1Managed sha1 = new SHA1Managed();
                byte[]      bAllHandshakeData        = AllHandShakeMessages.PeekAllSamples();
                byte[]      bmd5OfHandshakeMessages  = MD5Core.GetHash(bAllHandshakeData);
                byte[]      bsha1OfHandshakeMessages = sha1.ComputeHash(bAllHandshakeData);
                ByteBuffer  bSum = new ByteBuffer();
                bSum.AppendData(bmd5OfHandshakeMessages);
                bSum.AppendData(bsha1OfHandshakeMessages);

                byte [] bCombinedHashes = bSum.GetAllSamples();

                /// No use in writing out this debug, only a few of the characters get seen, the rest are dropped
                ///System.Diagnostics.Debug.WriteLine("**** Start all handshake data ****\r\n{0}\r\n**** End all handshake data ****", ByteHelper.HexStringFromByte(bAllHandshakeData, true, 32));
                /// verify_data
                ///     PRF(master_secret, finished_label, MD5(handshake_messages) + SHA-1(handshake_messages)) [0..11];

                TLSHandShakeMessage msgFinished = new TLSHandShakeMessage();
                msgFinished.HandShakeMessageType          = HandShakeMessageType.Finished;
                msgFinished.HandShakeFinished.verify_data = state.PRF(state.SecurityParameters.MasterSecret, "client finished", bCombinedHashes, 12);

                TLSRecord recordFinished = new TLSRecord();
                recordFinished.MajorVersion = 3;
                recordFinished.MinorVersion = 1;
                recordFinished.ContentType  = TLSContentType.Handshake;
                recordFinished.Messages.Add(msgFinished);

                state.WriteSequenceNumber = 0;
                /// This record must now be encrypted before it can be sent
                SendTLSRecord(recordFinished, true);


                ClientTLSState = ClientTLSState.SentClientFinished;
            }
            else if (msg.HandShakeMessageType == HandShakeMessageType.Finished)
            {
                /// Got the server finished method, let's verify the data
                ///
                SHA1Managed sha1 = new SHA1Managed();
                byte[]      bAllHandshakeData        = AllHandShakeMessages.GetAllSamples(); // no need to peek here, just get it all and clear it
                byte[]      bmd5OfHandshakeMessages  = MD5Core.GetHash(bAllHandshakeData);
                byte[]      bsha1OfHandshakeMessages = sha1.ComputeHash(bAllHandshakeData);
                ByteBuffer  bSum = new ByteBuffer();
                bSum.AppendData(bmd5OfHandshakeMessages);
                bSum.AppendData(bsha1OfHandshakeMessages);

                byte[] bCombinedHashes = bSum.GetAllSamples();

                /// No use in writing out this debug, only a few of the characters get seen, the rest are dropped
                ///System.Diagnostics.Debug.WriteLine("**** Start all handshake data ****\r\n{0}\r\n**** End all handshake data ****", ByteHelper.HexStringFromByte(bAllHandshakeData, true, 32));
                /// verify_data
                ///     PRF(master_secret, finished_label, MD5(handshake_messages) + SHA-1(handshake_messages)) [0..11];

                byte [] bComputedVerify = state.PRF(state.SecurityParameters.MasterSecret, "server finished", bCombinedHashes, 12);
                bool    bMatch          = ByteHelper.CompareArrays(msg.HandShakeFinished.verify_data, bComputedVerify);
                if (bMatch == false)
                {
                    SendAlert(AlertLevel.fatal, AlertDescription.HandshakeFailure);
                    Client.Disconnect();
                }
                else
                {
                    NegotiationFinished();
                }
            }
            else if (msg.HandShakeMessageType == HandShakeMessageType.CertificateRequest)
            {
                m_bSendClientCertificate = true;
            }



            if (ClientTLSState == TLS.ClientTLSState.ReceivedServerHello)
            {
                /// Gathering information
                ///
                if (msg.HandShakeMessageType == HandShakeMessageType.ServerHello)
                {
                    state.SecurityParameters.Cipher            = Cipher.FindCipher(msg.HandShakeServerHello.CipherSuite);
                    state.SecurityParameters.CompressionMethod = CompressionMethod.null0;
                    state.SecurityParameters.ConnectionEnd     = ConnectionEnd.client;
                    state.SecurityParameters.ServerRandom      = msg.HandShakeServerHello.RandomStruct.Bytes;
                }
                else if (msg.HandShakeMessageType == HandShakeMessageType.Certificate)
                {
                    if (msg.HandShakeCertificateMessage.Certificates.Count > 0)
                    {
                        state.SecurityParameters.PeerCertificate = msg.HandShakeCertificateMessage.Certificates[0];
                    }
                }
            }
        }