SSH encryption is a clever layered defense, not just a single lock, that makes your remote connections secure by combining public-key cryptography with symmetric encryption.

Let’s watch it in action. Imagine you’re on your local machine (client) and you want to connect to a remote server (server).

# On your local machine (client)
ssh user@your_server_ip_address

When you type this, a whole dance happens before you even see a shell prompt.

First, the client and server agree on which encryption algorithms they both support. They’ll exchange lists of ciphers (like AES-256-GCM), MAC algorithms (like HMAC-SHA2-256), and key exchange methods (like curve25519-sha256). This is the initial handshake.

Next, they perform a key exchange, typically using Diffie-Hellman (DH) or Elliptic Curve Diffie-Hellman (ECDH). This is where the magic of public-key cryptography comes in. Both sides generate temporary public/private key pairs. They exchange their public keys, but without ever sending their private keys over the wire. Using a mathematical trick, they can both independently derive the same shared secret key. This shared secret key is never transmitted directly, making it extremely difficult for an eavesdropper to figure out.

Example of ECDH (simplified concept, not actual SSH output):

  • Client: Generates private key c_priv and public key c_pub = G * c_priv (where G is a known base point on an elliptic curve). Sends c_pub to the server.
  • Server: Generates private key s_priv and public key s_pub = G * s_priv. Sends s_pub to the client.
  • Client: Computes shared secret S = c_priv * s_pub = c_priv * (G * s_priv) = G * c_priv * s_priv.
  • Server: Computes shared secret S = s_priv * c_pub = s_priv * (G * c_priv) = G * s_priv * c_priv.

Both arrive at the same S without ever sharing c_priv or s_priv. This S is then used to derive the symmetric session keys.

Once they have this shared secret, they use a Key Derivation Function (KDF) to generate several symmetric encryption keys and MAC keys. These are session-specific keys, meaning they are unique to this particular SSH connection and are discarded when the connection closes. They derive keys for both directions: one for client-to-server, and one for server-to-client.

Now, the actual authentication happens. This is usually done via password or public-key authentication. If you’re using password authentication, your password is sent encrypted using the session keys just established. If you’re using public-key authentication, your client uses your private key (which never leaves your machine) to sign a challenge sent by the server. The server then verifies this signature using your public key (which it already has from ~/.ssh/authorized_keys on the server).

Finally, all subsequent data – your commands, the output from the server, file transfers – is encrypted using the symmetric session keys and authenticated with the MAC keys. This provides both confidentiality (no one can read your data) and integrity (no one can tamper with your data in transit without detection).

The most surprising thing about SSH encryption is that the initial, public-key based key exchange is often vulnerable to a "man-in-the-middle" attack if you blindly accept new host keys. SSH protects against this by having clients store the server’s public host key after the first successful connection. If the server later presents a different host key, the client will warn you, indicating that the server’s identity might have changed, possibly due to an attacker impersonating the server. You have to explicitly confirm to proceed, which is a crucial security check.

After this, you’re ready to explore more advanced SSH features like tunneling or agent forwarding.

Want structured learning?

Take the full Cryptography course →