21

There are several questions which discuss the resistance of passphrase-protected private gpg keys against brute force attacks. It seems, this kind of discussion could go on forever.

Rather than starting yet another of these endless discussions, I would just like to ask which concrete options/parameters I can change in my gpg.conf to make my passphrase-protected private gpg key more secure.

From what I understand, the default options are chosen mainly for compatibility, rather than maximum security. For example, the default number of iterations s2k-count is 65536, so that even slow arm processors can compute it in milliseconds.

I don't care about slow arm processors. I would rather wait 100 milliseconds longer, and have my passphrase iterated 65011712 times.

I am not a crypto expert. Can somebody please suggest other options which could be changed from the defaults? At the moment, I have the following in my gpg.conf.

cipher-algo AES256
s2k-count 65011712

I am using gnupg 1.4.12 on Debian Wheezy

UPDATE (for the bounty):

Are there really no other parameters apart from cipher-algo and s2k-count that I can change, to make my password-protected secret key more resistant to a potential (brute-force) cryptographic attack ?

In particular, I don't like the idea that the default algorithm used for hashing the key is SHA1. Is this algorithm not obsoleted?

Should I not use s2k-digest-algo SHA256 instead ? Or is there a good reason to use SHA1 (i.e. hash size) ?

11
+250

Reasonable Defaults for s2k

You can tune multiple parameters. The s2k-mode should generally stay on it's default value, 3: this uses both a salt and repeats salt and passphrase during application of the digest function. Further parameters are the symmetric encryption algorithm (s2k-cipher-algo), the digest algorithm (s2k-digest-algo) and (if mode 3 is used) the number of repetitions of hash and passphrase, increasing the amount of data to be hashed (s2k-count). All of those options can either be set in the GnuPG configuration file ~/.gnupg/gpg.conf or on the command line (prefixed with --, for example --s2k-digest-algo).

For the three "tunable" options, you have to balance execution time and security.

  • s2k-cipher-algo: As the amount of data to encrypt is very small, it does not really matter how much overhead is spent on encryption without a notable difference. The default AES128 should probably be fine, but why not use the additional security margin if we won't suffer from a notably higher computation effort?
  • s2k-digest-algo and s2k-count have impact on the time spent on hashing while trying to crack the passphrase. The default SHA-1 has some known weaknesses and is considered outdated, so choose some algorithm of the SHA-2 suite. While writing this answer, 65011712 repetitions and SHA512 resulted in each decryption operation taking a notable delay but far below a second on my mobile Core i7; if the decrypted key is cached in gpg-agent anyway probably something one could live with.

    I'm not aware of a discussion of reasonable defaults here, usually the recommendation is to make hashing as expensive as you can accept.

I don't care about slow arm processors. I would rather wait 100 milliseconds longer, and have my passphrase iterated 65011712 times.

If you really don't mind, the "heavy-duty" configuration will be

s2k-mode 3              # default anyway
s2k-cipher-algo AES256
s2k-digest-algo SHA512
s2k-count 65011712

For a still-totally-fine, but faster configuration reduce the computation effort for hashing by using a smaller value for s2k-count or SHA256. AES128 as cypher is fine, but does not result in a notable faster computation.

Using those Defaults for Private Key Encryption

TL;DR: You need to trigger saving the key again (for example by changing the passphrase), as exporting just dumps from hard disk. GnuPG 2.1 (modern) is affected by a bug.

The longer version:

You have to discriminate between several uses of digest algorithms in OpenPGP/GnuPG.

OpenPGP Fingerprints

For calculating fingerprints, OpenPGP requires keys to be hashed using SHA1, as you can read up in RFC 4880, Section 12.2, Key IDs and Fingerprints:

A V4 fingerprint is the 160-bit SHA-1 hash of the octet 0x99, followed by the two-octet packet length, followed by the entire Public-Key packet starting with the version field.

There is no choice or possibility to configure this. We will observe this again further down.

Modification Detection Code Packet

The Modification Detection Code Packet also uses an SHA-1 hash to protect encrypted messages from being manipulated, no choice is left for configuration. This is not really relevant for the further discussion, I just mentioned it for completeness.

Symmetrically Encrypted Session Key and Data Packages

These package are used both in "normal" OpenPGP messages encrypted for a public key, where they again contain the literal data package and for messages encrypted with a passphrase.

In the first case, the symmetric key is encrypted using an asymmetric algorithm like RSA, no passphrase (or hashing of such one) is involved.

