yayi C++, python, image processing, hacking, etc

GPG subkeys manipulation: use case for the configuration of Thunderbird

Introduction

GPG is the standard for Internet privacy, its mechanisms are widely used not only in Emails, but also in package signature, authenticity. Its usage is somehow difficult mostly because of the tooling.

Recently Thunderbird, my favorite and beloved open source Email client, took a nice step better integrating with GPG: the project more or less absorbed a plugin, Enigmail, that was used for private email communication and made GPG privacy first class citizen. The integration is ok for the core functions, but lacks some important features. The user experience is catching up.

In this article, I will cover how to deal with one of the important feature of GPG lacking in Thunderbird: the GPG subkeys. I will first explain why this is an important feature and an overall good practice and then explain how to setup a GPG key with only the minimal subkeys for Thunderbird to work.

I am not a cryptography expert, which is good and bad. Bad in the sense that I may do mistakes or inaccuracies that are obvious to experts, but good in the sense that I am taking the user perspective and understanding and my explanations try to advocate the practical benefits of embracing good security practices. And of course, over time we do less and less mistakes.

There are plenty of resources on the Internet, one of the best I can think of is written by the Debian community.

Why GPG subkeys?

To explain why the GPG subkeys are important, I will start by making a little detour in what happened over the past years on the Internet concerning the passwords and user accounts.

We witnessed big players such as Adobe being cyber-attacked, where the hackers gain access to user information. Those leak contain more or less publicly accessible information (name, address, etc) but also more sensitive information such as your credit card number, or a password. This is an excerpt of corresponding Wikipedia article:

In 2013, Adobe endured a major security breach. Vast portions of the source code for the company's software were stolen and posted online and over 150 million records of Adobe's customers have been made readily available for download. In 2012, about 40 million sets of payment card information were compromised by a hack of Adobe.

One can read in the same article:

A 3.8 GB file stolen from Adobe and containing 152 million usernames, reversibly encrypted passwords and unencrypted password hints was posted on XYZ. [...], a password security firm, said that Adobe failed to use best practices for securing the passwords and has not salted them. Another security firm, [...], showed that Adobe used a weak encryption method permitting the recovery of a lot of information with very little effort.

It is not about blaming, that would lead us to nowhere: threats are a reality and we should deal with that. It is not about paranoia neither, we are on the Internet and every body can pretend being anyone or giving you guaranties.

The central element to our understanding is the notion of trust and how we use it, and this is not a surprise that this notion is one of the core design decision of any privacy tool. So let's start by explaining the mechanisms of trust.

Trust as a central design notion

The above security breach tells us several stories.

A user X - let's call her Lilith - registers to a service (a website) - let's call that service www.garden-gnome.com . For completing her registration, she needs to provide personal information (name, date of birth, address). She finalizes her registration by giving a password. That password combined to her username will certify the remote service it is really her using that service. So far, nothing fancy.

Lilith does not necessarily want anyone to know where she lives, but her address is a necessary information for the service to function because www.garden-gnome.com is shipping goods to her home. Giving her password is another such core information.

Now the website www.garden-gnome.com , for a reason or another, got hacked. The hack reached the user database, where all those information are stored. How that database was implemented is secondary: it is only a matter of time that the hackers get to the personal information of Lilith, including her password. And ... Lilith's password got leaked to the world of hackers: the hackers then try one by one other websites, including www.bank.com with various combination of Lilith's personal information as well as the password they reversed. They know that there is a good chance that Lilith has an account in www.bank.com because, for some reason, such an information was stored inside the database. Lilith uses the same password everywhere because she has trouble remember so many of the passwords she has to deal with, the hackers get access to her bank account and send some money to their own bank account through the Vatican. End of story.

Now what happened? Lilith, by providing the information to www.garden-gnome.com , gives trust to that service. That trust consist in personal information including a password. The service on the other hand, wants its customer to trust them, it is good and sane for their business. They did they best to follow the security practices at the time they implemented their website.

Trust is a mutual notion: without it the environment becomes toxic, dangerous, does not promote exchange, etc. We want trust to happen, so how do we mitigate the problem mentioned above?

Mitigation

