99

Say I have previously created a private/public key combination, and decided at the time to not protect the private key with a password. If I later decide to "beef up" security and use a password-protected private key instead, would I need to generate a new private/public key pair, or can I simply add a password to my existing private key?

Is the opposite possible as well, can I "remove" a password from an existing private key?

IQAndreas
  • 6,557
  • 8
  • 32
  • 51

4 Answers4

124

A word of caution: as stated in laverya's answer openssl encrypts the key in a way that (depending on your threat model) is probably not good enough any more.


Of course you can add/remove a passphrase at a later time.

  • add one (assuming it was an rsa key, else use dsa)

    openssl rsa -aes256 -in your.key -out your.encrypted.key
    mv your.encrypted.key your.key
    chmod 600 your.key
    

    the -aes256 tells openssl to encrypt the key with AES256.

    As ArianFaurtosh has correctly pointed out: For the encryption algorithm you can use aes128, aes192, aes256, camellia128, camellia192, camellia256, des (which you definitely should avoid), des3 or idea

  • remove it

    openssl rsa -in your.key -out your.open.key
    

    you will be asked for your passphrase one last time
    by omitting the -aes256 you tell openssl to not encrypt the output.

    mv your.open.key your.key
    chmod 600 your.key
    
Xander
  • 35,525
  • 27
  • 113
  • 141
guntbert
  • 1,825
  • 2
  • 18
  • 21
  • 3
    That's only for OpenSSL and things compatible with it, which is quite a few but far from all. And as correctly noted by laverya, OpenSSL's 'legacy' privatekey (PEM) encryption uses a _very_ weak PBKDF -- one iteration of MD5. You can do better (though not best) with `pkcs8 -topk8 [-v2 $cipher]` and in 1.1.0+ add `-niter $n` with the highest count you can afford (the default, and before 1.1.0 the only value, is 2048). – dave_thompson_085 Feb 12 '19 at 02:28
  • 1
    @dave_thompson_085 this should be an answer. The `openssl pkcs8 -topk8` command in modern versions of openssl can do scrypt or bcrypt with some large number of iterations. Even in older versions, it can do pbkdf2 with 2048 iterations. Depending on your openssl version, you may be stuck with Triple-DES as the cipher. – Brian Minton May 17 '19 at 03:30
  • @BrianMinton: sorry I missed this at the time, but this Q somehow got revived. 1.1.0+ supports scrypt, which I didn't notice before, but not bcrypt. OTOH I don't recall _any_ version limited to TDES for the cipher -- the oldest version I can still run, 0.9.8m from 2010 on a VM, supports PBES2 with AES, and Blowfish CAST IDEA as well as DES DES3. (Conversely with PBES1 or PKCS12PBE you are limited to DES3 -- or DES or RC2, both now useless -- by the scheme definitions in those now-aging RFCs, even on newest OpenSSL.) – dave_thompson_085 Dec 25 '20 at 05:14
29

While Guntbert's answer was good at the time, it's getting a little outdated. openssl rsa -aes256 creates an encrypted file using the md5 hash of your password as the encryption key, which is weaker than you would expect - and depending on your perspective that may in fact be worse than plaintext. (If you use the same password for your ssh key and your login, cracking the md5 hash will be significantly faster than attacking however your system stores the password - barring things like Windows XP)

A modern solution would be to use ssh-keygen -p -o -f PRIVATEKEY, which will allow you to enter a passphrase and then will overwrite the existing private key with the encrypted version. This uses the bcrypt pbkdf, which is FAR slower than md5 even when running at the default 16 rounds. 'Far slower' in this case means between a tenth and a half of a second, instead of a millionth of a second - not something you'll notice when logging in, but a massive difference when cracking passwords.

mwfearnley
  • 132
  • 6