It can also be used to encrypt a message symmetrically based on a passphrase, for example using gpg --symmetric, which will ask for a passphrase and encrypt from STDIN. The pgpdump (a tool similar to `gpg --list-packets, but sometimes providing more suitable output) output of such a message looks like

$ echo "foo" | gpg --passphrase "bar" --symmetric | pgpdump
Old: Symmetric-Key Encrypted Session Key Packet(tag 3)(13 bytes)
    New version(4)
    Sym alg - CAST5(sym 3)
    Iterated and salted string-to-key(s2k 3):
        Hash alg - SHA1(hash 2)
        Salt - 1d cd 72 c8 c3 30 df 84 
        Count - 65536(coded count 96)
New: Symmetrically Encrypted Data Packet(tag 9)(26 bytes)
    Encrypted data [sym alg is specified in sym-key encrypted session key]

Observe the settings for the string-to-key procedure: the digest algorithm (SHA1 as default), and the mangle count. These can be configured using --s2k-digest-algo and --s2k-count. Lets see what happens if we set those to SHA512 and the maximum of 65011712:

$ echo "foo" | gpg --passphrase "bar" --s2k-digest-algo SHA512 --s2k-count 65011712 --symmetric | pgpdump
Old: Symmetric-Key Encrypted Session Key Packet(tag 3)(13 bytes)
    New version(4)
    Sym alg - CAST5(sym 3)
    Iterated and salted string-to-key(s2k 3):
        Hash alg - SHA512(hash 10)
        Salt - ea 62 a1 ff 0b 2b f6 6a 
        Count - 65011712(coded count 255)
New: Symmetrically Encrypted Data Packet(tag 9)(26 bytes)
    Encrypted data [sym alg is specified in sym-key encrypted session key]

We successfully changed the passphrase mangling options using the --s2k-... options.

Passphrase Protected Exported Secret Keys

Now, let's get to one more use of the string-to-key procedure, encrypting exported secret keys. RFC 4880, 5.5.3. Secret-Key Packet Formats indicates the same string-to-key procedure should be in use, but indeed, --s2k-digest-option and --s2k-count have no effect any more:

$ gpg --s2k-digest-algo SHA512 --s2k-count 65011712 --export-secret-subkeys 0xDEADBEEF | pgpdump
[snip]
Old: Secret Subkey Packet(tag 7)(510 bytes)
    Ver 4 - new
    Public key creation time - Mon Jun  1 16:06:06 CEST 2015
    Pub alg - RSA Encrypt or Sign(pub 1)
    RSA n(1024 bits) - ...
    RSA e(17 bits) - ...
    Sym alg - CAST5(sym 3)
    Iterated and salted string-to-key(s2k 3):
        Hash alg - SHA1(hash 2)
        Salt - ab 7d c8 36 6a 67 4d dd 
        Count - 65536(coded count 96)
    IV - e9 76 d3 c4 b0 de 24 3c 
    Encrypted RSA d
    Encrypted RSA p
    Encrypted RSA q
    Encrypted RSA u
    Encrypted SHA1 hash
[snip]

This actually puzzled me for quite a while.

The solution was rather easy, though: gpg --export simply exports the key from the secring.gpg as-is. Setting the option for gpg --edit-key (through parameters or the gpg.conf file) and subsequently changing the passphrase using passwd triggers writing the encrypted key to the secring.gpg again -- and voilà, the key is encrypted as we wanted it to be, we don't even have to set the --s2k-... options during export any more:

$ gpg --export-secret-subkeys 0xDEADBEEF | pgpdump
[snip]
Old: Secret Subkey Packet(tag 7)(510 bytes)
    Ver 4 - new
    Public key creation time - Mon Jun  1 16:06:06 CEST 2015
    Pub alg - RSA Encrypt or Sign(pub 1)
    RSA n(1024 bits) - ...
    RSA e(17 bits) - ...
    Sym alg - CAST5(sym 3)
    Iterated and salted string-to-key(s2k 3):
        Hash alg - SHA512(hash 10)
        Salt - e1 82 c3 9f 07 74 7f 0c 
        Count - 65011712(coded count 255)
    IV - 97 20 69 ae 8d ec 0d 3c 
    Encrypted RSA d
    Encrypted RSA p
    Encrypted RSA q
    Encrypted RSA u
    Encrypted SHA1 hash
[snip]

GnuPG 2.1 (modern)

As of 2015-06-01, GnuPG 2.1 ("modern" branch) is affected from a bug (GnuPG Issue #1800): here, the gpg-agent takes care of all those operations, but does not care about the --s2k-... options at all. This should be resolved soon, as the bug was already marked as urgent by Werner Koch, GnuPG's main developer.

  • if I set s2k-cipher-algo to AES256, should not s2k-digest-algo be a hash function producing digest of the same size, i.e. SHA256 rather than SHA512 ? – Martin Vegter Jun 1 '15 at 19:10
  • hm, strange: I have added personal-digest-preferences SHA512 SHA256 SHA384 SHA224 SHA1 into my config file, and then generated a key. But the digest preferences of the newly generated key have default values: pref-hash-algos: 8 2 9 10 11. My prefs are being ignored. – Martin Vegter Jun 1 '15 at 19:39
  • These both actually form great questions, but aren't really related to this one (and the answer already got rather... lengthy). I'd propose you ask two new ones? – Jens Erat Jun 1 '15 at 20:23
2

Your GnuPG configuration parameters are already strong enough. Concerning SHA-1 weaknesses, they are, in practice, not so important as one might think. From the GnuPG manual:

Although the SHA-1 algorithm shows signs of weaknesses as well, it is still very hard and time consuming to create collisions. Mounting a pre-image attack is still far out of reach. Thus for the standard use of GnuPG, the signature based on SHA-1 are still fine. To be prepared for future developments, GnuPG is moving forward and some defaults have been changed to prefer SHA-256 over SHA-1. If in a few years the installed code base of modern GnuPG versions is large enough we are prepared to deprecate SHA-1 then.

Perhaps this is not the exact answer you're looking for, but if you want to strengthen your GnuPG installation my suggestion is to store the private key into a encrypted disk, and especially choose a strong passphrase for the private key (and for the private keyfile container, different from the GnuPG passphrase). The basic rules for strong passwords are:

  1. Composed of lowercase and uppercase characters, digits, and symbols
  2. Random-looking i.e. not showing any predictable pattern, whenever possible
  3. The longer, the better
  4. Stored only in your mind

You will have to find a compromise between points #2 and #4 as random-looking passphrases are hard to remember.

  • The above cited text speaks about SHA-1 hash in context of signing messages. But my question is about hash algorithm in context of protecting my private key (i.e. "key stretching"). – Martin Vegter May 31 '15 at 12:24
  • In which case the hash algorithm might just as well have been MD5, and still be secure. – Maarten Bodewes Jun 2 '15 at 21:00
1

You can put some paranoid options to your ~/.gnupg/gpg.conf. Check mine. It forces gpg to use strong AES algorithms, hashes your password 20000000 times before it uses it as a key which makes brutal force attack much more difficult.

s2k-cipher-algo AES256
s2k-digest-algo SHA256
cipher-algo AES256
digest-algo SHA256
s2k-count 20000000
s2k-mode 3
force-mdc
  • 1
    OPs parameters are equal or stronger than yours: he is already using AES256, the digest does not matter in passphrase strength and mdc/mode3 are defaults (source: man gpg) – Enos D'Andrea Dec 22 '14 at 19:07
  • @Enos - what do you mean " the digest does not matter in passphrase strength". Is s2k-digest-algo SHA256 not better than the default sha1 ? – Martin Vegter May 30 '15 at 22:22
  • @MartinVegter the SHA1 weakness (collisions attack) only makes sense against signatures, not against password mangling where subsequent straight hashings are used. I stand corrected in that SHA256 is 30% slower than SHA1 so it does provide a negligible advantage. – Enos D'Andrea Jun 1 '15 at 21:53
1

If someone can steal your encrypted key, then they can read your private files: chances are they can execute code into your machine and sniff your key password (however strong).

A GnuPG smartcard with an external keypad protects both the card and the password.

Edit: You could also patch GPG to allow higher values for s2k-count.

  • are you suggesting that protecting your private key with a strong passphrase is absolutely useless ? – Martin Vegter Dec 14 '14 at 12:41
  • All I am saying is that a chain is as strong as its weakest link. All the strongest link can do is give a false sense of security. – Enos D'Andrea Dec 14 '14 at 19:57
  • 1
    You cannot know in advance which link will be the weakest. Therefore, you need to make each link as strong as possible. – Martin Vegter Dec 15 '14 at 9:14
  • 1
    "As strong as possible" is asymptotic: you risk spending all your time hardening the first link. A risk assessment and subsequent tackling of the weakest links allows efficiently distributing hardening efforts. – Enos D'Andrea Dec 20 '14 at 9:48
-1

As far as the bounty goes - no, there are no parameters in GPG configuration you could change to harden your passphrase beyond reasonable use. It is also not a good idea to focus on one link in the whole security chain. Your key itself is as safe as it gets in the environment you store it in, assuming your passphrase is strong enough and not stored anywhere else than in your head. Next step is securing the environment. Move your key to a HSM or a smartcard, make sure there are no rootkits or keyloggers on your computer and your agent isn't compromised. Do a risk analysis, figure out the weaknesses and focus on weakest links - encrypted private key is not one of them.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.