Let's say I have access to the private portion of an RSA key-pair. How can I check if this key has associated passphrase or not?
-
18trying to use it – The Illusive Man Jul 11 '16 at 11:44
-
4@Ayozint Now sit back and wait for the questions on how to set up a dummy ssh server for the purpose, and how to kill a `ssh` process prematurely from a script after matching the string asking for a password. – nitro2k01 Jul 12 '16 at 14:57
5 Answers
The keyfile will have a different header if it is password protected. Here's the top of a key without a passphrase:
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEA3qKD/4PAc6PMb1yCckTduFl5fA1OpURLR5Z+T4xY1JQt3eTM
And here's the top of a key which is passphrase-protected:
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,556C1115CDA822F5
AHi/3++6PEIBv4kfpM57McyoSAAaT2ECxNOA5DRKxJQ9pr2D3aUeMBaBfWGrxd/Q
Unfortunately, that only works looking at the files. I know of no way for a server to be able to tell if the keys being presented to it were protected with a passphrase, which is the most useful place to be able to leverage that sort of info.
- 72,355
- 17
- 162
- 199
-
3A solution based on the timing could work. In case of an unencrypted key, the response is usually sent instantly as soon as the server sends the challenge, where as for an encrypted one it takes at least a few seconds for the user to enter the passphrase to decrypt the key. – André Borie Jul 12 '16 at 00:04
-
11@AndreBorie, unfortunately the client can't be trusted. Normal usage may have no delay if a key agent is caching the (phrased) key, and a malicious client could introduce fake delays to "mimic" unlocking the key... We went through the same thing 20 years ago with "timing analysis of password entry" on protocols like telnet :) – gowenfawr Jul 12 '16 at 00:25
-
12More generally, encryption of the key is a totally *client-side* operation. If you want to know that the key is encrypted, it needs to live and be decrypted server-side. But then the server has the decrypted private key, which rather defeats the point of asymmetric cryptography. – Kevin Jul 12 '16 at 04:08
-
6This answer is not correct (anymore). A priv key not showing the `proc-type` and `DEK` headers can very well be encrypted. – GerardJP Feb 07 '19 at 13:27
-
@GerardJP I interpret the answer as saying that if the `proc-type` and `DEK` header lines are missing, then it is not password protected. I don't think it is talking about whether or not something is encrypted. – bgoodr Dec 20 '19 at 22:03
It is not always so easy as described in the other answers. It works only with the old PEM keys. New openssh
format of the keys (generated with -o
option, more secure, since openssh-6.5) looks the same if you check the headers:
$ head rsa_enc
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABCYdi7MhY
$ head rsa
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
The easiest way in this case is to run some operation on them using ssh-keygen
. If it will ask for a passphrase, it has one (or it is not a ssh key), if not it does not have a passphrase:
$ ssh-keygen -yf rsa_enc
Enter passphrase:
$ ssh-keygen -yf rsa
ssh-rsa AAAAB3NzaC1y...
Maybe even better is the following example, since it doesn't ask for input: -P specifies the passphrase to use, an unprotected key opens with an empty passphrase.
$ ssh-keygen -y -P "" -f rsa_enc
Load key "path_to_key": incorrect passphrase supplied to decrypt private key`
$ ssh-keygen -y -P "" -f rsa
ssh-rsa AAAAB3NzaC1y...
-
More secure but less compatible: they perceived the fact that the known ASN.1 structure was also encrypted as facilitating the brute-force attacks, and therefore left out the standard storage to create their own storage format where the attacker can rely on no previously known text. Thanks! – WhiteWinterWolf Jul 11 '16 at 13:20
-
41The base64-encoded data does contain information about whether the key is encrypted, though: The first decodes to `openssh-key-v1.....aes256-cbc....bcrypt.........v..` and the second decodes to `openssh-key-v1.....none....none................ssh-` – Random832 Jul 11 '16 at 15:34
-
2@Random832 you are right. Thanks. But it is not so obvious as in the first case where it is in ASCII. – Jakuje Jul 11 '16 at 15:36
-
Well, base64 always maps three input characters to four output characters, so there is a chance that you could spot the encoded `non` or `one` of `none`, depending on what the exact offset of that string in the file is. – Ulrich Schwarz Jul 12 '16 at 05:28
-
-
-
@immibis Yes. Fixed now. Thanks for the note. Copy paste error. But the point was probably clear. – Jakuje Jul 12 '16 at 11:12
-
3To whoever wondering what does the `-yf` option do: *-y: This option will read a private OpenSSH format file and print an OpenSSH public key to stdout*, and `f` just stands for file path. [source](https://linux.die.net/man/1/ssh-keygen) – ᴍᴇʜᴏᴠ Mar 02 '18 at 14:51
-
2And in 2018 (beginning with 7.8) new format is now the _default_ and `-o` is not needed (you can still get old=OpenSSL format except for ed25519 with `-m pem`) FWIW PuTTY has its own 'ppk' format (also text+base64, but not PEM) with the second line specifying encryption or not. – dave_thompson_085 Feb 11 '19 at 04:56
The "RSA key" is actually a set of values stored as an ASN.1 structure in the standardized DER binary format, then encoded in base-64 to get the final PEM file.
A very easy way to determine whether a key is encoded or not is simply to check whether the ASN.1 header is present, and this is usually as simple as checking if the "key" begins with the letters MII
as in the example below:
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQCWxk9djtgA/t7n6M8g1d2fk3exyCSu1uubpxUkoFLJBKjLYiaa
[...]
eCrpRFHxhPICHI4db+I8GZ9QDmlbCN/bl3BBNNTn3w==
-----END RSA PRIVATE KEY-----
In password protected files, the whole ASN.1 structure being encrypted, it all appears as random characters.
- 19,142
- 4
- 59
- 107
-
1But this could lead to false positives if the encrypted string also starts with MII ? – Falco Jul 11 '16 at 13:49
-
4@Falco: Yes. On a practical basis, it is a good heuristic for instance to quickly check a set of unknown keys, but the only way to have a 100% guaranty about the key status (encrypted, corrupted, etc.) is by by using the method provided in Jakuje's answer (`ssh-keygen -yf
`). – WhiteWinterWolf Jul 11 '16 at 15:12 -
Simpler _and_ robust: OpenSSL 'traditional' format PEM-level encryption has two header lines plus a blank line before the encrypted&base64'd data, as shown in gowenfawr's answe – dave_thompson_085 Feb 11 '19 at 04:52
Private keys should be secured, trying to set the password just declares if it is yet password protected. With ssh-keygen
on the protected key:
~/.ssh$ ssh-keygen -p -f id_rsa_password_protected
Enter old passphrase:
And with not protected:
~/.ssh$ ssh-keygen -p -f id_rsa_not_protected
Enter new passphrase (empty for no passphrase):
So if it is not password protected, just set the password.
- 201
- 2
- 4
While the other answers give valid answers to achieve this manually, the following approach can be used within a shell script for automation.
The following command's exit code determines whether the key file found at $path_to_keyfile
has a password:
ssh-keygen -y -P "" -f "$path_to_keyfile" &>/dev/null
To use this command within a script that checks for this you could either use the following snippet
if ssh-keygen -y -P "" -f "$path_to_keyfile" &>/dev/null; then
echo "unprotected"
else
echo "protected"
fi
or use &&
and ||
as shorthands like so:
ssh-keygen -y -P "" -f "$path_to_keyfile" &>/dev/null && echo "Unprotected" || echo "Protected"
- 151
- 1
- 2
-
This is a good answer. Only problem is not the guard against the case the file doesn't exist. In this case you'll also get a non zero status. Maybe it's best to parse the output of `incorrect passphrase supplied to decrypt private key` to double-check it. – strboul Jul 24 '22 at 08:13
-
@strbout I would check for the file before executing the line with `ssh-keygen`, e.g. using `test -f "$path_to_keyfile" || exit 1` to abort, when the file does not exist. – Felix Aug 04 '22 at 21:48