The immediate observation is that we don't care about the exact password Lilith is using as long as Lilith is able to authenticate herself on that particular service: it can be anything that is unique to the specific service in use. Best is then to use a different password for each service, and now that Lilith knows about KeepassXC or Lastpass, everything works out. The only thing she needs to remember is the master password of her KeepassXC database of passwords: one password (strong, complicated, kept absolutely secret) to rule them all.

On the other side of Internet, the service www.garden-gnome.com does not ask anything beyond what it needs. For instance all the banking related information go through some payment service that delegates the sensitive banking information to the bank directly. www.garden-gnome.com learned that what matters for their service to work is "did she pay yes/no?" kind of answer from the bank.

The mutual trust transformed to something else, that has somewhat lower expectation from each parties:

  1. both parties now know that there is and always be a risk: they are not trying to hide it or to provide doubtful warranties,
  2. Lilith now isolates the aftermath of a password leak, and she provides nothing that can be reused in another context against her will or without her knowing,
  3. the service does not want to be trusted for some sensitive information so they delegate this part to people that know better how to do it right (2FA, etc). Asking less from their customers increases their trust,

Back to GPG and its subkeys

As mentioned above, one of the mechanisms of mitigation through isolation is shifting toward the structure "master password / derived password". Lilith holds one secret that she never shares, her master password, and derives other passwords from it (she generates random ones and stored them encrypted by her master password).

The same mechanism exist in GPG, and this is called subkeys: one master key - kept absolutely safe and never shared - is used to create derived keys called subkeys. It is possible to use the subkeys in various trust contexts: a software, a computer/laptop, a server, etc. If the subkey get compromised, it does not affect the master key and only affects the trust context where that subkey was used.

There are many trust contexts: accessing a remote website is one of them. Another one is when you use a particular device, eg. a laptop or a phone. How much do you trust that device? What operating system is it running? Does it have anti-viruses/malwares? How confident are you it is not running a key-logger? How much would you trust that laptop/phone if it gets stolen?

The mechanism of subkeys provide the same design as the master/derived password mentioned earlier: given a context, a subkey operates in that context only. The mechanism, however, does not issue warranties beyond what it is capable of doing, it mitigates risks by isolation.

I hope it is now clear that subkey is a core design element around trust and a desirable protection everybody would be willing to have. There is however one thing that is sure as of today (in 2022): subkeys are lacking support and tooling, and because of the difficulty in using or understanding them, they are considered as an advanced topic in the GPG.

What is it with Thunderbird then?

It may not be very clear why one would be willing to use subkeys for a software like Thunderbird, so let's talk about this first.

If we abstract the device or OS on which the software is running (see above), Thunderbird will be willing to access your signing or encryption private/secret key when sending emails. For doing so, it needs the passphrase of that key, which is how one unlocks keys.

To ease the life of users, the passphrase of the key is asked only during the import into Thunderbird. Whether the passphrase is stored in the Thunderbird password store or the key passphrase is changed to something that is managed by Thunderbird directly, is an implementation detail. For the record, I have not found the passphrase of that key in the password store, which is a goog thing and the accepted answer here gives details on how it is done, and shows also some concerns of advanced users. The software has then unconditional access to the keys. It is then possible to perform various operations on those keys to the extent permitted by Thunderbird, for instance exporting the keys to a file.

You see immediately that, depending on the technical choices Thunderbird makes and/or your ability to secure it properly, you may expose your GPG key. There is simply too many variables to handle to have peace of mind.

Asking the right questions

You may then think:

  1. how secure is Thunderbird?
  2. how can I secure it more?

Those are valid questions, let's say: the software is secure, the defaults are a tradeoff between ease of on-boarding newbies. It is possible to enforce better security practices by using a master password, or even use full disk encryption on your drive etc. In summary, we trust the software because we have to: there would be no point in using it if it was not the case.

Thunderbird has its weaknesses, like any piece of software, and another angle you may take when questioning your trust about a software could rather be:

  1. do the developers of Thunderbird want to be entrusted unconditionally?
  2. how can we mitigate the risks concerning the secrets we store in there?

On the first point, the EULA clearly states the "The product is provided 'as is' with all faults", and even if the development team should be trusted for doing its best, it is not claiming that it holds the sacred graal of security.