laverya
  • 391
  • 3
  • 4
  • 1
    It's worth noting that what openssh implemented has several differences to standard bcrypt. The most visible change is that "rounds" is actually the number of times the password is hashed with sha512, then hashed again with bcrypt using 64 rounds to derive the key then 64 rounds of encrypting a known block. Standard bcrypt uses `2^cost` rounds to derive the key then 64 rounds of encrypting a known block. For the equivalent of a normal bcrypt cost like 14, it should be roughly `2^14/128 = 128`, though it's not quite the same as openssh spends more time encrypting. – AndrolGenhald Feb 11 '19 at 20:06
  • If you don't want the (stronger) new openssh key format, remove `-o`. Some applications doesent recognize it. – Kuronashi Jul 29 '20 at 07:45
  • https://latacora.singles/2018/08/03/the-default-openssh.html is a broken link – hanzo2001 Aug 06 '20 at 09:10
  • updated to use archive.org for that broken link @hanzo2001 - thanks for the spot! – laverya Aug 08 '20 at 00:38
  • @JohannSchwarz+ since OpenSSH 7.8 in 2018-08, 'new format' is the default and you don't need `-o`; if you want old format, which as explained is very weak, specify `-m pem`. _Almost_ everything that can read OpenSSH-old (aka OpenSSL-legacy) can also read PKCS8 which as I noted on the other answer is more secure, especially since the improvements in OpenSSL 1.1.0 (2016); OpenSSH (since almost forever) can _read_ PKCS8 but not write it. – dave_thompson_085 Aug 09 '20 at 01:49
  • *A modern solution would be to use ssh-keygen -p -o -f PRIVATEKEY, which will allow you to enter a passphrase and then will overwrite the existing private key with the encrypted version.* Could you please shortly explain how to use such keys with openssl? I have tried it, and obviously my openssl version can't use it (`unable to load Private Key 139703991919744:error:0909006C:PEM routines:get_name:no start line:../crypto/pem/pem_lib.c:745:Expecting: ANY PRIVATE KEY`) – Binarus Sep 25 '20 at 14:01
  • 1
    @Binarus+ the OpenSSH 'new' format created by `-o` below 7.8 and by default since is not usable with OpenSSL at all. You can use `ssh-keygen` to convert it to 'old' format which is OpenSSL compatible. puttygen in recent versions of PuTTY can also handle it, and has several output options. – dave_thompson_085 Dec 25 '20 at 05:18
  • @dave_thompson_085 Thanks for your comment. Then I have misunderstood this answer. The first paragraph talks about OpenSSL and its insecure passphrase encryption, while the second paragraph start with "A modern solution ...". This made me believe that I had missed something and that I could use OpenSSH keys somehow with OpenSSL. Thanks for clarifying. Thanks also for the hint regarding putty. Unfortunately, putty couldn't handle OpenSSH passphrases protected by `-o` for ages, so I lost patience several months ago and dumped it. Instead, I now have installed cygwin and use its SSH. – Binarus Dec 25 '20 at 14:20
15

When a private is "protected by a password", it merely means that the key bytes, as stored somewhere, are encrypted with a password-derived symmetric key. A private key is readily encodable as a sequence of bytes, and can be copied, encrypted and decrypted just like any file. The important point here is that the password is all about storage: when the private key is to be used (e.g. to sign something), then it is first decrypted in the RAM of some computer, which then proceeds to use the non-encrypted private key. Correspondingly, there is nothing special in a RSA key pair which would make it suitable or unsuitable for password protection. Password protection is really an orthogonal issue.

Of course, if a private key has ever been stored on some physical medium (say, a hard disk) without any extra protection, then it may have left exploitable traces there. Details depend a lot on what system is actually used for private key storage. For instance, Windows systems use DPAPI for storing user's private keys, and DPAPI makes some extra efforts at not letting stored keys leak (whether these efforts are successful remains to be proven).

Thomas Pornin
  • 320,799
  • 57
  • 780
  • 949
  • 2
    May I suggest you explain the meaning of "orthogonal" in this case? – guntbert Jun 01 '14 at 16:57
  • 4
    @guntbert, in this context 'orthogonal' could be defined as "related but separate". Ie. the issues of certificate validity and certificate security are related (in that they both affect the security and functioning of the system) but they're distinct problems and their solutions don't directly interact. – Molomby Mar 22 '16 at 03:52
  • 3
    Your machine might be compromised in such a way that an attacker can read all your files on your mounted encrypted harddisk, but can't read your ram. In this threath model encrypting your private key gives you extra security. – Jens Timmerman Dec 14 '17 at 11:08
8

openssl rsa supports only RSA keys and its encryption is susceptible to brute-forcing.

It's better to use openssl pkcs8 - it uses a key derivation function and supports RSA, ECC and Edwards keys:

openssl pkcs8 -topk8 -in source.key -out encrypted.key

For even better security use the scrypt KDF:

openssl pkcs8 -topk8 -scrypt -in source.key -out encrypted.key

To decrypt a pkcs8 encrypted key, drop the -topk8 flag:

openssl pkcs8 -in enc.key -out dec.key
rustyx
  • 751
  • 6
  • 10
  • In OpenSSL 3.0.x (since 2021-09) `rsa` writes PKCS8 by default, though it remains as you say limited to RSA (and only the original rsaEncryption OID, not rsassa-pss). – dave_thompson_085 Sep 21 '22 at 06:53