/// <summary>
        /// Reads this object in from an array, returning how many bytes were read, or 0 if there is an error or not enough data
        /// </summary>
        /// <param name="bData"></param>
        /// <param name="nStartAt"></param>
        /// <returns></returns>
        public uint ReadFromArray(byte[] bData, int nStartAt)
        {
            Certificates.Clear();
            uint nReadSoFar = 0;

            if (bData.Length < (nStartAt + 3))
            {
                return(0);
            }

            CertificatesLength = ByteHelper.ReadUintBigEndian(bData, (int)(nStartAt + nReadSoFar), 3); nReadSoFar += 3;

            if (bData.Length < (nStartAt + nReadSoFar + CertificatesLength))
            {
                return(0);  //not enough data
            }
            int nDataRemaining = (int)CertificatesLength;

            while (nDataRemaining > 0)
            {
                int             nNextByteArrayLength = (int)ByteHelper.ReadUintBigEndian(bData, (int)(nStartAt + nReadSoFar), 3); nReadSoFar += 3;
                byte []         bNextCert            = ByteHelper.ReadByteArray(bData, (int)(nStartAt + nReadSoFar), nNextByteArrayLength); nReadSoFar += (uint)nNextByteArrayLength;
                X509Certificate cert = new X509Certificate(bNextCert);

                Certificates.Add(cert);
                nDataRemaining -= (3 + nNextByteArrayLength);
            }

            return(nReadSoFar);
        }
        /// <summary>
        /// Reads this object in from an array, returning how many bytes were read, or 0 if there is an error or not enough data
        /// </summary>
        /// <param name="bData"></param>
        /// <param name="nStartAt"></param>
        /// <returns></returns>
        public uint ReadFromArray(byte[] bData, int nStartAt)
        {
            if (bData.Length < (nStartAt + 32))
            {
                return(0);
            }

            gmt_unix_time = ByteHelper.ReadUintBigEndian(bData, nStartAt);
            random_bytes  = ByteHelper.ReadByteArray(bData, nStartAt + 4, 28);
            return(32);
        }
        /// <summary>
        /// Reads this object in from an array, returning how many bytes were read, or 0 if there is an error or not enough data
        /// </summary>
        /// <param name="bData"></param>
        /// <param name="nStartAt"></param>
        /// <returns></returns>
        public override uint ReadFromArray(byte[] bData, int nStartAt)
        {
            if (bData.Length < (nStartAt + 4))
            {
                return(0);
            }

            HandShakeMessageType = (HandShakeMessageType)bData[nStartAt + 0];
            MessageLength        = ByteHelper.ReadUintBigEndian(bData, nStartAt + 1, 3); // 24 bits only

            /// See if we have enough data for our message length
            ///
            if (bData.Length < (nStartAt + 4 + MessageLength))
            {
                return(0);
            }

            m_bRawBytes   = ByteHelper.ReadByteArray(bData, nStartAt + 4, (int)MessageLength);
            HandShakeData = m_bRawBytes;// Parse out our sub-message

            return(4 + MessageLength);
        }