Concerning the second point, it is like it was said earlier: one should put in Thunderbird only the necessary elements such that it operates, and isolate this trust context as much as possible from any other. No free lunch.

Still: how secure is Thunderbird?

For those that are worried about Thunderbird: Thunderbird is secure, it comes with sound defaults and provides all the necessary means to communicate safely. This however does not save us from some level of vigilance:

  1. the defaults are just defaults: they serve sound user experience and ease of use for the average user. The average user can be the one that leaks various passwords on random websites and you may not identify yourself to the average: you have to understand your needs and for doing so, you need awareness on where the problems are.
  2. the passwords are stored in the password manager of Thunderbird: anyone having access to the password manager of Thunderbird will have access to the passphrase of the GPG keys at the time those were installed in Thunderbird. (Having a master password set is not only a good idea: not using this feature is taking a high risk.)
  3. it is possible to export the installed GPG keys to disk and reuse those in another context: those keys may of course then open wide possibilities (signing programs, emails, decrypting files, etc) depending on where you were using those.

Let's do some practice: how do I do it with Thunderbird?

Ok, so now we discussed in length security and contexts, trust and attack surface, let's say we are totally convinced the right way to use GPG keys in Thunderbird is to import into Thunderbird only the necessary subkeys. This is done in 3 steps:

  1. from the original GPG key, we first choose and extract the subkeys
  2. we then edit the key further
  3. we finally export the subkeys to Thunderbird

Extracting the subkeys

GPG is not exactly known to be extremely user friendly, and I found it quite hard to manipulate each subkey separately. Graphical tools are not any better as far as I know, and subkeys are second citizens. The easiest procedure I've found is to import the keys/subkeys into a temporary GPG keystore, perform the manipulations in that temporary keystore and finally export the keys to file after careful inspection.

Let's first start by identifying the keys we need.

Selecting the keys for Thunderbird

In a terminal (you should have already your key in your GPG keychain), we first inspect the available keys:

> gpg --with-subkey-fingerprint --list-secret-keys
/Users/raffi/.gnupg/pubring.kbx
-------------------------------
sec   rsa2048 2014-10-23 [SC] [expires: 2022-10-31]
      EA2915DE9DEE7F2CFC17F36DD4DCF656B16691C4
uid           [ultimate] Raffi Enficiaud <raffi.enficiaud@XXXXX>
uid           [ultimate] Raffi Enficiaud (Alias for Raffi Enficiaud) <raffi.enficiaud@XXXXX>
uid           [ultimate] Raffi Enficiaud (Alias for Raffi Enficiaud) <raffi.enficiaud@XXXXX>
uid           [ultimate] Raffi Enficiaud (Alias for Raffi Enficiaud) <raffi@XXXXX>
uid           [ unknown] [jpeg image of size 203959]
ssb   rsa2048 2014-10-23 [E] [expires: 2022-10-31]
      EAE3D605867868463A630C94513453DFC85067FF
ssb   rsa4096 2015-06-28 [S] [expires: 2022-09-21]
      B8BE2B4E190553E3B0B7C414542B960FF636ACBA
ssb   rsa4096 2021-09-14 [S] [expires: 2025-09-14]
      5972A22ED75F464D86B7D83F12B5AE439236D120
ssb   rsa4096 2021-09-15 [S] [expires: 2025-09-15]
      13140EF28D6C3F5A3BCBEBEC3FB26A16084286C9

--list-secret-keys shows the secrets that are stored in the GPGP keychain (here located /Users/raffi/.gnupg/pubring.kbx), and we really need the --with-subkey-fingerprint otherwise we will have a hard time identifying what is needed for Thunderbird. Another possible command is

> gpg --keyid-format long --with-fingerprint --list-secret-keys
/Users/raffi/.gnupg/pubring.kbx
-------------------------------
sec   rsa2048/D4DCF656B16691C4 2014-10-23 [SC] [expires: 2022-10-31]
      Key fingerprint = EA29 15DE 9DEE 7F2C FC17  F36D D4DC F656 B166 91C4
