private void HandleExchangeFrame(ServerExchangeFrame frame) { if (frame.Success) { if (frame.Tag.Length > MAX_TAG_LENGTH) { OnExceptionThrown(new InvalidDataException("Invalid tag length.")); return; } HashPuzzle puzzle = new HashPuzzle(HashAlgorithmName.SHA256, ChallengeDifficulty, ServerNonce); if (!puzzle.VerifySolution(frame.Solution)) { OnExceptionThrown(new InvalidDataException("Challenge failed.")); return; } if (frame.Tag.Length == 0) { if (MutualAuthenticationRequired) { OnExceptionThrown(new InvalidDataException("Tag missing.")); return; } } else { _remoteTag = Tag.Deserialize(frame.Tag); if (TrustedIssuers != null && _remoteTag.Verify(TrustedIssuers)) { IsMutuallyAuthenticated = true; } if (MutualAuthenticationRequired) { OnExceptionThrown(new InvalidDataException("Invalid tag.")); return; } } ClientNonce = frame.Nonce; BufferFrame(new ServerValidateFrame(), FrameState.ServerValidate); SendExchangeFrame(GetPublicKey(), IsMutuallyAuthenticated); } else { OnChallengeFailed(); //TODO: check if we're disposed ServerNonce = CreateNonce(NONCE_LENGTH); BufferFrame(new ServerExchangeFrame(), FrameState.ServerExchange); SendNegotiateFrame(); } }
private void HandleNegotiateFrame(ClientNegotiateFrame frame) { if (frame.MinVersion > MAX_VERSION || frame.MaxVersion < MIN_VERSION) { OnExceptionThrown(new InvalidDataException("Invalid protocol version.")); return; } if (frame.Difficulty > MAX_DIFFICULTY) { OnExceptionThrown(new InvalidDataException("Challenge difficulty is too high.")); return; } if (frame.IsMutual && LocalTag == null) { OnExceptionThrown(new InvalidOperationException("Server requires mutual authentication.")); return; } HashPuzzle puzzle = new HashPuzzle(HashAlgorithmName.SHA256, frame.Difficulty, frame.Nonce); bool success = puzzle.FindSolution(); if (success) { Version = Math.Min(frame.MaxVersion, MAX_VERSION); ServerNonce = frame.Nonce; ClientNonce = CreateNonce(NONCE_LENGTH); BufferFrame(new ClientExchangeFrame(), FrameState.ClientExchange); } else { BufferFrame(new ClientNegotiateFrame(), FrameState.ClientNegotiate); } SendExchangeFrame(success, puzzle.Solution); }