public bool SendPacket(Packet packet, uint dwIP, ushort nPort, bool bEncrypt,
                               byte[] pachTargetClientHashORKadID, bool bKad, uint nReceiverVerifyKey)
        {
            UDPPack newpending = new UDPPack();

            newpending.dwIP     = dwIP;
            newpending.nPort    = nPort;
            newpending.packet   = packet;
            newpending.dwTime   = MpdUtilities.GetTickCount();
            newpending.bEncrypt =
                bEncrypt &&
                (pachTargetClientHashORKadID != null ||
                 (bKad && nReceiverVerifyKey != 0));
            newpending.bKad = bKad;
            newpending.nReceiverVerifyKey = nReceiverVerifyKey;

            if (newpending.bEncrypt && pachTargetClientHashORKadID != null)
            {
                MpdUtilities.Md4Cpy(newpending.pachTargetClientHashORKadID, pachTargetClientHashORKadID);
            }
            else
            {
                MpdUtilities.Md4Clr(newpending.pachTargetClientHashORKadID);
            }
            lock (sendLocker_)
            {
                controlpacketQueue_.Add(newpending);
            }// sendLocker.Unlock();

            MuleApplication.Instance.UploadBandwidthThrottler.QueueForSendingControlPacket(this);
            return(true);
        }
Beispiel #2
0
 public DeadSource(byte[] paucHash)
 {
     id_       = 0;
     serverIP_ = 0;
     port_     = 0;
     kadPort_  = 0;
     MpdUtilities.Md4Cpy(hash_, paucHash);
 }
Beispiel #3
0
 public DeadSource(DeadSource ds)
 {
     id_       = ds.id_;
     serverIP_ = ds.serverIP_;
     port_     = ds.port_;
     kadPort_  = ds.kadPort_;
     MpdUtilities.Md4Cpy(hash_, ds.hash_);
 }
Beispiel #4
0
 public ClientCreditsImpl(byte[] key)
 {
     credits_ = new CreditStruct();
     MpdUtilities.Md4Cpy(credits_.abyKey, key);
     InitalizeIdent();
     unSecureWaitTime_ = MpdUtilities.GetTickCount();
     secureWaitTime_   = MpdUtilities.GetTickCount();
     waitTimeIP_       = 0;
 }
Beispiel #5
0
 public MapSKey(byte[] key)
 {
     if (key != null)
     {
         MpdUtilities.Md4Cpy(key_, key);
     }
     else
     {
         MpdUtilities.Md4Clr(key_);
     }
 }
Beispiel #6
0
        public void SetConnectionEncryption(bool bEnabled, byte[] pTargetClientHash, bool bServerConnection)
        {
            if (streamCryptState_ != StreamCryptStateEnum.ECS_UNKNOWN &&
                streamCryptState_ != StreamCryptStateEnum.ECS_NONE)
            {
                if (!(streamCryptState_ == StreamCryptStateEnum.ECS_NONE) || bEnabled)
                {
                    Debug.Assert(false);
                }
                return;
            }

            Debug.Assert(rc4SendKey_ == null);
            Debug.Assert(rc4ReceiveKey_ == null);

            if (bEnabled && pTargetClientHash != null && !bServerConnection)
            {
                streamCryptState_ = StreamCryptStateEnum.ECS_PENDING;
                // create obfuscation keys, see on top for key format

                // use the crypt random generator
                randomKeyPart_ = MpdUtilities.GetRandomUInt32();

                byte[] achKeyData = new byte[21];
                MpdUtilities.Md4Cpy(achKeyData, pTargetClientHash);

                Array.Copy(BitConverter.GetBytes(randomKeyPart_), 0, achKeyData, 17, 4);

                achKeyData[16] = Convert.ToByte(MuleConstants.MAGICVALUE_REQUESTER);

                MD5 md5 = MD5.Create();

                rc4SendKey_ = MuleUtilities.RC4CreateKey(md5.ComputeHash(achKeyData), 16);

                achKeyData[16] = Convert.ToByte(MuleConstants.MAGICVALUE_SERVER);

                rc4ReceiveKey_ = MuleUtilities.RC4CreateKey(md5.ComputeHash(achKeyData), 16);
            }
            else if (bServerConnection && bEnabled)
            {
                serverCrypt_      = true;
                streamCryptState_ = StreamCryptStateEnum.ECS_PENDING_SERVER;
            }
            else
            {
                Debug.Assert(!bEnabled);
                streamCryptState_ = StreamCryptStateEnum.ECS_NONE;
            }
        }
Beispiel #7
0
        public FileIdentifierImpl(FileIdentifier rFileIdentifier, ulong rFileSize)
            : base(rFileIdentifier)
        {
            m_rFileSize = rFileSize;

            for (int i = 0; i < rFileIdentifier.RawMD4HashSet.Count; i++)
            {
                byte[] pucHashSetPart = new byte[16];
                MpdUtilities.Md4Cpy(pucHashSetPart, rFileIdentifier.RawMD4HashSet[i]);
                m_aMD4HashSet.Add(pucHashSetPart);
            }

            for (int i = 0; i < rFileIdentifier.RawAICHHashSet.Count; i++)
            {
                m_aAICHPartHashSet.Add(rFileIdentifier.RawAICHHashSet[i]);
            }
        }
