/**
   * @throws IOException
   * @throws KeyExchangeException
   */
  protected void beginKeyExchange() throws IOException, KeyExchangeException {
    log.info("Starting key exchange");

    // state.setValue(TransportProtocolState.PERFORMING_KEYEXCHANGE);
    String kexAlgorithm = "";

    // We now have both kex inits, this is where client/server
    // implemtations take over so call abstract methods
    try {
      // Determine the key exchange algorithm
      kexAlgorithm = getKexAlgorithm();

      if (log.isDebugEnabled()) {
        log.debug("Key exchange algorithm: " + kexAlgorithm);
      }

      // Get an instance of the key exchange algortihm
      SshKeyExchange kex = (SshKeyExchange) kexs.get(kexAlgorithm);

      // Do the key exchange
      performKeyExchange(kex);

      // Record the output
      exchangeHash = kex.getExchangeHash();

      if (sessionIdentifier == null) {
        sessionIdentifier = new byte[exchangeHash.length];
        System.arraycopy(exchangeHash, 0, sessionIdentifier, 0, sessionIdentifier.length);
        thread.setSessionId(sessionIdentifier);
      }

      hostKey = kex.getHostKey();
      signature = kex.getSignature();
      k = kex.getSecret();

      // Send new keys
      sendNewKeys();
      kex.reset();
    } catch (AlgorithmNotAgreedException e) {
      sendDisconnect(
          SshMsgDisconnect.KEY_EXCHANGE_FAILED, "No suitable key exchange algorithm was agreed");
      throw new KeyExchangeException("No suitable key exchange algorithm could be agreed.");
    }
  }