uid                 [ultimate] Raffi Enficiaud <raffi.enficiaud@XXXXX>
uid                 [ultimate] Raffi Enficiaud (Alias for Raffi Enficiaud) <raffi.enficiaud@XXXXX>
uid                 [ultimate] Raffi Enficiaud (Alias for Raffi Enficiaud) <raffi.enficiaud@XXXXX>
uid                 [ultimate] Raffi Enficiaud (Alias for Raffi Enficiaud) <raffi@XXXXX>
uid                 [ unknown] [jpeg image of size 203959]
ssb   rsa2048/513453DFC85067FF 2014-10-23 [E] [expires: 2022-10-31]
ssb   rsa4096/542B960FF636ACBA 2015-06-28 [S] [expires: 2022-09-21]
ssb   rsa4096/12B5AE439236D120 2021-09-14 [S] [expires: 2025-09-14]
ssb   rsa4096/3FB26A16084286C9 2021-09-15 [S] [expires: 2025-09-15]

where the output is slightly shorter. The information is essentially the same, the fingerprints are shorter: 513453DFC85067FF now corresponds to EAE3D605867868463A630C94513453DFC85067FF in the previous command and as you can see, the part 513453DFC85067FF appears in both. We will refer to the shorter versions in the following.

From the above command, we see:

  • the primary secret key is EA2915DE9DEE7F2CFC17F36DD4DCF656B16691C4: it is used for signing S and for certification C in the [SC], and is identified with the sec part. More on this below.
  • we have then 4 subkeys with secrets ssb, one can be used for encryption [E] and 3 for signing [S].

For Thunderbird to accept the GPG key, we need at least one encryption key and one signing key. The signing key may be the primary key, but since this key is extremely sensitive we want another subkey doing the signing job. So let's pick 513453DFC85067FF and 12B5AE439236D120. Note that there is no # in the sec nor in the ssb: this has an important meaning that we will explain later and any key with a # will not be directly usable in our setup.

Exporting the keys to file

Now we identified an encryption (513453DFC85067FF) and signing (12B5AE439236D120) subkeys, we export them to a temporary file:

> gpg \
     --export-secret-subkeys \
     --armor \
     --output /tmp/key-encryption.asc \
     513453DFC85067FF! \
     12B5AE439236D120!

The ! are important here: they tell gpg to export exactly those subkeys and nothing else.

This will ask the passphrases of the associated subkeys and then create one single file /tmp/key-encryption.asc containing only those 2 subkeys.

Importing the keys to a temporary vault

In the commands above, the default keychain is shown to be stored in the default location /Users/raffi/.gnupg/pubring.kbx: we can change that default from the command line. We will use this feature to manipulate the key in a safe location without putting any risk on our original key that is sitting in the default location.

We start by creating a temporary folder in a more or less "secure" way and initialize a GPG keychain there:

> export tmp_gpg_folder=$(mktemp -d)
> gpg --homedir $tmp_gpg_folder --list-keys
gpg: keybox '/var/folders/some/long/path/pubring.kbx' created
gpg: /var/folders/some/long/path/trustdb.gpg: trustdb created

We will use the variable $tmp_gpg_folder for the following manipulations, we don't really care where this folder is. Besides the information indicating the creation of the keychain - the directory was empty - the output shows no keys as expected.

We now import the previously exported subkeys into that temporary keychain:

> gpg --homedir $tmp_gpg_folder --import /tmp/key-encryption.asc
gpg: key D4DCF656B16691C4: public key "Raffi Enficiaud <raffi.enficiaud@XXXXX>" imported
gpg: key D4DCF656B16691C4: secret key imported
gpg: Total number processed: 1
gpg:               imported: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1

You will be asked for the passphrases (as many times as there are different passphrases for the subkeys, so at much twice).

Listing the content of the keychain now shows:

> gpg --homedir $tmp_gpg_folder --keyid-format long --with-fingerprint --list-secret-keys
sec#  rsa2048/D4DCF656B16691C4 2014-10-23 [SC] [expires: 2022-10-31]
      Key fingerprint = EA29 15DE 9DEE 7F2C FC17  F36D D4DC F656 B166 91C4