Beispiel #8
0
        public bool LoadMD4HashsetFromFile(Mpd.Generic.IO.FileDataIO file, bool bVerifyExistingHash)
        {
            byte[] checkid = new byte[16];
            file.ReadHash16(checkid);
            DeleteMD4Hashset();

            uint parts = file.ReadUInt16();

            //TRACE("Nr. hashs: %u\n", (uint)parts);
            if (bVerifyExistingHash &&
                (MpdUtilities.Md4Cmp(MD4Hash, checkid) != 0 ||
                 parts != TheoreticalMD4PartHashCount))
            {
                return(false);
            }
            for (uint i = 0; i < parts; i++)
            {
                byte[] cur_hash = new byte[16];
                file.ReadHash16(cur_hash);
                m_aMD4HashSet.Add(cur_hash);
            }

            if (!bVerifyExistingHash)
            {
                MpdUtilities.Md4Cpy(MD4Hash, checkid);
            }

            // Calculate hash out of hashset and compare to existing filehash
            if (m_aMD4HashSet.Count > 0)
            {
                return(CalculateMD4HashByHashSet(true, true));
            }
            else
            {
                return(true);
            }
        }
Beispiel #9
0
        public bool CalculateMD4HashByHashSet(bool bVerifyOnly, bool bDeleteOnVerifyFail)
        {
            if (m_aMD4HashSet.Count <= 1)
            {
                return(false);
            }
            byte[] buffer = new byte[m_aMD4HashSet.Count * 16];
            for (int i = 0; i < m_aMD4HashSet.Count; i++)
            {
                MpdUtilities.Md4Cpy(buffer, i * 16, m_aMD4HashSet[i], 0, m_aMD4HashSet[i].Length);
            }
            byte[]    aucResult = new byte[16];
            KnownFile knownFile = MuleApplication.Instance.FileObjectManager.CreateKnownFile();

            knownFile.CreateHash(buffer, (ulong)m_aMD4HashSet.Count * 16, aucResult);
            if (bVerifyOnly)
            {
                if (MpdUtilities.Md4Cmp(aucResult, MD4Hash) != 0)
                {
                    if (bDeleteOnVerifyFail)
                    {
                        DeleteMD4Hashset();
                    }
                    return(false);
                }
                else
                {
                    return(true);
                }
            }
            else
            {
                MpdUtilities.Md4Cpy(MD4Hash, aucResult);
                return(true);
            }
        }
Beispiel #10
0
        public bool InitFromLink(string sLink)
        {
            ED2KLink     pLink     = null;
            ED2KFileLink pFileLink = null;

            try
            {
                pLink = MuleApplication.Instance.ED2KObjectManager.CreateLinkFromUrl(sLink);
                if (pLink == null)
                {
                    throw new Exception("Not a Valid file link:" + sLink);
                }

                pFileLink = pLink.FileLink;
                if (pFileLink == null)
                {
                    throw new Exception("Not a Valid file link:" + sLink);
                }
            }
            catch (Exception)
            {
                //TODO:Log
                return(false);
            }

            tagList_.Add(MpdObjectManager.CreateTag(MuleConstants.FT_FILEHASH, pFileLink.HashKey));
            MpdUtilities.Md4Cpy(FileHash, pFileLink.HashKey);

            tagList_.Add(MpdObjectManager.CreateTag(MuleConstants.FT_FILESIZE, pFileLink.Size, true));
            FileSize = pFileLink.Size;

            tagList_.Add(MpdObjectManager.CreateTag(MuleConstants.FT_FILENAME, pFileLink.Name));
            SetFileName(pFileLink.Name, false, false, false);

            return(true);
        }
