When using SSH keys to authenticate to a server for remote access, why is it possible to devise the true key and therefore the passphrase from an encrypted private key, without checking each guess of the passphrase against the server to see if it authenticates?

I understand that the passphrase is only used to decrypt the key and not sent to the remote server, but I don't understand why it is easy to tell the result of the correct decryption from the result of an incorrect decryption. If that was impossible (or implausible), surely SSH keys would be more immune to bruteforcing and therefore stronger?

I see it as a weakness, but I barely understand the maths behind public key authentication, so I'm assuming that there is a reason I have missed but you far cleverer people are aware of.

Thanks, This is the question that I was trying to ask thanks for figuring that out. Is it impossible to design a key where it was harder to verify the key was correct? Thus making a key 'safer' from brute force attacks, or is this pointless?
–
Ben PageApr 14 '11 at 9:52

1

Note that normally you wouldn't have p and q (having them simply allows you to calculate d from e), so actually you would have to try if (x^d)^e = x mod p·q for some x.
–
Paŭlo EbermannSep 28 '11 at 17:26

2

@Paŭlo Ebermann: You would normally have p, q, and 1/q mod p in your private key, because that allows to use the Chinese remainder theorem to speed up the computations.
–
Christopher CreutzigApr 10 '12 at 19:00

As @caf shows, a RSA private key has a lot of internal structure, which is easily recognized. It would be very difficult to design a password-based encryption scheme such that the decryption of an encrypted RSA key with the wrong password still yields something which looks like a valid RSA private key.

However, this is relatively easy to do with DSA keys (and also with the elliptic-curve variant ECDSA). A DSA private key uses key parameters (called p, q and g) which are not required to be secret (they are also present in the corresponding public key); the only really private part in the key is x, an integer modulo q. Any integer modulo q is a valid DSA private key. So you can make a password-based encryption of x that way:

Choose q to be a 256-bit number (i.e. 2255 < q < 2256).

Use a block cipher with 256-bit blocks (e.g. Rijndael -- the AES is Rijndael with 128-bit blocks and 128-bit, 192-bit or 256-bit keys, but the original Rijndael also has a mode with 256-bit blocks).

To encrypt x with a password, first derive a key from the password (use bcrypt !) and then encrypt x (as a 256-bit string) with Rijndael. If the resulting string is not (when interpreted as a number) in the [0..q-1] range, then encrypt it again, and again, until you get back to the expected range. On average, you'll need to call Rijndael less than twice, so this is not computationally hard.

To decrypt x, just derive a key from the typed password, and apply Rijndael decryption. There again, do it recursively until you get back to the [0..q-1] range.

So this is doable. Is it a good idea ? The advantage of such encryption is that the password can no longer be brute-forced by an attacker who got a copy of the encrypted private key. On the other hand, if the attacker also has a copy of the public key, then he can easily verify that he decrypted with the right password. The public key being, well, meant to be public, it is not necessarily kept as confidential as the private key. The target server has it. Actually, all servers for which the private key is used to login have a copy of the public key. So the public key is only moderately confidential, at best. Therefore, the advantage provided by "unverifiable password encryption" as described above, seems tenuous. On the other hand, it has the following drawback: if the user mistypes his password, the server is still interrogated, and SSH can no longer make the distinction between "user fumbled with his keyboard" and "there's something wrong on the server".

So while what you ask for is feasible for at least some key types, it is understandable that it has not been implemented (yet). It is not an uncontested win; it is a trade-off between usability and security (you would loose a bit of usability to gain a bit of security).

If I steal a pen-drive with the file on it, I can offline brute-force the pass-phrase, just like I can brute-force any other encrypted file. Once I decrypt the file, I have both the public and private keys.

Rarely are keys used for authentication. Normally, they are used to establish a trusted secure channel, after which point you have to authenticate yourself with a username/password. Stealing your pendrive and decrypting the keys will still not give me access to the server, but it will allow me to man-in-the-middle your connection.

Note that you can always generate the public key from the private key, so if the attacker has the public key (which is plausible, it being public) then checking the answer is always trivial. I imagine that this is fundamental to all asymmetric encryption algorithms.

We should assume that the attacker has your public key (the public key is public, and stored on many machines). Given a candidate for the private key, the attacker can use the public key to test whether this candidate is correct (e.g., by checking to see whether the candidate private key correctly decrypts stuff that was encrypted under the public key). Therefore, given a candidate for the password, the attacker will always be able to check its validity by recovering the corresponding private key candidate and then checking it against the public key. This is not specific to the particular public-key algorithm used, or the format for storing and encrypting the private key. It is a fundamental limitation that will be present in almost any imaginable method for storing your SSH private key.

In short, the reason SSH has this risk is because there is realistically no feasible way to avoid the risk.

Therefore, it behooves you to choose a strong passphrase to protect your SSH private key.

SSH doesn't derive the passphrase, it guarantees that the person on the other end has access to some secret information. If you can't understand the math directly, here's a summary that you can take on faith:

I can verify that you know something, without knowing the something myself.

For a more in-depth description of what happens with Diffie-Hellman key exchanges, look at wikipedia. Basically, you can see that performing a certain operation on some numbers gives the result you would expect if I have the secret part of the key, but you don't have an easy way to derive the secret bit. Public keys (in RSA) actually contain all the information in the private keys, but it's hard to get to.

Your Question: i dont understand why it is easy to tell the result of the correct decryption from the result of an incorrect decryption.

I assume you are talking about a client providing an encrypted password to server. In most systems, if you provide the wrong password 3 times, the system will lock you out. In a way this is a denial-of-service attack. So you cannot keep on trying to authenticate until you succeed.

While Diffie-Hellman key exchange --- which by itself is subject to man-in-the-middle-attack when used alone --- is used by client and server to compute the session key, authentication is done by each party by proving to the other that it has the private key corresponding to its public key. But you cannot authenticate without the private key. It is not that the passphrase is used to decrypt the private key and you can keep trying several passphrases and get different 'private' keys and you can try them one by one until it 'works'. The passphrase protects the private key --- analogous to storing a paper with private key in a locker; unless you can open the locker with the right key, you cannot access the paper.

Finally, even if server allows the client the freedom to keep trying to authenticate by brute force, it is computationally infeasible to do, whether it is the 128 bit AES key (symmetric cryptography) or the 1024 bit RSA (public key cryptography). If brute-force attacks were feasible then such a crypto scheme will hardly be useful.

If an attacker has already gained access to the system that contains the private key and copied it, then an offline brute-force or dictionary attack is possible but may not feasible --- it depends on the length and complexity of the passphrase. With a complex passphrase of length 10 with upper/lower case, numbers and special chars, there are 72 ^ 10 possibilities. passphrase is the second line of defense. You need to break in first.
–
Babu SrinivasanApr 12 '11 at 6:34

@caf Yes, This is the question I meant. E.g. If I lose my pendrive with a private key file on it (how) is it possible to brute force the correct key without knowing what public key it relates to.
–
Ben PageApr 12 '11 at 11:29

@Babu Why are you able to tell from the key itself if the passphrase was correct? Why does giving an incorrect passprhrase not decrypt the key into some random 'plain-text' rather than the way I understand it which is if you supply the incorrect key you can find out straight away from only the private key?
–
Ben PageApr 12 '11 at 11:32