Pretty graphics for the Web of Trust

By David | March 29, 2023

I have recently added the ability to generate Graphviz DOT output to the Sequoia Web of Trust project. This new functionality has been released in version 0.7.0. With it, users can visually inspect an OpenPGP Web of Trust.

This can provide some fascinating insights into one’s own keyring, and the relationship between OpenPGP keys involved with software projects.

The sq-wot commandline tool can be used to inspect the relationship of one or more OpenPGP certificates in relation to a larger set of certificates. It can work on several certificates and/or keyring files.

By using one’s private key to sign the binding of a User ID (e.g. "Alice <alice@example.org>") and a certificate (e.g. "1234567890ABCDEF"), one asserts the authenticity of that binding between the User ID and the certificate (“I rely on the assertion that Alice <alice@example.org> is the owner of 1234567890ABCDEF). Bindings may be certified, but they can also be designated a Certificate Authority (CA).

These relationships between keys and User ID bindings is what is commonly referred to as a Web of Trust (WoT).

Many software projects sign their prebuilt software or source code. These signatures can be verified to establish the authenticity of the work. This can happen in the form of detached signatures for files or signatures on version control objects, such as signed git commits and tags and establishes a verifiable link between a certificate and a public artifact. To rely on the signatures, we need to also authenticate the certificates that made them. A WoT makes it easier to verify these certificates.

A notable similar application (and inspiration) to what is described in this article is wotmate which provides visual graphs for the Linux Kernel’s pgpkeys project.

Arch Linux’s Web of Trust

When looking at larger communities, such as Linux distributions, we can observe that some work with the concept of an OpenPGP Web of Trust.

Arch Linux for example employs a setup in which a set of main signing keys (each associated with one @master-key.archlinux.org User ID) signs the "@archlinux.org" User ID bindings of the various packager public keys of the distribution. This setup is handled in their archlinux-keyring project (which is the basis for a package of the same name).

Only with three or more such signatures does Arch Linux accept packages signed with that certificate. A system-wide GnuPG keyring (see pacman-key) used by the pacman package manager ensures that the WoT is honored on user systems when installing packages.

To figure out whether the author’s User ID ("David Runge <dvzrv@archlinux.org>") matches the three signature requirement, we can have a look at the keyring provided by the archlinux-keyring package. If you are not running Arch Linux (where the keyring is found in /usr/share/pacman/keyrings/archlinux.gpg), you can get the keyring as follows:

$ curl -L https://archlinux.org/packages/core/any/archlinux-keyring/download/ --output - |
  tar -O --zstd -xvf - usr/share/pacman/keyrings/archlinux.gpg > archlinux.pgp

Using sq-wot

Using our knowledge about which Fingerprints are considered those of the main signing keys (our trust roots), we can lookup the mail address associated with the User ID and specify that we want to aim for a trust amount of 360 (300%) 1:

$ sq-wot \
  --keyring archlinux.pgp \
  --trust-root "91FF E070 0E80 619C EB73  235C A88E 23E3 7751 4E00" \
  --trust-root "D8AF DDA0 7A5B 6EDF A7D8  CCDA D6D0 55F9 2784 3F1C" \
  --trust-root "2AC0 A42E FB0B 5CBC 7A04  02ED 4DC9 5B6D 7BE9 892E" \
  --trust-root "75BD 80E4 D834 509F 6E74  0257 B1B7 3B02 CC52 A02A" \
  --trust-root "69E6 471E 3AE0 6529 7529  832E 6BA0 F5A2 037F 4F41" \
  --trust-amount 360 \
  lookup \
  --email dvzrv@archlinux.org

[] 991F6E3F0765CF6295888586139B09DA5BF0D338 David Runge <dvzrv@archlinux.org>: doubly authenticated (300%)
  Path #1 of 3, trust amount 120:
    ◯ D8AFDDA07A5B6EDFA7D8CCDAD6D055F927843F1C ("Levente Polyak (Arch Linux Master Key) <anthraxx@master-key.archlinux.org>")
    │   certified the following binding on 2022-08-02
    └ 991F6E3F0765CF6295888586139B09DA5BF0D338 "David Runge <dvzrv@archlinux.org>"

  Path #2 of 3, trust amount 120:
    ◯ 91FFE0700E80619CEB73235CA88E23E377514E00 ("Florian Pritz (Arch Linux Master Key) <florian@master-key.archlinux.org>")
    │   certified the following binding on 2022-06-05
    └ 991F6E3F0765CF6295888586139B09DA5BF0D338 "David Runge <dvzrv@archlinux.org>"

  Path #3 of 3, trust amount 120:
    ◯ 75BD80E4D834509F6E740257B1B73B02CC52A02A ("Jonas Witschel (Arch Linux Master Key) <diabonas@master-key.archlinux.org>")
    │   certified the following binding on 2022-07-09
    └ 991F6E3F0765CF6295888586139B09DA5BF0D338 "David Runge <dvzrv@archlinux.org>"