Beispiel #11
0
 public MapSKey(MapSKey key)
 {
     MpdUtilities.Md4Cpy(key_, key.key_);
 }
        public virtual int DecryptReceivedClient(byte[] pbyBufIn, int nBufLen,
                                                 out byte[] ppbyBufOut, uint dwIP, out uint nReceiverVerifyKey, out uint nSenderVerifyKey)
        {
            int nResult = nBufLen;

            ppbyBufOut         = pbyBufIn;
            nReceiverVerifyKey = 0;
            nSenderVerifyKey   = 0;

            if (nResult <= CRYPT_HEADER_WITHOUTPADDING /*|| !MuleApplication.Instance.Preference.IsClientCryptLayerSupported()*/)
            {
                return(nResult);
            }

            switch (pbyBufIn[0])
            {
            case MuleConstants.PROTOCOL_EMULEPROT:
            case MuleConstants.PROTOCOL_KADEMLIAPACKEDPROT:
            case MuleConstants.PROTOCOL_KADEMLIAHEADER:
            case MuleConstants.PROTOCOL_UDPRESERVEDPROT1:
            case MuleConstants.PROTOCOL_UDPRESERVEDPROT2:
            case MuleConstants.PROTOCOL_PACKEDPROT:
                return(nResult);    // no encrypted packet (see description on top)
            }

            // might be an encrypted packet, try to decrypt
            RC4Key keyReceiveKey = null;
            uint   dwValue       = 0;
            // check the marker bit which type this packet could be and which key to test first, this is only an indicator since old clients have it set random
            // see the header for marker bits explanation
            byte byCurrentTry = (byte)(((pbyBufIn[0] & 0x03) == 3) ? 1 : (pbyBufIn[0] & 0x03));
            byte byTries;

            if (MuleApplication.Instance.KadEngine.Preference == null)
            {
                // if kad never run, no point in checking anything except for ed2k encryption
                byTries      = 1;
                byCurrentTry = 1;
            }
            else
            {
                byTries = 3;
            }
            bool bKadRecvKeyUsed = false;
            bool bKad            = false;

            do
            {
                byTries--;
                MD5    md5     = MD5.Create();
                byte[] rawHash = null;
                if (byCurrentTry == 0)
                {
                    // kad packet with NodeID as key
                    bKad            = true;
                    bKadRecvKeyUsed = false;
                    if (MuleApplication.Instance.KadEngine.Preference != null)
                    {
                        byte[] achKeyData = new byte[18];
                        Array.Copy(MuleApplication.Instance.KadEngine.Preference.KadID.Bytes, 0, achKeyData, 0, 16);
                        Array.Copy(pbyBufIn, 1, achKeyData, 16, 2); // random key part sent from remote client
                        rawHash = md5.ComputeHash(achKeyData);
                    }
                }
                else if (byCurrentTry == 1)
                {
                    // ed2k packet
                    bKad            = false;
                    bKadRecvKeyUsed = false;
                    byte[] achKeyData = new byte[23];
                    MpdUtilities.Md4Cpy(achKeyData, MuleApplication.Instance.Preference.UserHash);
                    achKeyData[20] = MAGICVALUE_UDP;
                    Array.Copy(BitConverter.GetBytes(dwIP), 0, achKeyData, 16, 4);
                    Array.Copy(pbyBufIn, 1, achKeyData, 21, 2); // random key part sent from remote client
                    rawHash = md5.ComputeHash(achKeyData);
                }
                else if (byCurrentTry == 2)
                {
                    // kad packet with ReceiverKey as key
                    bKad            = true;
                    bKadRecvKeyUsed = true;
                    if (MuleApplication.Instance.KadEngine.Preference != null)
                    {
                        byte[] achKeyData = new byte[6];
                        Array.Copy(BitConverter.GetBytes(MuleApplication.Instance.KadEngine.Preference.GetUDPVerifyKey(dwIP)),
                                   achKeyData, 4);
                        Array.Copy(pbyBufIn, 1, achKeyData, 4, 2); // random key part sent from remote client
                        rawHash = md5.ComputeHash(achKeyData);
                    }
                }
                else
                {
                    Debug.Assert(false);
                }

                MuleUtilities.RC4CreateKey(rawHash, 16, ref keyReceiveKey, true);
                byte[] outBuf = new byte[4];
                MuleUtilities.RC4Crypt(pbyBufIn, 3, outBuf, 0, 4, keyReceiveKey);
                dwIP         = BitConverter.ToUInt32(outBuf, 0);
                byCurrentTry = (byte)((byCurrentTry + 1) % 3);
            } while (dwValue != MAGICVALUE_UDP_SYNC_CLIENT && byTries > 0); // try to decrypt as ed2k as well as kad packet if needed (max 3 rounds)

            if (dwValue == MAGICVALUE_UDP_SYNC_CLIENT)
            {
                // yup this is an encrypted packet
                // debugoutput notices
                // the following cases are "allowed" but shouldn't happen given that there is only our implementation yet
                if (bKad && (pbyBufIn[0] & 0x01) != 0)
                {
                    MpdUtilities.DebugLog(
                        string.Format("Received obfuscated UDP packet from clientIP: {0} with wrong key marker bits (kad packet, ed2k bit)", MpdUtilities.IP2String(dwIP)));
                }
                else if (bKad && !bKadRecvKeyUsed && (pbyBufIn[0] & 0x02) != 0)
                {
                    MpdUtilities.DebugLog(
                        string.Format("Received obfuscated UDP packet from clientIP: {0} with wrong key marker bits (kad packet, nodeid key, recvkey bit)", MpdUtilities.IP2String(dwIP)));
                }
                else if (bKad && bKadRecvKeyUsed && (pbyBufIn[0] & 0x02) == 0)
                {
                    MpdUtilities.DebugLog(
                        string.Format("Received obfuscated UDP packet from clientIP: {0} with wrong key marker bits (kad packet, recvkey key, nodeid bit)", MpdUtilities.IP2String(dwIP)));
                }

                byte   byPadLen;
                byte[] outBuf = new byte[1];
                MuleUtilities.RC4Crypt(pbyBufIn, 7, outBuf, 0, 1, keyReceiveKey);
                byPadLen = outBuf[0];

                nResult -= CRYPT_HEADER_WITHOUTPADDING;
                if (nResult <= byPadLen)
                {
                    MpdUtilities.DebugLogError(
                        string.Format("Invalid obfuscated UDP packet from clientIP: {0}, Paddingsize ({1}) larger than received bytes",
                                      MpdUtilities.IP2String(dwIP), byPadLen));
                    return(nBufLen); // pass through, let the Receivefunction do the errorhandling on this junk
                }
                if (byPadLen > 0)
                {
                    MuleUtilities.RC4Crypt(null, null, byPadLen, keyReceiveKey);
                }
                nResult -= byPadLen;

                if (bKad)
                {
                    if (nResult <= 8)
                    {
                        MpdUtilities.DebugLogError(
                            string.Format("Obfuscated Kad packet with mismatching size (verify keys missing) received from clientIP: {0}",
                                          MpdUtilities.IP2String(dwIP)));
                        return(nBufLen); // pass through, let the Receivefunction do the errorhandling on this junk;
                    }
                    // read the verify keys
                    outBuf = new byte[4];
                    MuleUtilities.RC4Crypt(pbyBufIn, (int)(CRYPT_HEADER_WITHOUTPADDING + byPadLen),
                                           outBuf, 0, 4, keyReceiveKey);
                    nReceiverVerifyKey = BitConverter.ToUInt32(outBuf, 0);
                    MuleUtilities.RC4Crypt(pbyBufIn, (int)(CRYPT_HEADER_WITHOUTPADDING + byPadLen + 4),
                                           outBuf, 0, 4, keyReceiveKey);
                    nSenderVerifyKey = BitConverter.ToUInt32(outBuf, 0);
                    nResult         -= 8;
                }

                ppbyBufOut = new byte[nResult];
                Array.Copy(pbyBufIn, (nBufLen - nResult), ppbyBufOut, 0, nResult);

                MuleUtilities.RC4Crypt(ppbyBufOut, ppbyBufOut, (uint)nResult, keyReceiveKey);
                MuleApplication.Instance.Statistics.AddDownDataOverheadCrypt((uint)(nBufLen - nResult));
                //DEBUG_ONLY( MpdUtilities.DebugLog(("Received obfuscated UDP packet from clientIP: %s, Key: %s, RKey: %u, SKey: %u"), MpdUtilities.IP2String(dwIP), bKad ? (bKadRecvKeyUsed ? ("ReceiverKey") : ("NodeID")) : ("UserHash")
                //	, nReceiverVerifyKey != 0 ? *nReceiverVerifyKey : 0, nSenderVerifyKey != 0 ? *nSenderVerifyKey : 0) );
                return(nResult); // done
            }
            else
            {
                MpdUtilities.DebugLogWarning(
                    string.Format("Obfuscated packet expected but magicvalue mismatch on UDP packet from clientIP: {0}, Possible RecvKey: {1}",
                                  MpdUtilities.IP2String(dwIP), MuleApplication.Instance.KadEngine.Preference.GetUDPVerifyKey(dwIP)));
                return(nBufLen); // pass through, let the Receivefunction do the errorhandling on this junk
            }
        }
        public virtual int EncryptSendClient(ref byte[] ppbyBuf, int nBufLen, byte[] pachClientHashOrKadID, bool bKad, uint nReceiverVerifyKey, uint nSenderVerifyKey)
        {
            Debug.Assert(MuleApplication.Instance.PublicIP != 0 || bKad);
            Debug.Assert(MuleApplication.Instance.Preference.IsClientCryptLayerSupported);
            Debug.Assert(pachClientHashOrKadID != null || nReceiverVerifyKey != 0);
            Debug.Assert((nReceiverVerifyKey == 0 && nSenderVerifyKey == 0) || bKad);

            byte byPadLen        = 0;           // padding disabled for UDP currently
            int  nCryptHeaderLen = byPadLen + CRYPT_HEADER_WITHOUTPADDING + (bKad ? 8 : 0);

            int nCryptedLen = nBufLen + nCryptHeaderLen;

            byte[] pachCryptedBuffer = new byte[nCryptedLen];
            bool   bKadRecKeyUsed    = false;

            ushort nRandomKeyPart = MpdUtilities.GetRandomUInt16();
            MD5    md5            = MD5.Create();

            byte[] rawHash = null;
            if (bKad)
            {
                if ((pachClientHashOrKadID == null ||
                     MpdUtilities.IsNullMd4(pachClientHashOrKadID)) &&
                    nReceiverVerifyKey != 0)
                {
                    bKadRecKeyUsed = true;
                    byte[] achKeyData = new byte[6];
                    Array.Copy(BitConverter.GetBytes(nReceiverVerifyKey), achKeyData, 4);
                    Array.Copy(BitConverter.GetBytes(nRandomKeyPart), 0,
                               achKeyData, 4, 2);
                    rawHash = md5.ComputeHash(achKeyData);
                    //DEBUG_ONLY( DebugLog(_T("Creating obfuscated Kad packet encrypted by ReceiverKey (%u)"), nReceiverVerifyKey) );
                }
                else if (pachClientHashOrKadID != null && !MpdUtilities.IsNullMd4(pachClientHashOrKadID))
                {
                    byte[] achKeyData = new byte[18];
                    MpdUtilities.Md4Cpy(achKeyData, pachClientHashOrKadID);
                    Array.Copy(BitConverter.GetBytes(nRandomKeyPart), 0,
                               achKeyData, 16, 2);
                    rawHash = md5.ComputeHash(achKeyData);
                    //DEBUG_ONLY( DebugLog(_T("Creating obfuscated Kad packet encrypted by Hash/NodeID %s"), md4str(pachClientHashOrKadID)) );
                }
                else
                {
                    ppbyBuf = null;
                    Debug.Assert(false);
                    return(nBufLen);
                }
            }
            else
            {
                byte[] achKeyData = new byte[23];
                MpdUtilities.Md4Cpy(achKeyData, pachClientHashOrKadID);
                uint dwIP = (uint)MuleApplication.Instance.PublicIP;
                Array.Copy(BitConverter.GetBytes(dwIP), 0, achKeyData, 16, 4);
                Array.Copy(BitConverter.GetBytes(nRandomKeyPart), 0, achKeyData, 21, 2);
                achKeyData[20] = MAGICVALUE_UDP;
                rawHash        = md5.ComputeHash(achKeyData);
            }
            RC4Key keySendKey = null;

            MuleUtilities.RC4CreateKey(rawHash, 16, ref keySendKey, true);

            // create the semi random byte encryption header
            byte bySemiRandomNotProtocolMarker = 0;
            int  i;

            for (i = 0; i < 128; i++)
            {
                bySemiRandomNotProtocolMarker = MpdUtilities.GetRandomUInt8();
                bySemiRandomNotProtocolMarker =
                    (byte)(bKad ? (bySemiRandomNotProtocolMarker & 0xFE) :
                           (bySemiRandomNotProtocolMarker | 0x01)); // set the ed2k/kad marker bit
                if (bKad)
                {
                    bySemiRandomNotProtocolMarker =
                        (byte)(bKadRecKeyUsed ? ((bySemiRandomNotProtocolMarker & 0xFE) | 0x02) :
                               (bySemiRandomNotProtocolMarker & 0xFC)); // set the ed2k/kad and nodeid/reckey markerbit
                }
                else
                {
                    bySemiRandomNotProtocolMarker = (byte)(bySemiRandomNotProtocolMarker | 0x01); // set the ed2k/kad marker bit
                }
                bool bOk = false;
                switch (bySemiRandomNotProtocolMarker)
                { // not allowed values
                case MuleConstants.PROTOCOL_EMULEPROT:
                case MuleConstants.PROTOCOL_KADEMLIAPACKEDPROT:
                case MuleConstants.PROTOCOL_KADEMLIAHEADER:
                case MuleConstants.PROTOCOL_UDPRESERVEDPROT1:
                case MuleConstants.PROTOCOL_UDPRESERVEDPROT2:
                case MuleConstants.PROTOCOL_PACKEDPROT:
                    break;

                default:
                    bOk = true;
                    break;
                }
                if (bOk)
                {
                    break;
                }
            }
            if (i >= 128)
            {
                // either we have _really_ bad luck or the randomgenerator is a bit messed up
                Debug.Assert(false);
                bySemiRandomNotProtocolMarker = 0x01;
            }

            uint dwMagicValue = MAGICVALUE_UDP_SYNC_CLIENT;

            pachCryptedBuffer[0] = bySemiRandomNotProtocolMarker;
            Array.Copy(BitConverter.GetBytes(nRandomKeyPart), 0, pachCryptedBuffer, 1, 2);
            MuleUtilities.RC4Crypt(BitConverter.GetBytes(dwMagicValue), 0, pachCryptedBuffer, 3, 4, keySendKey);
            MuleUtilities.RC4Crypt(BitConverter.GetBytes(byPadLen), 0, pachCryptedBuffer, 7, 1, keySendKey);

            Random rand = new Random();

            for (int j = 0; j < byPadLen; j++)
            {
                byte byRand = (byte)rand.Next(255);     // they actually dont really need to be random, but it doesn't hurts either
                MuleUtilities.RC4Crypt(BitConverter.GetBytes(byRand), 0,
                                       pachCryptedBuffer, CRYPT_HEADER_WITHOUTPADDING + j, 1, keySendKey);
            }

            if (bKad)
            {
                MuleUtilities.RC4Crypt(BitConverter.GetBytes(nReceiverVerifyKey), 0,
                                       pachCryptedBuffer, CRYPT_HEADER_WITHOUTPADDING + byPadLen, 4, keySendKey);
                MuleUtilities.RC4Crypt(BitConverter.GetBytes(nSenderVerifyKey), 0,
                                       pachCryptedBuffer, CRYPT_HEADER_WITHOUTPADDING + byPadLen + 4, 4, keySendKey);
            }

            MuleUtilities.RC4Crypt(ppbyBuf, 0,
                                   pachCryptedBuffer, nCryptHeaderLen, (uint)nBufLen, keySendKey);
            ppbyBuf = pachCryptedBuffer;

            MuleApplication.Instance.Statistics.AddUpDataOverheadCrypt((uint)(nCryptedLen - nBufLen));
            return(nCryptedLen);
        }
