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); }