void NegotiateSecurity(AuthenticationMethod[] methods)
        {
            _c.SendByte((byte)methods.Length);
            //验证密码
            VncStream.Require(methods.Length > 0,
                              "Client is not allowed in.",
                              VncFailureReason.NoSupportedAuthenticationMethods);
            foreach (var method in methods)
            {
                _c.SendByte((byte)method);
            }

            var selectedMethod = (AuthenticationMethod)_c.ReceiveByte();

            VncStream.Require(methods.Contains(selectedMethod),
                              "Invalid authentication method.",
                              VncFailureReason.UnrecognizedProtocolElement);

            bool success = true;

            if (selectedMethod == AuthenticationMethod.Password)
            {
                var challenge = VncPasswordChallenge.GenerateChallenge();
                using (new Utility.AutoClear(challenge))
                {
                    _c.Send(challenge);

                    var response = _c.Receive(16);
                    using (new Utility.AutoClear(response))
                    {
                        var e = new PasswordProvidedEventArgs(challenge, response);
                        OnPasswordProvided(e);
                        success = e.IsAuthenticated;
                    }
                }
            }

            _c.SendUInt32BE(success ? 0 : (uint)1);

            if (!success)
            {
                _c.SendString("Password authentication failed!", true);
            }

            VncStream.Require(success,
                              "Failed to authenticate.",
                              VncFailureReason.AuthenticationFailed);
        }
        public void NegotiateSecurityIncorrectPasswordTest()
        {
            using (var stream = new TestStream())
            {
                // Have the client send authentication method 'Password', which is what the server expects
                VncStream clientStream = new VncStream(stream.Input);
                clientStream.SendByte((byte)AuthenticationMethod.Password);
                clientStream.Send(new byte[16]); // An empty response
                stream.Input.Position = 0;

                var session = new VncServerSession();
                session.Connect(stream, null, startThread: false);

                Assert.False(session.NegotiateSecurity(new AuthenticationMethod[] { AuthenticationMethod.Password }));

                VncStream serverStream = new VncStream(stream.Output);
                stream.Output.Position = 0;

                // Server will have offered 1 authentication method, and failed to authenticate
                // the client
                Assert.Equal(1, serverStream.ReceiveByte());                                   // 1 authentication method offered
                Assert.Equal((byte)AuthenticationMethod.Password, serverStream.ReceiveByte()); // The authentication method offered
                Assert.NotEqual(0u, serverStream.ReceiveUInt32BE());                           // Challenge, part 1
                Assert.NotEqual(0u, serverStream.ReceiveUInt32BE());                           // Challenge, part 2
                Assert.NotEqual(0u, serverStream.ReceiveUInt32BE());                           // Challenge, part 3
                Assert.NotEqual(0u, serverStream.ReceiveUInt32BE());                           // Challenge, part 4
                Assert.Equal(1u, serverStream.ReceiveUInt32BE());                              // Authentication failed
                Assert.Equal("Failed to authenticate", serverStream.ReceiveString());          // Error message

                Assert.Equal(stream.Output.Length, stream.Output.Position);
                Assert.Equal(stream.Input.Length, stream.Input.Position);
            }
        }