129

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?

2
  • 18
    trying to use it
    – user15194
    Commented Jul 11, 2016 at 11:44
  • 5
    @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
    Commented Jul 12, 2016 at 14:57

5 Answers 5

136

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.

5
  • 3
    A 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. Commented Jul 12, 2016 at 0: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
    Commented Jul 12, 2016 at 0:25
  • 12
    More 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
    Commented Jul 12, 2016 at 4:08
  • 9
    This answer is not correct (anymore). A priv key not showing the proc-type and DEK headers can very well be encrypted.
    – GerardJP
    Commented Feb 7, 2019 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
    Commented Dec 20, 2019 at 22:03
115

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...
9
  • 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! Commented Jul 11, 2016 at 13:20
  • 44
    The 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
    Commented Jul 11, 2016 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
    Commented Jul 11, 2016 at 15:36
  • 5
    To 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 Commented Mar 2, 2018 at 14:51
  • 2
    And 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. Commented Feb 11, 2019 at 4:56
18

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.

3
  • 1
    But this could lead to false positives if the encrypted string also starts with MII ?
    – Falco
    Commented Jul 11, 2016 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 <keyfile>). Commented Jul 11, 2016 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 Commented Feb 11, 2019 at 4:52
11

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.

1
  • simply brilliant
    – buncis
    Commented Nov 28, 2023 at 11:26
8

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"
3
  • 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
    Commented Jul 24, 2022 at 8: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
    Commented Aug 4, 2022 at 21:48
  • There are other failure cases, too, such as "Permission denied". So, the command shown really distinguishes if the file is readable and unprotected or if it is not. If you want to distinguish protected vs not exists or not readable (or other such failures), then use extra tests as @Felix suggests.
    – jrw32982
    Commented Mar 14 at 14:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .