1

I am trying to understand the client part of the SSH protocol and referring the Paramiko library which is a native Python library for SSH protocol. The corresponding code can be found here.

def _send_kex_init(self):
    """
    announce to the other side that we'd like to negotiate keys, and what
    kind of key negotiation we support.
    """
    self.clear_to_send_lock.acquire()
    try:
        self.clear_to_send.clear()
    finally:
        self.clear_to_send_lock.release()
    self.in_kex = True
    if self.server_mode:
        mp_required_prefix = 'diffie-hellman-group-exchange-sha'
        kex_mp = [k for k in self._preferred_kex if k.startswith(mp_required_prefix)]
        if (self._modulus_pack is None) and (len(kex_mp) > 0):
            # can't do group-exchange if we don't have a pack of potential primes
            pkex = [k for k in self.get_security_options().kex
                            if not k.startswith(mp_required_prefix)]
            self.get_security_options().kex = pkex
        available_server_keys = list(filter(list(self.server_key_dict.keys()).__contains__,
                                            self._preferred_keys))
    else:
        available_server_keys = self._preferred_keys

    m = Message()
    m.add_byte(cMSG_KEXINIT)
    m.add_bytes(os.urandom(16))
    m.add_list(self._preferred_kex)
    m.add_list(available_server_keys)
    m.add_list(self._preferred_ciphers)
    m.add_list(self._preferred_ciphers)
    m.add_list(self._preferred_macs)
    m.add_list(self._preferred_macs)
    m.add_list(self._preferred_compression)
    m.add_list(self._preferred_compression)
    m.add_string(bytes())
    m.add_string(bytes())
    m.add_boolean(False)
    m.add_int(0)
    # save a copy for later (needed to compute a hash)
    self.local_kex_init = m.asbytes()
    self._send_message(m)
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Jayendra Parmar
  • 702
  • 12
  • 30

1 Answers1

1

SSH protocol allows both parties to implement a different sets of algorithms for incoming and outgoing directions. Or practically speaking, it allows a party to implement a specific algorithm for one of the directions only.

Paramiko implements all algorithms for both directions, so it populates lists of both incoming and outgoing algorithms with the same set.


See the code in _parse_kex_init method, which parses the packet populated by the code you refer to:

    client_encrypt_algo_list = m.get_list()
    server_encrypt_algo_list = m.get_list()

...

        agreed_local_ciphers = list(
            filter(
                client_encrypt_algo_list.__contains__,
                self._preferred_ciphers,
            )
        )
        agreed_remote_ciphers = list(
            filter(
                server_encrypt_algo_list.__contains__,
                self._preferred_ciphers,
            )
        )
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992