public override bool Pass(INodeEndpointProtocolRequest request)
            {
                lock (this.stepLock)
                {
                    switch (this.currentStep)
                    {
                    case Step.WaitingForUserName:
                    {
                        this.currentStep = Step.WaitingForEncryptedAuthData;
                        string userName    = request.RequestMessage();
                        byte[] passwordMD5 = this.authenticationProvider.GetUserNamePasswordMD5(userName);
                        byte[] authData    = new byte[128];
                        new Random().NextBytes(authData);

                        if (passwordMD5 != null)
                        {
                            this.expectedMixedAuthDataAndPassword = Md5AuthDataAndPassword(authData, passwordMD5);
                        }
                        request.Respond(authData);
                    }
                        return(false);

                    case Step.WaitingForEncryptedAuthData:
                    {
                        if (this.expectedMixedAuthDataAndPassword == null)
                        {
                            request.Respond("FAIL");
                        }
                        else
                        {
                            this.currentStep = Step.WaitingForPublicKey;
                            byte[] expected = this.expectedMixedAuthDataAndPassword;
                            byte[] actual   = request.Message;
                            this.expectedMixedAuthDataAndPassword = null;

                            bool fail = false;
                            if (expected.Length != actual.Length)
                            {
                                fail = true;
                            }
                            else
                            {
                                for (int i = 0; i < expected.Length; i++)
                                {
                                    if (expected[i] != actual[i])
                                    {
                                        fail = true;
                                        break;
                                    }
                                }
                            }

                            request.Respond(fail ? "FAIL" : "PASS");
                        }
                    }
                        return(false);

                    case Step.WaitingForPublicKey:
                    {
                        this.currentStep = Step.Done;
                        byte[] publicKey = request.Message;
                        byte[] key, iv;
                        Crypting.AesGenerateKey(out key, out iv);

                        byte[] message = new byte[sizeof(int) + key.Length + iv.Length];
                        StreamProtocol <Stream> .WriteLeadBytes(key.Length, message);

                        Array.Copy(key, 0, message, sizeof(int), key.Length);
                        Array.Copy(iv, 0, message, sizeof(int) + key.Length, iv.Length);

                        byte[] encryptedMessage = Crypting.RsaEncrypt(message, publicKey);
                        request.Respond(encryptedMessage);

                        SetKey(key, iv);
                    }
                        return(false);
                    }
                }
                return(true);
            }