/// <summary>
        /// Create a KileDecrypter instance.
        /// User should call following methods in sequence to initialize: AsExchange, TgsExchange and ApExchange.
        /// After exchanges are done, call DecryptRequest or DecryptResponse from first encrypted message to last.
        /// Do not skip any request or response.
        /// </summary>
        /// <param name="domain">
        /// The realm part of the client's principal identifier.
        /// This argument cannot be null.
        /// </param>
        /// <param name="cName">
        /// The account to logon the remote machine. Either user account or computer account.
        /// This argument cannot be null.
        /// </param>
        /// <param name="password">
        /// The password of the user.
        /// This argument cannot be null.
        /// </param>
        /// <param name="accountType">
        /// The type of the logon account. User or Computer.
        /// </param>
        /// <param name="connectionType">
        /// The connection type, TCP or UDP.
        /// </param>
        /// <exception cref="System.ArgumentNullException">
        /// Thrown when any parameter is null.
        /// </exception>
        public KileDecrypter(
            string domain,
            string cName,
            string password,
            KileAccountType accountType,
            KileConnectionType connectionType)
        {
            if (domain == null)
            {
                throw new ArgumentNullException(nameof(domain));
            }
            if (cName == null)
            {
                throw new ArgumentNullException(nameof(cName));
            }
            if (password == null)
            {
                throw new ArgumentNullException(nameof(password));
            }

            kileDecoder = new KileDecoder();
            kileDecoder.connectionType = connectionType;

            string salt = KileRole.GenerateSalt(domain, cName, accountType);

            kileDecoder.clientContext               = new KileClientContext();
            kileDecoder.clientContext.Password      = password;
            kileDecoder.clientContext.TransportType = connectionType;
            kileDecoder.clientContext.Salt          = salt;

            kileDecoder.serverContext = new KileServerContext();
            kileDecoder.serverContext.TransportType = connectionType;
            kileDecoder.serverContext.Salt          = salt;
            kileDecoder.serverContextList           = new Dictionary <KileConnection, KileServerContext>(new KileServerContextComparer());
            kileDecoder.serverContextList.Add(new KileConnection(FAKE_ENDPOINT), kileDecoder.serverContext);
        }