“Use key-based auth instead of a password” is common advice for connecting to a server over SSH. But what exactly does key authentication prove, and how does that differ from what a password proves? This post works through the mechanics of what each method is actually demonstrating.
Authentication is an act of proof
Note: authentication is the process of confirming that whoever just connected really is who they claim to be, based on some kind of evidence. It’s often confused with authorization, which is a separate concept covering what a confirmed identity is then allowed to do.
Every authentication scheme ultimately comes down to a choice: what evidence counts as proof of identity? Password authentication and public-key authentication answer that question in fundamentally different ways.
Password authentication: proving you know a secret by stating it
Password authentication is structurally simple. Client and server both know the same secret in advance. The client sends that secret to the server, the server compares it (usually after hashing) against its own stored record, and a match means “authenticated.”
The weakness lives in that structure itself: the secret gets stated, directly, as part of the exchange. SSH’s transport is encrypted, so eavesdropping isn’t the main concern — the problems lie elsewhere:
- Passwords people can actually remember tend to have far lower entropy than machine-generated random values, which makes them susceptible to dictionary and brute-force attacks
- Reusing the same password across services turns one leak into an entry point for every other server that shares it (credential stuffing)
- If the value stored server-side (a hash) ever leaks, it opens the door to offline brute-forcing
In short, password authentication proves “I know the secret” by transmitting the secret — or a value derived directly from it.
Public-key authentication: proving possession without ever handing over the secret
Public-key authentication proves identity a completely different way, built on asymmetric cryptography — a public/private key pair.
Note: asymmetric cryptography uses two mathematically linked but distinct keys: a private key for signing or decrypting, and a public key for verifying or encrypting. Deriving one key from the other is designed to be computationally infeasible.
Only the public key gets registered on the server ahead of time. The private key never leaves the client machine. During authentication, the server sends a random challenge value; the client signs it with the private key and sends the signature back. The server verifies that signature using the registered public key — a valid signature is proof that the client holds the matching private key, without the private key itself ever being transmitted.
That’s the decisive difference. Password authentication sends the secret itself over the wire. Public-key authentication only ever sends proof of possession (a signature), and by design, that proof can’t be reverse-engineered back into the private key.
What happens if server-side data leaks
The difference becomes stark when you consider what a leak of server-side authentication data actually costs.
With password authentication, what the server stores is a password hash. If that hash leaks, an attacker can brute-force it offline — and a weak password will eventually fall.
With public-key authentication, what the server stores is the public key itself — information that’s meant to be public by definition. A leak of that data costs nothing, because there was never a secret sitting on the server side to begin with. Not putting anything secret on the server is the core of why public-key authentication is safer.
A real example: narrowing authentication down to one explicit key
This app’s SSH connection code (core/ssh_utils.py::get_ssh_connection()) doesn’t just use public-key authentication — it also deliberately narrows which key gets tried.
connect_kwargs = {'look_for_keys': False, 'allow_agent': False}
if 'ssh_key_path' in site and site['ssh_key_path']:
...
pkey = load_any_ssh_key(key_path, passphrase=ssh_passphrase)
connect_kwargs['pkey'] = pkey
return Connection(
host=site['ssh_host'],
user=site['ssh_user'],
port=site.get('ssh_port', 22),
connect_timeout=15,
connect_kwargs=connect_kwargs
)
look_for_keys=False and allow_agent=False turn off the SSH client library’s (paramiko’s) default behavior of trying every key under ~/.ssh/ and every key registered in a running SSH agent. Only the one key specified in that site’s configuration is passed in explicitly via pkey.
This isn’t a matter of taste. In an environment managing many sites, leaving automatic key discovery on means a single connection attempt can end up trying several candidate keys back to back — quickly running into OpenSSH’s MaxAuthTries limit (6 by default). If the server side has protection like fail2ban or OpenSSH’s PerSourcePenalties, a legitimate administrator can end up temporarily blocking their own IP by accident. Pinning “this connection uses exactly this one key” isn’t about the strength of authentication itself — it’s a structural fix for a pitfall specific to managing many sites at once.
Turning password login off entirely, server-side
Beyond using key auth on the client, it’s also standard practice to set PasswordAuthentication no in sshd_config, so the server won’t even accept password login attempts. That’s a well-documented, standard OpenSSH setting — not some private operational trick — and it follows a simple principle: eliminate the weaker authentication path rather than just discouraging its use. No matter how strong a key is, if the same account can still be reached with a password, that’s where an attacker will aim.
How this connects to choosing a key type
An earlier post, SSH Key Types: RSA vs. ED25519 vs. ECDSA — Which Should You Use?, covered which key algorithm to pick once you’re using public-key authentication. This post is one layer earlier in that decision: why choose public-key authentication over a password in the first place. Picking a key algorithm is a decision that only comes up after you’ve already committed to that approach.
Summary
Password authentication proves “I know the secret” by transmitting the secret itself. Public-key authentication proves the same kind of claim — “I am who I say I am” — by transmitting only proof of possession, never the private key. That difference directly shapes the blast radius of a server-side data leak: a leaked password hash is a starting point for an attacker, while a leaked public key is worthless to one, because it was never secret to begin with. Keeping nothing secret on the server side is the most fundamental reason SSH key authentication is recommended over passwords.