Beispiel #14
0
        private int Negotiate(byte[] pBuffer, int offset, int nLen)
        {
            int nRead = 0;

            Debug.Assert(receiveBytesWanted_ > 0);
            try
            {
                while (negotiatingState_ != NegotiatingStateEnum.ONS_COMPLETE && receiveBytesWanted_ > 0)
                {
                    if (receiveBytesWanted_ > 512)
                    {
                        Debug.Assert(false);
                        return(0);
                    }

                    if (fiReceiveBuffer_ == null)
                    {
                        byte[] pReceiveBuffer = new byte[512]; // use a fixed size buffer
                        fiReceiveBuffer_ = MpdObjectManager.CreateSafeMemFile(pReceiveBuffer);
                    }
                    int nToRead = Math.Min(Convert.ToInt32(nLen) - nRead, Convert.ToInt32(receiveBytesWanted_));
                    fiReceiveBuffer_.Write(pBuffer, nRead, nToRead);
                    nRead += nToRead;
                    receiveBytesWanted_ -= Convert.ToUInt32(nToRead);
                    if (receiveBytesWanted_ > 0)
                    {
                        return(nRead);
                    }
                    uint nCurrentBytesLen = (uint)fiReceiveBuffer_.Position;

                    if (negotiatingState_ != NegotiatingStateEnum.ONS_BASIC_CLIENTA_RANDOMPART &&
                        negotiatingState_ != NegotiatingStateEnum.ONS_BASIC_SERVER_DHANSWER)
                    { // don't have the keys yet
                        byte[] pCryptBuffer = fiReceiveBuffer_.Buffer;
                        MuleUtilities.RC4Crypt(pCryptBuffer, pCryptBuffer, nCurrentBytesLen, rc4ReceiveKey_);
                    }
                    fiReceiveBuffer_.SeekToBegin();

                    switch (negotiatingState_)
                    {
                    case NegotiatingStateEnum.ONS_NONE:     // would be a bug
                        Debug.Assert(false);
                        return(0);

                    case NegotiatingStateEnum.ONS_BASIC_CLIENTA_RANDOMPART:
                    {
                        Debug.Assert(rc4ReceiveKey_ == null);

                        byte[] achKeyData = new byte[21];
                        MpdUtilities.Md4Cpy(achKeyData, MuleApplication.Instance.Preference.UserHash);
                        achKeyData[16] = Convert.ToByte(MuleConstants.MAGICVALUE_REQUESTER);
                        fiReceiveBuffer_.Read(achKeyData, 17, 4);         // random key part sent from remote client

                        MD5 md5 = MD5.Create();
                        rc4ReceiveKey_ =
                            MuleUtilities.RC4CreateKey(md5.ComputeHash(achKeyData), 16);
                        achKeyData[16] = Convert.ToByte(MuleConstants.MAGICVALUE_SERVER);
                        rc4SendKey_    =
                            MuleUtilities.RC4CreateKey(md5.ComputeHash(achKeyData), 16);

                        negotiatingState_   = NegotiatingStateEnum.ONS_BASIC_CLIENTA_MAGICVALUE;
                        receiveBytesWanted_ = 4;
                        break;
                    }

                    case NegotiatingStateEnum.ONS_BASIC_CLIENTA_MAGICVALUE:
                    {
                        uint dwValue = fiReceiveBuffer_.ReadUInt32();
                        if (dwValue == MuleConstants.MAGICVALUE_SYNC)
                        {
                            // yup, the one or the other way it worked, this is an encrypted stream
                            //DEBUG_ONLY( MpdUtilities.DebugLog(("Received proper magic value, clientIP: %s"), DbgGetIPString()) );
                            // set the receiver key
                            negotiatingState_   = NegotiatingStateEnum.ONS_BASIC_CLIENTA_METHODTAGSPADLEN;
                            receiveBytesWanted_ = 3;
                        }
                        else
                        {
                            MpdUtilities.DebugLogError(("CEncryptedStreamSocket: Received wrong magic value from clientIP %s on a supposly encrytped stream / Wrong Header"), DbgGetIPString());
                            OnError(Convert.ToInt32(EMSocketErrorCodeEnum.ERR_ENCRYPTION));
                            return(-1);
                        }
                        break;
                    }

                    case NegotiatingStateEnum.ONS_BASIC_CLIENTA_METHODTAGSPADLEN:
                        DbgByEncryptionSupported = fiReceiveBuffer_.ReadUInt8();
                        DbgByEncryptionRequested = fiReceiveBuffer_.ReadUInt8();
                        if (DbgByEncryptionRequested != Convert.ToByte(EncryptionMethodsEnum.ENM_OBFUSCATION))
                        {
                            MpdUtilities.AddDebugLogLine(EDebugLogPriority.DLP_LOW, false, ("CEncryptedStreamSocket: Client %s preffered unsupported encryption method (%i)"), DbgGetIPString(), DbgByEncryptionRequested);
                        }
                        receiveBytesWanted_ = fiReceiveBuffer_.ReadUInt8();
                        negotiatingState_   = NegotiatingStateEnum.ONS_BASIC_CLIENTA_PADDING;
                        if (receiveBytesWanted_ > 0)
                        {
                            break;
                        }
                        else
                        {
                            goto case NegotiatingStateEnum.ONS_BASIC_CLIENTA_PADDING;
                        }

                    case NegotiatingStateEnum.ONS_BASIC_CLIENTA_PADDING:
                    {
                        // ignore the random bytes, send the response, set status complete
                        SafeMemFile fileResponse = MpdObjectManager.CreateSafeMemFile(26);
                        fileResponse.WriteUInt32(MuleConstants.MAGICVALUE_SYNC);
                        byte bySelectedEncryptionMethod = Convert.ToByte(EncryptionMethodsEnum.ENM_OBFUSCATION);         // we do not support any further encryption in this version, so no need to look which the other client preferred
                        fileResponse.WriteUInt8(bySelectedEncryptionMethod);

                        IPEndPoint remoteEp = RemoteEndPoint as IPEndPoint;

                        byte byPaddingLen =
                            MuleApplication.Instance.ServerConnect.AwaitingTestFromIP(BitConverter.ToUInt32(remoteEp.Address.GetAddressBytes(), 0))
                                        ? Convert.ToByte(16) :
                            Convert.ToByte(MuleApplication.Instance.Preference.CryptTCPPaddingLength + 1);
                        byte byPadding = Convert.ToByte(MpdUtilities.GetRandomUInt8() % byPaddingLen);

                        fileResponse.WriteUInt8(byPadding);
                        for (int i = 0; i < byPadding; i++)
                        {
                            fileResponse.WriteUInt8(MpdUtilities.GetRandomUInt8());
                        }
                        SendNegotiatingData(fileResponse.Buffer, (uint)fileResponse.Length);
                        negotiatingState_ = NegotiatingStateEnum.ONS_COMPLETE;
                        streamCryptState_ = StreamCryptStateEnum.ECS_ENCRYPTING;
                        //DEBUG_ONLY( MpdUtilities.DebugLog(("CEncryptedStreamSocket: Finished Obufscation handshake with client %s (incoming)"), DbgGetIPString()) );
                        break;
                    }

                    case NegotiatingStateEnum.ONS_BASIC_CLIENTB_MAGICVALUE:
                    {
                        if (fiReceiveBuffer_.ReadUInt32() != MuleConstants.MAGICVALUE_SYNC)
                        {
                            MpdUtilities.DebugLogError(("CEncryptedStreamSocket: EncryptedstreamSyncError: Client sent wrong Magic Value as answer, cannot complete handshake (%s)"), DbgGetIPString());
                            OnError(Convert.ToInt32(EMSocketErrorCodeEnum.ERR_ENCRYPTION));
                            return(-1);
                        }
                        negotiatingState_   = NegotiatingStateEnum.ONS_BASIC_CLIENTB_METHODTAGSPADLEN;
                        receiveBytesWanted_ = 2;
                        break;
                    }

                    case NegotiatingStateEnum.ONS_BASIC_CLIENTB_METHODTAGSPADLEN:
                    {
                        DbgByEncryptionMethodSet = fiReceiveBuffer_.ReadUInt8();
                        if (DbgByEncryptionMethodSet != Convert.ToByte(EncryptionMethodsEnum.ENM_OBFUSCATION))
                        {
                            MpdUtilities.DebugLogError(("CEncryptedStreamSocket: Client %s set unsupported encryption method (%i), handshake failed"),
                                                       DbgGetIPString(), DbgByEncryptionMethodSet);
                            OnError(Convert.ToInt32(EMSocketErrorCodeEnum.ERR_ENCRYPTION));
                            return(-1);
                        }
                        receiveBytesWanted_ = fiReceiveBuffer_.ReadUInt8();
                        negotiatingState_   = NegotiatingStateEnum.ONS_BASIC_CLIENTB_PADDING;
                        if (receiveBytesWanted_ > 0)
                        {
                            break;
                        }
                        else
                        {
                            goto case NegotiatingStateEnum.ONS_BASIC_CLIENTB_PADDING;
                        }
                    }

                    case NegotiatingStateEnum.ONS_BASIC_CLIENTB_PADDING:
                        // ignore the random bytes, the handshake is complete
                        negotiatingState_ = NegotiatingStateEnum.ONS_COMPLETE;
                        streamCryptState_ = StreamCryptStateEnum.ECS_ENCRYPTING;
                        //DEBUG_ONLY( MpdUtilities.DebugLog(("CEncryptedStreamSocket: Finished Obufscation handshake with client %s (outgoing)"), DbgGetIPString()) );
                        break;

                    case NegotiatingStateEnum.ONS_BASIC_SERVER_DHANSWER:
                    {
                        Debug.Assert(cryptDHA_ != new BigInteger(0));
                        byte[] aBuffer = new byte[MuleConstants.PRIMESIZE_BYTES + 1];
                        fiReceiveBuffer_.Read(aBuffer, 0, Convert.ToInt32(MuleConstants.PRIMESIZE_BYTES));
                        BigInteger cryptDHAnswer =
                            new BigInteger(aBuffer, (int)MuleConstants.PRIMESIZE_BYTES);
                        BigInteger cryptDHPrime =
                            new BigInteger(dh768_p_, (int)MuleConstants.PRIMESIZE_BYTES);          // our fixed prime
                        BigInteger cryptResult =
                            cryptDHAnswer.modPow(cryptDHA_, cryptDHPrime);

                        cryptDHA_ = 0;
                        Array.Clear(aBuffer, 0, aBuffer.Length);

                        // create the keys
                        Array.Copy(cryptResult.getBytes(), aBuffer, MuleConstants.PRIMESIZE_BYTES);
                        aBuffer[MuleConstants.PRIMESIZE_BYTES] = Convert.ToByte(MuleConstants.MAGICVALUE_REQUESTER);
                        MD5 md5 = MD5.Create();

                        rc4SendKey_ =
                            MuleUtilities.RC4CreateKey(md5.ComputeHash(aBuffer), 16);
                        aBuffer[MuleConstants.PRIMESIZE_BYTES] = Convert.ToByte(MuleConstants.MAGICVALUE_SERVER);
                        rc4ReceiveKey_ =
                            MuleUtilities.RC4CreateKey(md5.ComputeHash(aBuffer), 16);

                        negotiatingState_   = NegotiatingStateEnum.ONS_BASIC_SERVER_MAGICVALUE;
                        receiveBytesWanted_ = 4;
                        break;
                    }

                    case NegotiatingStateEnum.ONS_BASIC_SERVER_MAGICVALUE:
                    {
                        uint dwValue = fiReceiveBuffer_.ReadUInt32();
                        if (dwValue == MuleConstants.MAGICVALUE_SYNC)
                        {
                            // yup, the one or the other way it worked, this is an encrypted stream
                            MpdUtilities.DebugLog(("Received proper magic value after DH-Agreement from Serverconnection IP: %s"), DbgGetIPString());
                            // set the receiver key
                            negotiatingState_   = NegotiatingStateEnum.ONS_BASIC_SERVER_METHODTAGSPADLEN;
                            receiveBytesWanted_ = 3;
                        }
                        else
                        {
                            MpdUtilities.DebugLogError(("CEncryptedStreamSocket: Received wrong magic value after DH-Agreement from Serverconnection"), DbgGetIPString());
                            OnError(Convert.ToInt32(EMSocketErrorCodeEnum.ERR_ENCRYPTION));
                            return(-1);
                        }
                        break;
                    }

                    case NegotiatingStateEnum.ONS_BASIC_SERVER_METHODTAGSPADLEN:
                        DbgByEncryptionSupported = fiReceiveBuffer_.ReadUInt8();
                        DbgByEncryptionRequested = fiReceiveBuffer_.ReadUInt8();
                        if (DbgByEncryptionRequested != Convert.ToByte(EncryptionMethodsEnum.ENM_OBFUSCATION))
                        {
                            MpdUtilities.AddDebugLogLine(EDebugLogPriority.DLP_LOW, false, ("CEncryptedStreamSocket: Server %s preffered unsupported encryption method (%i)"), DbgGetIPString(), DbgByEncryptionRequested);
                        }
                        receiveBytesWanted_ = fiReceiveBuffer_.ReadUInt8();
                        negotiatingState_   = NegotiatingStateEnum.ONS_BASIC_SERVER_PADDING;
                        if (receiveBytesWanted_ > 16)
                        {
                            MpdUtilities.AddDebugLogLine(EDebugLogPriority.DLP_LOW, false, ("CEncryptedStreamSocket: Server %s sent more than 16 (%i) padding bytes"), DbgGetIPString(), receiveBytesWanted_);
                        }
                        if (receiveBytesWanted_ > 0)
                        {
                            break;
                        }
                        else
                        {
                            goto case NegotiatingStateEnum.ONS_BASIC_SERVER_PADDING;
                        }

                    case NegotiatingStateEnum.ONS_BASIC_SERVER_PADDING:
                    {
                        // ignore the random bytes (they are decrypted already), send the response, set status complete
                        SafeMemFile fileResponse = MpdObjectManager.CreateSafeMemFile(26);
                        fileResponse.WriteUInt32(MuleConstants.MAGICVALUE_SYNC);
                        byte bySelectedEncryptionMethod =
                            Convert.ToByte(EncryptionMethodsEnum.ENM_OBFUSCATION);         // we do not support any further encryption in this version, so no need to look which the other client preferred
                        fileResponse.WriteUInt8(bySelectedEncryptionMethod);
                        byte byPadding = (byte)(MpdUtilities.GetRandomUInt8() % 16);
                        fileResponse.WriteUInt8(byPadding);
                        for (int i = 0; i < byPadding; i++)
                        {
                            fileResponse.WriteUInt8(MpdUtilities.GetRandomUInt8());
                        }

                        negotiatingState_ = NegotiatingStateEnum.ONS_BASIC_SERVER_DELAYEDSENDING;
                        SendNegotiatingData(fileResponse.Buffer, (uint)fileResponse.Length, 0, true);         // don't actually send it right now, store it in our sendbuffer
                        streamCryptState_ = StreamCryptStateEnum.ECS_ENCRYPTING;
                        MpdUtilities.DebugLog(("CEncryptedStreamSocket: Finished DH Obufscation handshake with Server %s"), DbgGetIPString());
                        break;
                    }

                    default:
                        Debug.Assert(false);
                        break;
                    }
                    fiReceiveBuffer_.SeekToBegin();
                }

                fiReceiveBuffer_ = null;
                return(nRead);
            }
            catch (Exception)
            {
                Debug.Assert(false);
                OnError(Convert.ToInt32(EMSocketErrorCodeEnum.ERR_ENCRYPTION));
                fiReceiveBuffer_ = null;
                return(-1);
            }
        }
 protected FileIdentifierBaseImpl(FileIdentifierBase rFileIdentifier)
 {
     MpdUtilities.Md4Cpy(md4Hash_, rFileIdentifier.MD4Hash);
     HasAICHHash = rFileIdentifier.HasAICHHash;
     AICHHash    = rFileIdentifier.AICHHash;
 }