What is the Web of Trust?
This is the second article in a series about GPG and public-key encryption. This part doesn't depend on the previous part about generating and using a keypair but you may want to read that first anyway for background.
Now that you've got a keypair there are a couple of issues to address: how do other people find it and how can they verify that it's really your key? Anybody can generate a key for any arbitrary email address so what can you do to make sure you have the real one? It's called the web of trust and it's a pretty neat solution to that problem.
What is a Web of Trust?
The math of asymmetric keys means that we can use them to sign any data — including other keys. In the OpenPGP keysystem, signing a key signifies that we have validated that it belongs to the person whose name is on it. This creates a kind of graph over all of the keys, linking them together in what's called a "web of trust." This is similar to the world wide web in that we can use these links to find paths between nodes that aren't directly connected to each other.
This diagram shows how the web of trust can be used to figure out the validity of an unknown key. If I trust Eva and Eva trusts Manuel, then I can also trust Manuel since there's a path between my key and Manuel's key. This kind of link is not quite as strong as if we personally verified a key so we distinguish between direct links, where we have personally checked that a key belongs to a particular person, and indirect links, where our trust comes from the links between keys.
What's great about this is that it allows us to have some degree of certainty that an unknown key belongs to who it says it belongs to. If I end up with two keys for the same identity and one has been signed by a bunch of people I trust and the other has no signatures then it's easy for me to tell which one I should use. This only works, however, if I have some trusted keys in my keyring. Let's talk about how to get those.
Finding Public Keys
GPG keys can be distributed in any way you want - for example, I have mine listed on my website, on keybase, and uploaded to a bunch of keyservers. The simplest way is to import a key from a file or ASCII-armored string like this:
$ gpg --import ./my_key.pub.asc
That's it. Importing keys from files is super easy and if you see a key posted online somewhere that's probably how you'll do it. If you just know a person's email address however then you'll need to look up their key on a keyserver. Other people will want to be able to look up your keys this way too so you'll want to upload them to a keyserver too. The way to do this with GPG is
$ gpg --keyserver <key server> --send-key <key id>
There are lots of keyservers out there but most of them are federated so that keys uploaded to one of them will eventually end up duplicated on the others. SKS is a popular keyserver network so let's say we want to send the key we generated last time there:
$ gpg --keyserver hkp://pool.sks-keyservers.net --send-key 13D0B439 gpg: sending key 5DF274C713D0B439 to hkp://pool.sks-keyservers.net
Now if we want to get somebody's key, we just ask the keyserver for it using their email address. For example, to get my public key, you could do this:
$ gpg --keyserver hkp://pool.sks-keyservers.net --search-keys firstname.lastname@example.org  gpg: data source: http://188.8.131.52:11371 (1) Peter Beard
3072 bit RSA key 7BE960323A4FF3E2, created: 2018-04-07 (revoked) (2) Peter Beard Peter Beard 4096 bit RSA key B4A371011B4ED7ED, created: 2016-11-12, expires: 2021-11-11 Keys 1-2 of 2 for "email@example.com". Enter number(s), N)ext, or Q)uit > 2 gpg: key B4A371011B4ED7ED: "Peter Beard " not changed gpg: Total number processed: 1 gpg: unchanged: 1
You can see that there are multiple keys matching my email address but only one of them is active so that's the one we download. Now you can encrypt things you want to send to me and you can verify anything that I've signed with that key, right? Well, almost.
Before we start using a key we should take a look at the signatures it has. Let's say we're Ingo and we're trying to set up the web from that Wikipedia example - what might that look like?. Well assuming we've already generated our own keypair we'll need to get the keys for our friends Eva and Axel - let's say they've kindly provided us with files containing these keys:
$ gpg --import ./eva.pub.asc gpg: key EC180DF84D7A82F0: public key "Eva Friend
" imported gpg: Total number processed: 1 gpg: imported: 1 gpg: marginals needed: 3 completes needed: 1 trust model: pgp gpg: depth: 0 valid: 10 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 10u gpg: next trustdb check due at 2021-06-13 $ gpg --import ./axel.pub.asc gpg: key 1DE9888E13316A02: public key "Axel Friend " imported gpg: Total number processed: 1 gpg: imported: 1 gpg: marginals needed: 3 completes needed: 1 trust model: pgp gpg: depth: 0 valid: 9 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 9u gpg: next trustdb check due at 2020-12-26 $ gpg --list-keys ./ingo ------ pub rsa4096 2020-06-13 [SC] [expires: 2021-06-13] 96DBE852024841C3D7F5076F41CEAC45B766EE00 uid [ultimate] Ingo Myself sub rsa4096 2020-06-13 [E] [expires: 2021-06-13] pub rsa4096 2020-06-13 [SC] [expires: 2021-10-23] 2458335DB495B689DA1832D8EC180DF84D7A82F0 uid [ unknown] Eva Friend sub rsa4096 2020-06-13 [E] [expires: 2021-10-23] pub rsa2048 2020-06-13 [SC] [expires: 2020-12-26] 1F02C831CABDAE9A38FA1E7E1DE9888E13316A02 uid [ unknown] Axel Friend sub rsa2048 2020-06-13 [E] [expires: 2020-12-26]
Before each person's name you can see the current trust level - there are five levels of trust that can be applied to a key:
- Unknown - you don't know whether or not you trust this person
- None - this person's signatures can't be trusted
- Marginal - this person is pretty careful about validating keys before signing them
- Full - you trust this person as much as yourself to validate keys properly
- Ultimate - even if this key isn't valid you trust its owner's signatures as much as your own (rarely used except for your own keys)
There are no fixed rules as to what the different levels mean, just guidelines. In this case, we have a level 3 signature since we generated the key ourselves. If you have a friend who you know properly validates keys before signing them then you might also trust them at a 3. Most people in your web of trust will probably be level 2.
To see how the web of trust works, let's import a few more keys that have been signed by our friends:
Let's say we know Axel and Eva very well and completely trust them to validate other people's keys - we'll set their trust levels to
full and see how that changes things.
$ gpg --edit-key eva gpg (GnuPG) 2.2.20; Copyright (C) 2020 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. pub rsa4096/EC180DF84D7A82F0 created: 2020-06-13 expires: 2021-10-23 usage: SC trust: unknown validity: unknown sub rsa4096/3A255E76281F37CF created: 2020-06-13 expires: 2021-10-23 usage: E [ unknown] (1). Eva Friend
gpg> trust pub rsa4096/EC180DF84D7A82F0 created: 2020-06-13 expires: 2021-10-23 usage: SC trust: unknown validity: unknown sub rsa4096/3A255E76281F37CF created: 2020-06-13 expires: 2021-10-23 usage: E [ unknown] (1). Eva Friend Please decide how far you trust this user to correctly verify other users' keys (by looking at passports, checking fingerprints from different sources, etc.) 1 = I don't know or won't say 2 = I do NOT trust 3 = I trust marginally 4 = I trust fully 5 = I trust ultimately m = back to the main menu Your decision? 4 pub rsa4096/EC180DF84D7A82F0 created: 2020-06-13 expires: 2021-10-23 usage: SC trust: full validity: unknown sub rsa4096/3A255E76281F37CF created: 2020-06-13 expires: 2021-10-23 usage: E [ unknown] (1). Eva Friend Please note that the shown key validity is not necessarily correct unless you restart the program.
We then do the same for Axel's key and see how that changes the output of