Authenticating certificates
If you want to send someone an encrypted email, you will need public key material to do the encryption. Public key material is part of a certificate, and getting the right material is equivalent to getting the right certificate. Certificates also contain User IDs, claiming that the corresponding user published this certificate and that the public key material within is indeed the right one to use. This suggests that once you know the ID of a user (for instance, by their email address), identifying the right certificate should be easy.
User IDs, however, are arbitrary claims which need to be verified before it's advisable to rely on any public key material linked to them. This process of verification is called authentication. This process, however, is not well-defined. How much "evidence" do I need before I can trust the claimed binding between a User ID and the public key material?
If the intended receiver of my email has created and published a certificate, there is a "right" certificate. Certificates have unique, unambiguous identifiers called fingerprints. In contrast to User IDs, these are not claims but checksums over (some of) the content. Knowing the fingerprint allows identifying a certificate with near-absolute certainty.
This shifts the problem from identifying the right certificate to identifying the right fingerprint. Fortunately, fingerprints are much smaller – small enough to, for instance, print on a business card. The downside of fingerprints is that they are completely unintuitive sequences of characters with high entropy and no redundancy – they have no obvious correlation with a User ID.
Identifying a certificate—the waterproof way
Assuming that you are certain you have the right fingerprint—let's name it $FPR
—retrieving its corresponding certificate can be done with:
$ sq network search $FPR
If the fingerprint is found, this downloads the certificate from online sources and stores it in the local certificate store. You can read more about retrieving certificates.
The next step is to tell Sequoia PGP that the binding between a User ID and this certificate is valid. This might come as a surprise as we skip the manual comparison of fingerprints – let sq
do the job:
$ sq pki link add --cert $FPR --userid $USER_ID
Since sq network search $FPR
retrieved a certificate with that fingerprint, all that remains is to verify that this certificate contains the expected User ID. sq pki link add
does that and will return an error if that User ID is not present, or you made a typo in the fingerprint.
After this step, everything is set up to proceed with the encryption of the email.
By the way, you can get the fingerprint of your own key using:
$ sq key list $USER_ID
Identifying a certificate—softer approaches
The scenario in the preceding section is a bit idealistic—it assumes that:
- you are in possession of the right fingerprint
- the corresponding certificate has been published on a well-known server that is reachable on the internet
Real circumstances are often less optimal. But no matter how you obtained the fingerprint (or certificate), it happened in a context which can be taken into account and used as evidence.
If you received a fingerprint printed on a slip of paper handed over by the alleged creator of the corresponding key, this is strong evidence that you got the right fingerprint. The same could be said if you obtained the certificate itself on a USB stick.
Things become less reliable if the fingerprint reached you in an email, especially if that email was not signed. If that email came in response to a request ("Please send me your certificate ..."), it adds to its trustworthiness. If you know the sender personally, this might be another plus.
Some keyservers require an attestation. They send an email message to each User ID in a certificate which looks like an email address, containing a link. Clicking that link sends a specific request back to the server, which is taken as a confirmation of the email addresses authenticity, and hence the User ID, reasonably binding the User ID to the certificate. If you receive a certificate from such a server, you can take this into account.
Some websites publish corresponding fingerprints or even certificates alongside their contact email address. Assuming that only a limited number of people are able to modify the content of this website and all of them have honest intentions, this can also be taken as evidence of authenticity.
However, all the above examples (and there are many more) are circumstantial. They reflect social relationships, assumptions of integrity, diligence and probably more.
On top of this, not every email is sent in a life or death scenario; many of them are quite mundane, and it might even be acceptable to send them unencrypted.
All of this makes trade-offs a viable option. The amount of evidence one wants to see before relying on a certificate is likely to correlate with the importance or significance of the message that it authenticates. These trade-offs are probably the main way to handle "authentication" in practice.
Using the result
Once you are willing to rely on a certificate, you need to add a link in the PKI of Sequoia PGP. This enables Sequoia PGP to remember your decision and treat the certificate as authenticated from that moment onward.
Adding a link is done with:
$ sq pki link add --cert $FPR --userid $USER_ID
Instead of --userid
, --email
would work. If you specify --all
, all bindings in the designated certificate will be added.
This command does several things:
- It adds a signature to the certificate.
- This signature indicates that you consider the binding between the certificate and the User ID to be authentic.
- Future invocations of
sq
(or any other software using Sequoia PGP) will recognize this signature and its implied authenticity.
You can see the effect with:
$ sq pki link list --cert-email alice@example.com
- ┌ 60B00B3173854BA69689B19CCAC5C827BE11485F
└ "<alice@example.com>"
- is linked
- ┌ 60B00B3173854BA69689B19CCAC5C827BE11485F
└ "Alice"
- is linked
The key used to generate the signature is not an arbitrary key, but the trust root key located in the certificate store. For details see chapter Shadow CAs.
The above command will also add a trust-depth to the binding between certificate and User ID. Using sq pki link add
as above, the trust depth will be zero, which means that the authenticity implied by the signature does not "spread out"; it's limited to exactly this binding.
A trust depth of one means that not only the specific binding is considered authentic, but also all certifications made by this certificate.
Consider the following example:
There are 4 certificates (A, B, C, D), each with just one User ID, and these bindings:
- Alice's certificate
[ A, alice@example.com ]
- Bob's certificate
[ B, bob@example.com ]
- Carol's certificate
[ C, carol@example.com ]
- Dave's certificate
[ D, dave@example.com ]
Assuming that Alice is certain that Bob's certificate (especially the binding
[ B, bob@example.com ]
) is authentic, and Bob is equally certain about Carol's certificate, as is Carol of Dave's, each of them certifies the corresponding certificates:
- Alice's certificate
[ A, alice@example.com ]
- Bob's certificate
[ B, bob@example.com ](certified using A)
- Carol's certificate
[ C, carol@example.com ](certified using B)
- Dave's certificate
[ D, dave@example.com ](certified using C)
If Alice certifies Bob's certificate with a trust depth of zero, then—from Alice's perspective—Bob's certificate is authenticated. That's all.
If Alice uses a trust depth of one, then not only is Bob's certificate considered authentic, but Carol's is too, because Bob's certificate certifies Carol's. By assigning a trust depth of one, Alice marks Bob as a trust introducer, and his certifications are now considered as good as if Alice had done the certifications herself.
Carol has certified Dave's certificate. From Alice's perspective, however, Dave's certificate is not authenticated. A trust depth of one only effects the immediate certifications from Bob. To also include Dave's certificate, Alice has to assign Bob a trust depth of two, thus allowing Bob to also introduce trust introducers to Alice, in this case: Carol. Alice would then accept her certification of Dave's certificate.
To visualize the effect of trust depth from Alice's perspective:
trust-depth Trusted certificates 0 Bob 1 Bob, Carol 2 Bob, Carol, Dave Please note that Alice assigns the trust depth when certifying Bob's certificate. She doesn't have to touch Carol's certificate (or even Dave's) to achieve the effect. They don't have to be in Alice's local certificate store, and they don't even have to exist at the time of the certification. They do, however, have to be available locally when Alice calculates the authenticity of the certificates.
Trust depth is a counter which indicates how many hops in a certification chain will be covered by the initial assertion of authenticity. The maximum depth is 255.
The above sq pki link add
with a trust depth of 1 looks like (note the authorize
):
$ sq pki link authorize --depth 1 --cert $FPR --email bob@example.com
...
Certificates can have more than one User ID. Instead of treating each User ID separately—repeating sq pki link add
for each of them—you can pass --all
on the command line.
$ sq pki link add --cert $FPR --all
Links created by sq pki link add
will not expire, but this can be changed by using --expiration DATE
. DATE
can either be in ISO 8601 format (2025-12-31
) or a time interval string like 3y
(3 years).
$ sq pki link add --cert $FPR --all --expiration 3y
Links can be retracted at any point in time. Use
$ sq pki link retract --cert $FPR --email bob@example.com
to retract a specific certificate to User ID binding, or
$ sq pki link retract --cert $FPR --all
as a convenience to remove all links associated with the given certificate.
The existing links within the PKI can be listed with:
$ sq pki link list
- ┌ 042C3AA73E1566E90FDC31B05C1EA3A3B894010E
└ "Public Directories"
- is linked as a partially trusted CA
- trust amount: 40
- ┌ 4D735E0D7DDE1B338E05F2B80AF4CE6DF697FB28
└ "<alice@example.com>"
- is linked
- ┌ 4D735E0D7DDE1B338E05F2B80AF4CE6DF697FB28
└ "Alice"
- is linked
- ┌ D4A2E8E858B215BD4E0A775C2904DCFB85ED0E9B
└ "<bob@example.com>"
- is linked
- ┌ D4A2E8E858B215BD4E0A775C2904DCFB85ED0E9B
└ "Bob"
- is linked
This example shows a list with two certificates, each of them has two User IDs. Additionally, the shadow CA for "Public Directories" is displayed.