uid                 [ unknown] Raffi Enficiaud <raffi.enficiaud@XXXXX>
uid                 [ unknown] Raffi Enficiaud (Alias for Raffi Enficiaud) <raffi.enficiaud@XXXXX>
uid                 [ unknown] Raffi Enficiaud (Alias for Raffi Enficiaud) <raffi.enficiaud@XXXXX>
uid                 [ unknown] Raffi Enficiaud (Alias for Raffi Enficiaud) <raffi@XXXXX>
uid                 [ unknown] [jpeg image of size 203959]
ssb   rsa2048/513453DFC85067FF 2014-10-23 [E] [expires: 2022-10-31]
ssb   rsa4096/12B5AE439236D120 2021-09-14 [S] [expires: 2025-09-14]

Note the # in sec# rsa2048/D4DCF656B16691C4: it means the secret of that key is not available, which is what we want: the D4DCF656B16691C4 is the primary key and we want it safe. We have on top of that exactly

  1. one encryption key with ssb: public and secret part available
  2. one signing key with ssb: public and secret part available

This for instance would not be good:

sub  rsa4096/542B960FF636ACBA
     created: 2015-06-28  expires: 2022-09-21  usage: S

as sub indicates that only the public key is available.

Change the passphrase

This is only needed if you use different passphrases for the subkeys, as Thunderbird is unable to import those.

We are now entering in edit mode for the key. This is a very powerful command and we'll describe some interesting commands later. For now, we just want to change the passphrase:

> gpg --homedir $tmp_gpg_folder --edit-key D4DCF656B16691C4
gpg (GnuPG/MacGPG2) 2.2.32; Copyright (C) 2021 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret subkeys are available.

pub  rsa2048/D4DCF656B16691C4
     created: 2014-10-23  expires: 2022-10-31  usage: SC
     trust: unknown       validity: unknown
ssb  rsa2048/513453DFC85067FF
     created: 2014-10-23  expires: 2022-10-31  usage: E
ssb  rsa4096/12B5AE439236D120
     created: 2021-09-14  expires: 2025-09-14  usage: S
[ unknown] (1). Raffi Enficiaud <raffi.enficiaud@XXXXX>
[ unknown] (2)  Raffi Enficiaud (Alias for Raffi Enficiaud) <raffi.enficiaud@XXXXX>
[ unknown] (3)  Raffi Enficiaud (Alias for Raffi Enficiaud) <raffi.enficiaud@XXXXX>
[ unknown] (4)  Raffi Enficiaud (Alias for Raffi Enficiaud) <raffi@XXXXX>
[ revoked] (5)  Raffi Enficiaud <raffi.enficiaud@XXXXX>
[ unknown] (6)  [jpeg image of size 203959]
gpg>

and we then type:

gpg> passwd

You will be asked for the previous passphrase and for the new single one. You may be asked for more passphrases prompts if you have subkeys with different passphrases and this may be disturbing: in the passphrase window, look at the fingerprint (in red in the picture) you are prompted for.

Passphrase prompt GPG Keychain on macOS

Export the key and import to Thunderbird

The final step is to export the identity (made of 2 subkeys E/S with secrets and the primary key public part) and import it to Thunderbird.

> gpg --homedir $tmp_gpg_folder --export-secret-subkeys --armor --output /tmp/key-encryption.asc

We are done with the temporary folder.

In Thunderbird, go to Menu > Tools > OpenPGP Key manager and then select Import secret key(s) from file, select the file /tmp/key-encryption.asc and enter the passphrase.

Now inspect the key property and select the "structure" tab, you should see something like this:

Key structure

It properly shows:

  • one primary key with an (!), which indicates the secret is not available
  • 2 subkeys, one for encryption and one for signing (without the (!) sign)

We are all good!

Conclusion

GPG is a really nice, powerful project and now that is entirely part of Thunderbird, learning good practices such as the subkeys and how to make it work with Thunderbird seems to be a good time.

By partitioning the trust contexts, GPG subkeys are the analog of the rule "one password, one website" we now use regularly on the web. Often simply flagged as a "good practice", we have taken a deeper dive into how the design of subkeys mitigates various risk we trusting a software or a device. Subkeys are however deemed an advanced feature and the tooling is not making it easy to use.

