void Decode(byte[] message, int startIndex, int length)
        {
            int payloadOffset = length;
            int micOffset     = 64;

            ValidateArguments(message, startIndex, length);

            if (message.Length >= 64)
            {
                Flags = (NtlmFlags)BitConverterLE.ToUInt32(message, startIndex + 60);
            }
            else
            {
                Flags = (NtlmFlags)0x8201;
            }

            int lmLength = BitConverterLE.ToUInt16(message, startIndex + 12);
            int lmOffset = BitConverterLE.ToUInt16(message, startIndex + 16);

            LmChallengeResponse = new byte[lmLength];
            Buffer.BlockCopy(message, startIndex + lmOffset, LmChallengeResponse, 0, lmLength);
            payloadOffset = Math.Min(payloadOffset, lmOffset);

            int ntLength = BitConverterLE.ToUInt16(message, startIndex + 20);
            int ntOffset = BitConverterLE.ToUInt16(message, startIndex + 24);

            NtChallengeResponse = new byte[ntLength];
            Buffer.BlockCopy(message, startIndex + ntOffset, NtChallengeResponse, 0, ntLength);
            payloadOffset = Math.Min(payloadOffset, ntOffset);

            int domainLength = BitConverterLE.ToUInt16(message, startIndex + 28);
            int domainOffset = BitConverterLE.ToUInt16(message, startIndex + 32);

            Domain        = DecodeString(message, startIndex + domainOffset, domainLength);
            payloadOffset = Math.Min(payloadOffset, domainOffset);

            int userLength = BitConverterLE.ToUInt16(message, startIndex + 36);
            int userOffset = BitConverterLE.ToUInt16(message, startIndex + 40);

            UserName      = DecodeString(message, startIndex + userOffset, userLength);
            payloadOffset = Math.Min(payloadOffset, userOffset);

            int workstationLength = BitConverterLE.ToUInt16(message, startIndex + 44);
            int workstationOffset = BitConverterLE.ToUInt16(message, startIndex + 48);

            Workstation   = DecodeString(message, startIndex + workstationOffset, workstationLength);
            payloadOffset = Math.Min(payloadOffset, workstationOffset);

            int skeyLength = BitConverterLE.ToUInt16(message, startIndex + 52);
            int skeyOffset = BitConverterLE.ToUInt16(message, startIndex + 56);

            EncryptedRandomSessionKey = new byte[skeyLength];
            Buffer.BlockCopy(message, startIndex + skeyOffset, EncryptedRandomSessionKey, 0, skeyLength);
            payloadOffset = Math.Min(payloadOffset, skeyOffset);

            // OSVersion
            if ((Flags & NtlmFlags.NegotiateVersion) != 0 && length >= 72)
            {
                // decode the OS Version
                int major = message[startIndex + 64];
                int minor = message[startIndex + 65];
                int build = BitConverterLE.ToUInt16(message, startIndex + 66);

                OSVersion  = new Version(major, minor, build);
                micOffset += 8;
            }

            // MIC
            if (micOffset + 16 <= payloadOffset)
            {
                Mic = new byte[16];
                Buffer.BlockCopy(message, startIndex + micOffset, Mic, 0, Mic.Length);
            }
        }