[] C7E7849466FE2358343588377258734B41C31549 David Runge <dvzrv@archlinux.org>: doubly authenticated (300%)
  Path #1 of 3, trust amount 120:
    ◯ D8AFDDA07A5B6EDFA7D8CCDAD6D055F927843F1C ("Levente Polyak (Arch Linux Master Key) <anthraxx@master-key.archlinux.org>")
    │   certified the following binding on 2019-10-17
    └ C7E7849466FE2358343588377258734B41C31549 "David Runge <dvzrv@archlinux.org>"

  Path #2 of 3, trust amount 120:
    ◯ 91FFE0700E80619CEB73235CA88E23E377514E00 ("Florian Pritz (Arch Linux Master Key) <florian@master-key.archlinux.org>")
    │   certified the following binding on 2019-10-06
    └ C7E7849466FE2358343588377258734B41C31549 "David Runge <dvzrv@archlinux.org>"

  Path #3 of 3, trust amount 120:
    ◯ 2AC0A42EFB0B5CBC7A0402ED4DC95B6D7BE9892E ("David Runge (Arch Linux Master Key) <dvzrv@master-key.archlinux.org>")
    │   certified the following binding on 2021-06-05
    └ C7E7849466FE2358343588377258734B41C31549 "David Runge <dvzrv@archlinux.org>"

By default sq-wot uses human-readable output. Above we see that there are two packager keys associated with the same User ID (this is because one of them is currently being decommissioned) and that both are considered valid under the given constraint.

DOT Output Format

Using the newly added DOT output format (by specifying --format dot), we can make use of graphviz’s dot commandline tool to convert the resulting graph directly into a visual representation (such as a scalable vector graphics (SVG) file).

$ sq-wot \
  --format dot \
  --keyring archlinux.pgp \
  --trust-root "91FF E070 0E80 619C EB73  235C A88E 23E3 7751 4E00" \
  --trust-root "D8AF DDA0 7A5B 6EDF A7D8  CCDA D6D0 55F9 2784 3F1C" \
  --trust-root "2AC0 A42E FB0B 5CBC 7A04  02ED 4DC9 5B6D 7BE9 892E" \
  --trust-root "75BD 80E4 D834 509F 6E74  0257 B1B7 3B02 CC52 A02A" \
  --trust-root "69E6 471E 3AE0 6529 7529  832E 6BA0 F5A2 037F 4F41" \
  --trust-amount 360 \
  lookup \
  --email dvzrv@archlinux.org |
  dot -Tsvg -o output.svg

The DOT output format provides a legend, which explains the color code of the nodes in the graph: Trust roots are colored purple, intermediate introducers dark gray, authenticated targets green and unauthenticated targets red. The legend also shows information on targeted trust amount and other relevant options to the tooling.

When requesting a trust amount of 600 (500%) we can observe, that there is a difference between the two packager keys. Only one of them has five main signing key signatures and under the given constraint the other is not considered valid:

Gossip

To see which signatures of keys are generally available, without trusting any of them, we can use the --gossip option:

$ sq-wot \
  --format dot \
  --keyring archlinux.pgp \
  --gossip \
  lookup \
  --email dvzrv@archlinux.org |
  dot -Tsvg -o output.svg

Considering Time

Sometimes it is interesting to figure out whether a binding has been or will be considered authentic at a different point in time. For this purpose we can use the --time <ISO 8601 timestamp> option:

$ sq-wot \
  --format dot \
  --keyring archlinux.pgp \
  --gossip \
  --time 20200101 \
  lookup \
  --email dvzrv@archlinux.org |
  dot -Tsvg -o output.svg

Using Your Own Keyring

It is possible for sq-wot to use a local GnuPG keyring as well. The following is a possibly quite large and dense graph (depending on the amount of keys and signatures in your local keyring):

$ sq-wot \
  --format dot \
  --gpg \
  --gossip \
  list |
  dot -Tsvg -o output.svg

We hope that you will enjoy plotting graphs with sq-wot and that it will be helpful in making sense of whatever WoT you are working with!

Financial Support

Since the start of the project over five years ago, the p≡p foundation financially supports the people who work on Sequoia. In 2021, the NLnet foundation awarded us six grants as part of the NGI Assure program.

We are actively looking for additional financial support to diversify our funding.

You don’t need to directly use Sequoia to be positively impacted by it. We’re focused on creating tools for activists, lawyers, and journalists who can’t rely on centralized authentication solutions. So, consider donating. Of course, if your company is using Sequoia, consider sponsoring a developer (or two). Note: if you want to use Sequoia under a license other than the LGPLv2+, please contact the foundation.


  1. According to RFC 4880, a binding is fully authenticated if it has a trust amount of 120 (or greater), which sq-wot refers to as 100%. A binding that has been fully authenticated three times therefore has a trust amount of 360 (300%). ↩︎