This article gave easy steps for manipulating keys in the context of their use in a trusted software, our lovely Thunderbird. The operations of inspecting, selecting and extracting a subset of subkeys, editing, removing unwanted secret parts, are in fact not that hard and of course can be applied in any trust/security context other than Thunderbird.

Good guidance serves good practices and I hope to see more and more people using advanced features of GPG within Thunderbird.

A bit(e) more on GPG

You did not have enough? Here some more information about GPG.

Various cryptic GPG symbols: cheat sheet

Because we are humans, we need sometimes a little help to understand what the tools are trying to tell us. Especially we need to understand the output of the gpg --list-secret-keys: without it, doing something intelligent with the keys will be hard.

> gpg --keyid-format long --with-fingerprint --list-secret-keys
[...]
sec   rsa2048/D4DCF656B16691C4 2014-10-23 [SC] [expires: 2022-10-31]
      Key fingerprint = EA29 15DE 9DEE 7F2C FC17  F36D D4DC F656 B166 91C4
uid                 [ultimate] Raffi Enficiaud <raffi.enficiaud@XXXXX>
ssb   rsa2048/513453DFC85067FF 2014-10-23 [E] [expires: 2022-10-31]
ssb   rsa4096/542B960FF636ACBA 2015-06-28 [S] [expires: 2022-09-21]
ssb   rsa4096/12B5AE439236D120 2021-09-14 [S] [expires: 2025-09-14]
ssb   rsa4096/3FB26A16084286C9 2021-09-15 [S] [expires: 2025-09-15]

Let's start with the simplest: uid means User ID and is basically your identity. As shown in examples above, you may attach several uids to a specific key.

About the sec, ssb etc in front of each line, here is the meaning:

SymbolMeaning
secSECret key
ssbSecret SuBkey
pubPUBlic key
subpublic SUBkey

About the parts in brackets, [SC], [E] etc:

SymbolMeaning
Ckey Certification
SSign data
EEncrypt communications/storage
AAuthentication

I really don't know what Authentication means in this setup and never seen it in use.

GPG edit mode

The edit mode is very convenient once we start using the --homedir command line option: we can experiment and mess up with that command without impacting much the original identity.

We start by selecting a specific key, for instance 3FB26A16084286C9, this is done with the key command in the prompt:

gpg> key 3FB26A16084286C9

sec  rsa2048/D4DCF656B16691C4
     created: 2014-10-23  expires: 2022-10-31  usage: SC
     trust: unknown       validity: unknown
ssb  rsa2048/513453DFC85067FF
     created: 2014-10-23  expires: 2022-10-31  usage: E
ssb  rsa4096/542B960FF636ACBA
     created: 2015-06-28  expires: 2022-09-21  usage: S
ssb  rsa4096/12B5AE439236D120
     created: 2021-09-14  expires: 2025-09-14  usage: S
ssb* rsa4096/3FB26A16084286C9
     created: 2021-09-15  expires: 2025-09-15  usage: S
[ unknown] (1). Raffi Enficiaud <raffi.enficiaud@XXXXX>

The selected subkey has now an * in front.

We can now do various things, let's delete that key completely:

gpg> delkey
Do you really want to delete this key? (y/N) y

sec  rsa2048/D4DCF656B16691C4
     created: 2014-10-23  expires: 2022-10-31  usage: SC
     trust: unknown       validity: unknown
ssb  rsa2048/513453DFC85067FF
     created: 2014-10-23  expires: 2022-10-31  usage: E
ssb  rsa4096/542B960FF636ACBA
     created: 2015-06-28  expires: 2022-09-21  usage: S
ssb  rsa4096/12B5AE439236D120
     created: 2021-09-14  expires: 2025-09-14  usage: S
[ unknown] (1). Raffi Enficiaud <raffi.enficiaud@XXXXX>

Then we save and exit:

gpg> save

Finally I remove the secret attached to the primary key:

gpg --homedir $tmp_gpg_folder --delete-secret-key D4DCF656B16691C4!

where the ! is important otherwise all secrets will be deleted and the key will become worthless.

All in all, I find this way of selecting the subkeys I need much easier.

References

The interpretation of the key parts was taken from this article.