mirror of
https://codeberg.org/openpgp/notes.git
synced 2024-11-30 03:22:06 +01:00
Merge branch 'draft' into tammi-ch6
This commit is contained in:
commit
5259fb0606
4 changed files with 307 additions and 159 deletions
|
@ -135,6 +135,11 @@ Instead, key flags, along with other metadata about that component key, such as
|
||||||
- For the primary key, its key flags and other metadata can be defined in two ways: they can be linked with the [Primary User ID](primary_user_id) or through a [direct key signature](direct_key_signature).
|
- For the primary key, its key flags and other metadata can be defined in two ways: they can be linked with the [Primary User ID](primary_user_id) or through a [direct key signature](direct_key_signature).
|
||||||
- For subkeys, the key flags and other metadata are set using the mechanism that binds the subkey to the certificate, specifically through the primary key. Further details on [binding subkeys](binding_subkeys) are below.
|
- For subkeys, the key flags and other metadata are set using the mechanism that binds the subkey to the certificate, specifically through the primary key. Further details on [binding subkeys](binding_subkeys) are below.
|
||||||
|
|
||||||
|
```{admonition} TODO
|
||||||
|
:class: warning
|
||||||
|
|
||||||
|
Write a section about algorithm preference/feature signaling
|
||||||
|
```
|
||||||
|
|
||||||
(identity_components)=
|
(identity_components)=
|
||||||
## Identity components
|
## Identity components
|
||||||
|
@ -165,9 +170,9 @@ Heiko, please clarify what the value is of this proposal or remove it.
|
||||||
```
|
```
|
||||||
|
|
||||||
(primary_user_id)=
|
(primary_user_id)=
|
||||||
### Implimations of the Primary User ID
|
### Implications of the Primary User ID
|
||||||
|
|
||||||
Within a certificate, a specific User ID is desginated as the [Primary User ID](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-primary-user-id).
|
Within a certificate, a specific User ID is designated as the [Primary User ID](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-primary-user-id).
|
||||||
|
|
||||||
Each User ID carries associated preference settings, such as preferred encryption algorithms, which is detailed in {numref}`zooming_in_user_id`). The preferences associated with the Primary User ID take precedence by default.
|
Each User ID carries associated preference settings, such as preferred encryption algorithms, which is detailed in {numref}`zooming_in_user_id`). The preferences associated with the Primary User ID take precedence by default.
|
||||||
|
|
||||||
|
|
|
@ -6,75 +6,97 @@ SPDX-License-Identifier: CC-BY-SA-4.0
|
||||||
(signing_data)=
|
(signing_data)=
|
||||||
# Signatures over data
|
# Signatures over data
|
||||||
|
|
||||||
A data signature guarantees the authenticity (and implicitly also the integrity) of a message, e.g., an email or a file.
|
In OpenPGP, a *data signature* guarantees the authenticity and, implicitly, the integrity of certain data. Typical use cases of data signatures include the authentication of software packages and emails.
|
||||||
|
|
||||||
More specifically, when we say "authenticity", we mean that the signature guarantees that whoever controls the signing key material has issued that signature. The question of who controls that key material is a separate concern. We might independently want to verify that our intended communication partner uses the cryptographic identity in question.
|
"Authenticity" in this context means that the data signature was issued by the entity controlling the signing key material. However,
|
||||||
|
it does not automatically signal if the expected party indeed controls the signer certificate. OpenPGP does offer mechanisms for *strong authentication*, connecting certificates to specific identities. This verifies that the intended communication partner is indeed associated with the cryptographic identity behind the signature[^sign-auth].
|
||||||
|
|
||||||
Note that signatures over data are different from {ref}`component_signatures_chapter`, which are used to attach metadata or subkeys to a certificate.
|
[^sign-auth]: Other signing solutions, like [signify](https://flak.tedunangst.com/post/signify), focus on pure signing without strong authentication of the signer's identity.
|
||||||
|
|
||||||
Typical use cases for signatures over data in OpenPGP are signatures for software packages or emails.
|
Data signatures can only be issued by component keys with the *signing* [key flag](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-key-flags).
|
||||||
|
|
||||||
When signing data, OpenPGP offers mechanisms for strong authentication, based on bindings between certificates and identities, and the option to verify those bindings.
|
Note that data signatures are distinct from {ref}`component_signatures_chapter`, which are used to form and maintain certificates, as well as to certify identities on certificates.
|
||||||
|
|
||||||
Other signing solutions, such as [signify](https://flak.tedunangst.com/post/signify), typically only offer a solution for pure signing, without offering
|
|
||||||
a mechanism for authentication.
|
|
||||||
|
|
||||||
|
(data_signature_types)=
|
||||||
## Signature types
|
## Signature types
|
||||||
|
|
||||||
Two OpenPGP [signature types](signature_types) apply to data signatures:
|
OpenPGP data signatures use one of two [signature types](signature_types):
|
||||||
|
|
||||||
- Signature of a binary document (*Binary Signature*, type ID `0x00`): a universal signature type for binary data. This signature type is typically used for files or data streams.
|
- [**Binary signature**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#sigtype-binary) (type ID `0x00`): This is the standard signature type for binary data and is typically used for files or data streams. Binary signatures are calculated over the data without any modifications or transformations.
|
||||||
Binary signatures are calculated over the data "as is", without performing any transformations.
|
- [**Text signature**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-signature-of-a-canonical-te) (type ID `0x01`): Used for textual data, such as email bodies. When calculating a text signature, the data is first normalized by converting line endings into a canonical form (`<CR><LF>`). This approach mitigates issues caused by platform-specific text encodings. This is especially important for detached and cleartext signatures, where the message file might undergo re-encoding between the creation and verification of the signature.
|
||||||
- Signature of a canonical text document (*Text Signature*, type ID `0x01`): used for textual data, such as email bodies. When calculating a text signature, the data is first normalized by converting line endings into a canonical form (`<CR><LF>`). This normalization mitigates issues caused by platform-specific default text encodings.
|
|
||||||
(This can be useful for detached signatures, when the message file may get re-encoded between signature generation and validation)
|
|
||||||
|
|
||||||
Data signatures are always calculated by a component key that carries the *signing* key flag.
|
Data signatures are generated by hashing the message content along with the metadata in the OpenPGP signature packet, and calculating a cryptographic signature over that hash. The resulting cryptographic signature is stored in the signature packet.
|
||||||
|
|
||||||
Data signatures are created by hashing the message content and calculating a cryptographic signature over the hash.
|
Data signature packets manifest in three distinct forms, which will be detailed in the subsequent section.
|
||||||
The resulting cryptographic signature is stored in an OpenPGP signature packet, which can be used in different ways. We'll discuss these in the following sections.
|
|
||||||
|
|
||||||
## Forms of OpenPGP data signatures
|
## Forms of OpenPGP data signatures
|
||||||
|
|
||||||
OpenPGP signatures over data can be generated and distributed in three forms[^sign-modes-gpg]:
|
OpenPGP data signatures can be applied in three distinct forms[^sign-modes-gpg]:
|
||||||
|
|
||||||
- *Detached*: The signature is a standalone artifact, separate from the signed data.
|
- **Detached**: The OpenPGP signature exists as a separate entity, independent of the signed data.
|
||||||
- *Inline*: The original data and the signature over the data are stored in an OpenPGP container.
|
- **Inline**: Both the original data and its corresponding OpenPGP signature are encapsulated within an OpenPGP container.
|
||||||
- *Cleartext signature*: A method to sign text while leaving the original message in a human-readable format.
|
- **Cleartext signature**: A plaintext message and its OpenPGP signature coexist in a combined text format, preserving the readability of the original message.
|
||||||
|
|
||||||
[^sign-modes-gpg]: These signature forms correspond with GnuPG's `--detach-sign`, `--sign` and `--clear-sign` modes.
|
[^sign-modes-gpg]: These three forms of signature application align with GnuPG's `--detach-sign`, `--sign`, and `--clearsign` command options.
|
||||||
|
|
||||||
### Detached signatures
|
### Detached signatures
|
||||||
|
|
||||||
This method is especially useful for signing software releases and other files that must not be modified by the signing process.
|
A detached signature is produced by calculating an OpenPGP signature over the data intended for signing. The original data remains unchanged, and the OpenPGP signature is stored as a standalone file. A detached signature file can be distributed alongside or independent of the original data. The authenticity and integrity of the original data file can be verified by using the detached signature file.
|
||||||
|
|
||||||
A detached signature is produced by calculating an OpenPGP signature over a piece of data.
|
This signature format is especially useful for signing software releases and other files where it is imperative that the content remains unaltered during the signing process.
|
||||||
The resulting OpenPGP signature packet can then be distributed alongside or independent of the original data.
|
|
||||||
|
|
||||||
### Inline signatures
|
### Inline signatures
|
||||||
|
|
||||||
This method is usually used with signed and/or encrypted emails.
|
An inline signature joins the signed data and its corresponding data signature into a single OpenPGP message.
|
||||||
|
|
||||||
Most clients that support OpenPGP for encrypted and/or signed messages make use of inline-signatures.
|
This method is commonly used for signing or encrypting emails. Most email software capable of handling OpenPGP communications typically uses inline signatures.
|
||||||
To produce a signature, the entirety of the data needs to be processed by the producer. This has the consequence that an application that efficiently emits signed data can only append the signature at the end of the data stream.
|
|
||||||
On the other hand, an application that needs to efficiently verify signed data needs to know the signer's public key and used hash algorithm before processing the data.
|
|
||||||
To solve this issue, so-called One-Pass Signature packets are prefixed to the signed data. Those are small packets containing the fingerprint of the signing key, as well as the used hash algorithm. This is all the information a receiving application needs to know to initiate the verification process.
|
|
||||||
|
|
||||||
To produce an inline-signed message, the original data is first wrapped in a [Literal Data packet](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit), which is prefixed with one or more [One-Pass Signature packets](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#one-pass-sig), and affixed with the corresponding signature packets.
|
#### Structure
|
||||||
The verifying application can read the One-Pass Signature packets and initiate the verification process.
|
|
||||||
The literal data can then be processed, such that the signatures at the end of the message can be verified in *one pass*.
|
|
||||||
|
|
||||||
TODO: explain nesting of OPSs.
|
An inline-signed OpenPGP message consists of three segments:
|
||||||
|
|
||||||
|
1. [**One-pass signature packets**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#one-pass-sig): These one or more packets precede the signed data and enable signature computation in one pass.
|
||||||
|
|
||||||
|
2. [**Literal data packet**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#lit): This contains the original data (e.g., the body of a message), without additional interpretation or conversion.
|
||||||
|
|
||||||
|
3. **Data signature packets**: These contain the cryptographic signature corresponding to the original data.
|
||||||
|
|
||||||
|
#### Creation
|
||||||
|
|
||||||
|
To produce an inline signature, the signer processes the entirety of the data by reading from an input file and writing into an output OpenPGP message file. As the data is processed, the signer simultaneously calculates a cryptographic signature. This procedure results in the appending of a data signature packet to the output OpenPGP message file, where it can be efficiently stored.
|
||||||
|
|
||||||
|
For efficient verification, an application must understand how to handle the literal data prior to its reading. This requirement is addressed by the one-pass signature packets located at the beginning of inline-signed messages. These packets include essential information such as the fingerprint of the signing key and the hash algorithm used for computing the signature's hash digest. This setup enables the verifier to process the data correctly and efficiently.
|
||||||
|
|
||||||
|
```{admonition} TODO
|
||||||
|
:class: warning
|
||||||
|
|
||||||
|
Is the signer keyid/fingerprint in the OPS important for the verifier to be able to verify the signature efficiently? Or is it (only?) there to be hashed and signed, along with the literal data?
|
||||||
|
|
||||||
|
Realization: It's probably useful to know the fingerprints right away, to first go find the public key material, before calculating the hash of a huge file.
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Verification
|
||||||
|
|
||||||
|
Inline-signed messages enable efficient verification in *one pass*, structured as follows:
|
||||||
|
|
||||||
|
1. **Initiation with one-pass signature packets**: These packets begin the verification process. They include the signer's key ID/fingerprint, essential for identifying the appropriate public key for signature validation.
|
||||||
|
|
||||||
|
2. **Processing the literal data packet**: This step involves hashing the literal data, preparing it for signature verification.
|
||||||
|
|
||||||
|
3. **Verifying signature packets**: Located at the end of the message, these packets are checked against the previously calculated hash digest.
|
||||||
|
|
||||||
|
Important to note, the signer's public key, critical for the final verification step, is not embedded in the message. Verifiers must acquire this key externally (e.g., from a key server) to authenticate the signature successfully.
|
||||||
|
|
||||||
### Cleartext signatures
|
### Cleartext signatures
|
||||||
|
|
||||||
The *Cleartext Signature Framework* (CSF) is a mechanism that combines two goals:
|
The *Cleartext Signature Framework* (CSF) in OpenPGP accomplishes two primary objectives:
|
||||||
|
|
||||||
- It leaves the message in clear text format, so that it can be viewed directly by a human in a program that knows nothing about OpenPGP.
|
- maintaining the message in a human-readable cleartext format, accessible without OpenPGP-specific software
|
||||||
- At the same time it adds an OpenPGP signature that allows verification of that message by users whose software supports OpenPGP.
|
- incorporating an OpenPGP signature for authentication by users with OpenPGP-compatible software
|
||||||
|
|
||||||
#### Example
|
#### Example
|
||||||
|
|
||||||
In {numref}`cleartext` we inspect an example of a cleartext signature in detail. Let's have a brief look at this example, here, to get a sense of what a cleartext signature looks like:
|
The following is a detailed example of a {numref}`cleartext` signature:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
-----BEGIN PGP SIGNED MESSAGE-----
|
-----BEGIN PGP SIGNED MESSAGE-----
|
||||||
|
@ -91,28 +113,40 @@ r13/eqMN8kfCDw==
|
||||||
-----END PGP SIGNATURE-----
|
-----END PGP SIGNATURE-----
|
||||||
```
|
```
|
||||||
|
|
||||||
The cleartext signature consists of two blocks, which contain the message and a signature, respectively. In this case the message consists of the text "hello world".
|
This signature consists of two parts: a message ("hello world") and an ASCII-armored OpenPGP signature. The message is immediately comprehensible to a human reader, while the signature block allows for the message's authenticity verification via OpenPGP software.
|
||||||
|
|
||||||
Notice that this message is readable by a human reader, without requiring additional software tools, as long as the reader understands which elements to ignore.
|
#### Use case
|
||||||
|
|
||||||
The message is followed by a block that contains an OpenPGP signature for the message, in ASCII armored form. Using OpenPGP software, this signature can be verified.
|
Clear text signatures combine the advantages of both detached and inline signatures:
|
||||||
|
|
||||||
#### Use-case
|
- **Self-contained format**: Cleartext signatures enable the message and its signature to be stored as a single file.
|
||||||
|
|
||||||
One use-case for cleartext signatures is: Asking someone to sign some piece of data. The person who is asked to sign the data can easily inspect it with simple commandline tools, such as `cat`, and verify that they agree with the data they are asked to sign.
|
- **Human readability**: The message within a cleartext signature remains accessible in a plain text format. This eliminates the need for specialized software to read the message content.
|
||||||
|
|
||||||
We use this for example to verify User ID and primary key of Arch Linux packagers before signing the User IDs on their keys with the main signing keys and to verify the data claims when introducing new packagers (i.e. already established packagers vouch for the data of a new packager).
|
These features are particularly beneficial in scenarios where signed messages are managed semi-manually and where existing system infrastructure offers limited or no native support for OpenPGP in the workflow[^arch-certifications].
|
||||||
|
|
||||||
|
[^arch-certifications]: An illustrative example is the workflow adopted by Arch Linux to certify User IDs of new packagers. This process relies on [cleartext signed statements from existing packagers](https://gitlab.archlinux.org/archlinux/archlinux-keyring/-/blob/master/.gitlab/issue_templates/New%20Packager%20Key.md?ref_type=heads&plain=1#L33-46). These signed statements are stored as attachments in an issue tracking system for later inspection. The advantage of this approach lies in the convenience of having the message and signature in a single file, which simplifies manual handling. Based on the vouches in these cleartext signed messages and an [email confirmation from the new packager](https://gitlab.archlinux.org/archlinux/archlinux-keyring/-/wikis/workflows/verify-a-packager-key), the main key operators can issue OpenPGP third-party certifications.
|
||||||
|
|
||||||
#### Text transformations for cleartext signatures
|
#### Text transformations for cleartext signatures
|
||||||
|
|
||||||
TODO: explain text transforms for cleartext signatures (LF->CRLF etc)
|
The cleartext signature framework includes specific text normalization procedures to ensure the integrity and clarity of the message:
|
||||||
|
|
||||||
|
_ **Escaping dashes**: The framework implements a method of [dash-escaped text](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-dash-escaped-text) within the message. Dash-escaping ensures that the parser correctly distinguishes between the armor headers, which are part of the signature's structure, and any lines in the message that happen to start with a dash.
|
||||||
|
|
||||||
|
- **Normalization of line endings**: Consistent with the approach for any other [text signature](data_signature_types), a cleartext signature is calculated on the text with normalized line endings (`<CR><LF>`). This ensures that the signature remains valid regardless of the text format of the receiving implementation.
|
||||||
|
|
||||||
#### Pitfalls
|
#### Pitfalls
|
||||||
|
|
||||||
Cleartext signatures are popular and have useful applications.
|
Despite their widespread adoption, cleartext signatures have their limitations and are sometimes viewed as a "legacy method"[^csf-gnupg]. The RFC details the [pitfalls of cleartext signatures](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-issues-with-the-cleartext-s), such as incompatibility with semantically meaningful whitespace, challenges with large messages, and security vulnerabilities related to misleading Hash header manipulations. Given these issues, safer alternatives like inline and detached signature forms are advised.
|
||||||
|
|
||||||
At the same time, they are considered a "legacy method"[^csf-gnupg] by some.
|
|
||||||
|
|
||||||
[^csf-gnupg]: https://lists.gnupg.org/pipermail/gnupg-devel/2023-November/035428.html
|
[^csf-gnupg]: https://lists.gnupg.org/pipermail/gnupg-devel/2023-November/035428.html
|
||||||
|
|
||||||
The RFC points out a number of [pitfalls of cleartext signatures](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-issues-with-the-cleartext-s), and advises that in many cases, the inline and detached signature forms are preferable.
|
## Advanced topics
|
||||||
|
|
||||||
|
### Nesting of one-pass signatures
|
||||||
|
|
||||||
|
```{admonition} TODO
|
||||||
|
:class: warning
|
||||||
|
|
||||||
|
Write
|
||||||
|
```
|
|
@ -6,90 +6,87 @@ SPDX-License-Identifier: CC-BY-SA-4.0
|
||||||
(component_signatures_chapter)=
|
(component_signatures_chapter)=
|
||||||
# Signatures on components
|
# Signatures on components
|
||||||
|
|
||||||
In this chapter, we'll consider OpenPGP signatures that apply to components. That is, signatures that apply to:
|
In this chapter, we'll look at OpenPGP signatures that apply to components of certificates. That is, signatures that apply to:
|
||||||
|
|
||||||
- Component keys (primary keys or subkeys), or
|
- Component keys (primary keys or subkeys) and
|
||||||
- Identity components (User IDs or User attributes).
|
- Identity components (User IDs or User attributes).
|
||||||
|
|
||||||
This chapter adds a lot of detail to the material we discussed in the {ref}`certificates_chapter` chapter. Signatures on components are a crucial mechanism for forming OpenPGP certificates (which combine component keys and identities, via signatures on those components).
|
Signatures on components are used to construct and maintain certificates, and to model the authentication of identities.
|
||||||
|
|
||||||
Additionally, signatures on components play a crucial role for authentication of identities. Mechanisms for decentralized authentication are one of OpenPGP's core strengths, we'll look into how they work.
|
This chapter expands on topics we introduced in the {ref}`certificates_chapter` chapter.
|
||||||
|
|
||||||
Finally, signatures on components are also a central mechanism for life-cycle management of OpenPGP certificates and their components. This includes defining or changing expiration dates, or issuing revocations, for certificates or their components.
|
## Self-signatures vs third-party signatures
|
||||||
|
|
||||||
## Self-signatures and third-party signatures
|
There are two fundamentally different flavors of signatures on components:
|
||||||
|
|
||||||
There are two important scenarios to distinguish:
|
- *Self-signatures*, which are issued by the certificate holder themselves using the primary key of the certificate, and
|
||||||
|
- *third-party signatures*, which are issued by a third party.
|
||||||
|
|
||||||
- *Self-signatures*: Issued by the certificate's owner, using the primary key of the same certificate.
|
### Self-signatures
|
||||||
- *Third-party signatures*: Issued by a key that is part of a different certificate.
|
|
||||||
|
|
||||||
### Meaning differs between self- and third-party signatures
|
*Self-signatures* on components are a crucial mechanism for forming OpenPGP certificates (by binding the certificate's components into one combined data structure), as well as for life-cycle management of certificates (that is: performing changes to the certificate, over time).
|
||||||
|
|
||||||
The meaning of a signature depends in part on who issued it. A self-signature often has a different meaning from a signature issued by a third party.
|
Life-cycle management operations on OpenPGP certificates and their components include:
|
||||||
|
|
||||||
|
- binding additional components to a certificate,
|
||||||
|
- changing the expiration date, or other metadata, of a component, and
|
||||||
|
- invalidating components or existing self-signatures using revocations.
|
||||||
|
|
||||||
|
Self-signatures are issued by the certificate's owner, using the primary key of the same certificate.
|
||||||
|
|
||||||
|
```{note}
|
||||||
|
No [key flag](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-key-flags) is required to issue self-signatures. An OpenPGP primary key can issue self-signatures by default.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Third-party signatures
|
||||||
|
|
||||||
|
Third-party signatures on components form the basis for OpenPGP's decentralized authentication functionality (also known as the *Web of Trust*). They encode authentication-related statements about certificates and their associated identities.
|
||||||
|
|
||||||
|
Third-party OpenPGP signatures can be used to make the following types of statements:
|
||||||
|
|
||||||
|
- Certification of identity claims,
|
||||||
|
- Delegation of authentication decisions,
|
||||||
|
- Invalidating previous third-party signature statements using revocations.
|
||||||
|
|
||||||
|
```{note}
|
||||||
|
The **certify others** [key flag](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-key-flags) (`0x01`) is required to issue third-party signatures. Only the primary key of a certificate may hold this key flag.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Self-signatures and third-party signatures convey different meanings
|
||||||
|
|
||||||
|
The meaning of a signature depends in part on who issued it. A self-signature performs a different function than the same type of signature issued by a third party.
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
- A [direct key signature](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-direct-key-signature-type-i) issued as a self-signature can be used to set preferences and advertise features that apply to the whole certificate, while
|
- Certifying self-signatures (type IDs `0x10` - `0x13`) are used to bind a User ID to a certificate, while
|
||||||
- A similar [direct key signature](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-direct-key-signature-type-i) issued by a third party, which carries a [trust signature](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-trust-signature) subpacket, acts as a statement by the issuer that they delegate trust to the signed certificate (the issuer thereby uses the remote certificate as a trust root in the *Web of Trust*).
|
- third-party signatures of the same type IDs indicate that the signer endorses the authenticity of a User ID.
|
||||||
|
|
||||||
Or:
|
Or:
|
||||||
|
|
||||||
- Certifying self-signatures (type IDs `0x10` - `0x13`) are used to bind a User ID to a certificate, while
|
- A [direct key signature](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-direct-key-signature-type-i) issued as a self-signature can be used to set preferences and advertise features that apply to the whole certificate, while
|
||||||
- the same signature type IDs issued by a third party are statements by the signer that they endorse the authenticity of the signed User ID to some degree.
|
- a similar [direct key signature](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-direct-key-signature-type-i) issued by a third party delegates trust to the signed certificate, when it carries a [trust signature](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-trust-signature) subpacket. The issuer thereby configures the signed certificate as a trust root in the *Web of Trust*, for themselves.
|
||||||
|
|
||||||
There are further signature types for signatures on data, as well as designated types to bind and revoke subkeys.
|
## Self-signatures: Forming certificates and life-cycle management
|
||||||
|
|
||||||
## Signatures on components
|
The components in an OpenPGP certificate are bound together using signatures. These *binding signatures* join the components together, while also adding metadata to them.
|
||||||
|
|
||||||
A typical use-case for a self-signature is to attach a User ID, such as a name and email address to a certificate.
|
Internally, an OpenPGP certificate consists of a sequence of OpenPGP packets. These packets are just strung together, one after the other. When a certificate is stored in a file[^tpk], it's easy to remove some of these packets, or add new ones.
|
||||||
This is done by calculating the signature over the User ID and the public primary key.
|
|
||||||
The resulting User ID certification (typically type 0x13, potentially type 0x10-0x12) can then be inserted into the certificate, right after the User ID packet.
|
|
||||||
|
|
||||||
Other examples for self-signatures are binding signatures for subkeys. To add an OpenPGP subkey to a certificate, a subkey binding signature is calculated over the public primary key, followed by the public subkey.
|
|
||||||
The resulting subkey binding signature (type 0x18) can then be inserted into the certificate right after the subkey.
|
|
||||||
If the subkey itself is intended to be used as a **S**igning key, an extra step is required.
|
|
||||||
To prevent an attacker from being able to "adopt" a victims signing subkey and then being able to claim to be the origin of signatures in fact made by victim, subkey binding signatures for signing subkeys need to include an embedded "back signature" (formally known as [primary key binding signature](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#sigtype-primary-binding)) made by the signing key itself.
|
|
||||||
|
|
||||||
Certifications over User IDs can also be used to certify certificates of third-parties.
|
|
||||||
If Alice is certain that `Bob Baker <bob@example.com>` controls the key `0xB0B`, she can create a User ID certification signature for that identity and send it to Bob.
|
|
||||||
Bob can then add this signature to his certificate.
|
|
||||||
TODO: More WoT.
|
|
||||||
|
|
||||||
```{note}
|
|
||||||
The **certify others** key flag is not required in order to issue certifying self-signatures.
|
|
||||||
This key flag is only necessary to issue valid third-party certifications.
|
|
||||||
```
|
|
||||||
|
|
||||||
### Revocations
|
|
||||||
|
|
||||||
One important class of self-signatures are revocations.
|
|
||||||
|
|
||||||
A revocation signature is used to retract the statement formed by a prior signature.
|
|
||||||
A subkey revocation signature revokes a prior subkey binding signature, while a certification revocation revokes a certification signature.
|
|
||||||
Typical use-cases for revocations are marking certificates or individual subkeys as unusable (for example, when the private key has been compromised or superseded), or marking User IDs as no longer used.
|
|
||||||
|
|
||||||
A revocation signature can either be hard or soft. A soft revocation of a certificate invalidates it from the revocation signature's creation time onwards. This means signatures issued before the revocation remain intact. A hard revocation, by contrast, invalidates the certificate retroactively, rendering all issued signatures invalid, regardless of creation time. Soft revocations are typically used whenever a key or User ID is retired or superseded gracefully, while hard revocations can, for example, signal compromise of secret key material.
|
|
||||||
|
|
||||||
## Self-signatures: Linking the components of a certificate
|
|
||||||
|
|
||||||
So far we've looked at the components in an OpenPGP certificate, but certificates actually contain another set of elements, which bind the components together, and add metadata to them.
|
|
||||||
|
|
||||||
Internally, an OpenPGP certificate consists of a sequence of OpenPGP packets. These packets are just stringed together, one after the other. When a certificate is stored in a file[^tpk], it's easy to remove some of these packets, or add new ones.
|
|
||||||
|
|
||||||
[^tpk]: When stored in a file, OpenPGP certificates are in a format called [transferable public key](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-transferable-public-keys).
|
[^tpk]: When stored in a file, OpenPGP certificates are in a format called [transferable public key](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-transferable-public-keys).
|
||||||
|
|
||||||
However, the owner of a certificate doesn't want a third party to add subkeys (or add [identity components](identity_components)) to their certificate, pretending that the certificate owner put those components there.
|
However, the owner of a certificate doesn't want a third party to add subkeys or [identity components](identity_components) to their certificate, pretending that the certificate owner put those components there.
|
||||||
|
|
||||||
To prevent malicious addition of components, OpenPGP uses cryptographic signatures. These signatures show that components have been added by the owner of the OpenPGP certificate (these linking signatures are issued by the primary key of the certificate).
|
To prevent malicious addition of components, OpenPGP uses cryptographic signatures. These signatures show that components have been added by the owner of the OpenPGP certificate. They are issued by the primary key of the certificate.
|
||||||
|
|
||||||
So while anyone can still unilaterally store unrelated subkeys and [identity components](identity_components) in an OpenPGP certificate dataset, OpenPGP implementations that read this certificate should discard components that don't have a valid cryptographic connection with the certificate.
|
So while anyone can still unilaterally store unrelated subkeys and [identity components](identity_components) in an OpenPGP certificate dataset, OpenPGP implementations that load a certificate can (and usually should) discard components that don't have a valid cryptographic connection with the certificate.
|
||||||
|
|
||||||
(Conversely, it's easy for a third party to leave out packets when passing on an OpenPGP certificate. An attacker can, for example, choose to omit revocation packets. The recipient of such a partial copy has no way to notice the omission, without access to a different source for the certificate that contains the revocation packet.)
|
```{note}
|
||||||
|
Conversely, it's easy for a third party to leave out packets, while handling an OpenPGP certificate dataset. An attacker can, for example, simply choose to omit revocation packets. The recipient of such a partial copy has no way to notice this omission, without access to a different source for the certificate that contains the revocation packet.
|
||||||
|
```
|
||||||
|
|
||||||
Note, though, that there are some cases where third parties legitimately add "unbound" packets to certificates (that is: packets that are not signed by the certificate's owner):
|
Note that there are some cases where third parties legitimately add "unbound" packets (that is: packets that are not signed by the certificate's owner) to a certificate:
|
||||||
|
|
||||||
- [Third-party certifications](third_party_cert) are traditionally added to the certificate that they make a statement about (this can cause problems in systems that unconditionally accept and include such certifications[^flooding]),
|
- [Third-party certifications](third_party_cert) are traditionally stored as part of the packet data of the certificate that they make a statement about (in systems that unconditionally accept and include such certifications, this can cause problems[^flooding]),
|
||||||
- OpenPGP software may add [unbound identity data](unbound_user_ids), locally.
|
- OpenPGP software may add [unbound identity data](unbound_user_ids), locally.
|
||||||
|
|
||||||
[^flooding]: Storing third-party identity certifications in the target OpenPGP certificate is convenient for consumers: it is easy to find all relevant certifications in one central location. However, when third parties can unilaterally add certifications, this opens an avenue for denial-of-service attacks by flooding. The SKS network of OpenPGP key servers [allowed and experienced this problem](https://dkg.fifthhorseman.net/blog/openpgp-certificate-flooding.html).
|
[^flooding]: Storing third-party identity certifications in the target OpenPGP certificate is convenient for consumers: it is easy to find all relevant certifications in one central location. However, when third parties can unilaterally add certifications, this opens an avenue for denial-of-service attacks by flooding. The SKS network of OpenPGP key servers [allowed and experienced this problem](https://dkg.fifthhorseman.net/blog/openpgp-certificate-flooding.html).
|
||||||
|
@ -97,97 +94,219 @@ Note, though, that there are some cases where third parties legitimately add "un
|
||||||
(bind_subkey)=
|
(bind_subkey)=
|
||||||
### Binding subkeys to a certificate
|
### Binding subkeys to a certificate
|
||||||
|
|
||||||
Linking a subkey to an OpenPGP certificate is done with a ["Subkey Binding Signature"](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#sigtype-subkey-binding). Such a signature signals that the "primary key wants to be associated with the subkey".
|
Subkeys is linked to an OpenPGP certificate using a [subkey binding signature](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#sigtype-subkey-binding) (type ID `0x18`). This signature type effectively signals that the "primary key wants to be associated with the subkey".
|
||||||
|
|
||||||
The subkey binding signature also adds metadata.
|
A subkey binding signature binds a subkey to a primary key, and adds metadata in the signature packet. Once generated, the subkey binding signature packet is stored in the certificate, directly following the subkey it binds.
|
||||||
|
|
||||||
|
(Note that subkeys that have the *signing* [key flag](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-key-flags) are a special case, and are handled slightly differently. See {numref}`bind_subkey_sign`.)
|
||||||
|
|
||||||
```{figure} diag/subkey_binding_signature.png
|
```{figure} diag/subkey_binding_signature.png
|
||||||
|
|
||||||
Linking an OpenPGP subkey to the primary key with a binding signature
|
Linking an OpenPGP subkey to the primary key with a binding signature
|
||||||
```
|
```
|
||||||
|
|
||||||
The [Signature packet](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-signature-packet-tag-2) that binds the subkey to the primary key has the signature type [SubkeyBinding](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-subkey-binding-signature-si).
|
To specify metadata for the subkey, such as the [*key expiration time*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#key-expiration-subpacket), or the capabilities that are set using [*key flags*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#key-flags), subpackets are included in the subkey binding signature packet.
|
||||||
|
|
||||||
|
```{note}
|
||||||
|
The validity of a subkey is bounded by that of the primary key, meaning that an expired primary key causes the subkey to be invalid, no matter the subkey expiration time.
|
||||||
|
|
||||||
In order to specify an expiration time for the subkey, a key expiration time subpacket can be included. Note, that the validity of the subkey is bounded by that of the primary key, meaning an expired primary key causes the subkey to be invalidated, no matter the subkey expiration time.
|
It's legal for a subkey to not have an explicit expiry time. In that case, its expiration date is implicitly the same as the expiration date of the primary key.
|
||||||
|
|
||||||
Note, that a subkey cannot be "older" than the primary key. The value of the subkeys creation date MUST be greater than that of the primary key.
|
A subkey cannot be "older" than the primary key. The value of the subkeys creation date MUST be greater than that of the primary key.
|
||||||
|
```
|
||||||
|
|
||||||
|
(bind_subkey_sign)=
|
||||||
### Special case: Binding signing subkeys to a certificate
|
### Special case: Binding signing subkeys to a certificate
|
||||||
|
|
||||||
Binding subkeys with the "signing" key flag is a special case. For the most part, it works the same as binding other types of subkeys, but there is an additional requirement:
|
To bind subkeys with the "signing" key flag to a certificate is a special case. For the most part, it works the same as binding other types of subkeys, but there is one additional requirement:
|
||||||
|
|
||||||
When binding a signing subkey to a primary key, it is not sufficient that the "primary key wants to be associated with the subkey." In addition, the subkey must signal that it "wants to be associated with that primary key."
|
To bind a signing-capable subkey to a primary key, it is not sufficient that the "primary key wants to be associated with the subkey." In addition, the subkey must signal that it "wants to be associated with that primary key."
|
||||||
|
|
||||||
Otherwise, Alice could "adopt" Bob's signing subkey and convincingly claim that she made signatures that were in fact issued by Bob.
|
Otherwise, Alice could "adopt" Bob's signing subkey and convincingly claim that she made signatures that were in fact issued by Bob.
|
||||||
This is to prevent an attack where the attacker "adopts" the victims signing subkey as their own in order to claim ownership over documents which were in fact signed by the victim.
|
This is to prevent an attack where the attacker "adopts" the victims signing subkey as their own in order to claim ownership over documents which were in fact signed by the victim.
|
||||||
Contrary to the `SubkeyBinding` signature, which is issued by the certificate's primary key, the `PrimaryKeyBinding` signature is instead created by the subkey.
|
In contrast to the [subkey binding signature](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#sigtype-subkey-binding) (type ID `0x18`), which is issued by the certificate's primary key, the [primary key binding signature](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#sigtype-primary-binding) (type ID `0x19`) is instead created by the subkey (informally also called an embedded "back signature").
|
||||||
|
|
||||||
```{figure} diag/subkey_binding_signatur_for_signing_sk.png
|
```{figure} diag/subkey_binding_signatur_for_signing_sk.png
|
||||||
|
|
||||||
Linking an OpenPGP signing subkey to the primary key with a binding signature, and an embedded primary key binding signature
|
Linking an OpenPGP signing subkey to the primary key with a binding signature, and an embedded primary key binding signature
|
||||||
```
|
```
|
||||||
|
|
||||||
This additional "Primary Key Binding" Signature is informally called a "back signature" (because the subkey uses the signature to point "back" to the primary key) is an embedded `PrimaryKeyBinding` "back signature" (type 0x19).
|
The additional [*primary key binding*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#sigtype-primary-binding) signature (type 0x19) is informally called a "back signature" (because the subkey uses the signature to point "back" to the primary key).
|
||||||
|
|
||||||
The *primary key binding signature* is "embedded" as subpacket data in the *subkey binding signature* that connects the signing subkey to the primary key.
|
The *primary key binding signature* is "embedded" as subpacket data in the *subkey binding signature* which connects the signing subkey to the primary key.
|
||||||
|
|
||||||
|
(bind_ident)=
|
||||||
### Binding identities to a certificate
|
### Binding identities to a certificate
|
||||||
|
|
||||||
"User ID" identity components are bound to an OpenPGP certificate by issuing a self-signature ("User Attributes" work analogously).
|
Another use-case for a self-signature is to link an identity component (such as a User ID that specifies a name and email address) to a certificate.
|
||||||
|
|
||||||
|
User ID components are bound to an OpenPGP certificate by issuing a certifying self-signature. "User Attributes" work analogously.
|
||||||
|
|
||||||
For example, the User ID `Alice Adams <alice@example.org>` may be associated with Alice's certificate `AAA1 8CBB 2546 85C5 8358 3205 63FD 37B6 7F33 00F9 FB0E C457 378C D29F 1026 98B3`.
|
For example, the User ID `Alice Adams <alice@example.org>` may be associated with Alice's certificate `AAA1 8CBB 2546 85C5 8358 3205 63FD 37B6 7F33 00F9 FB0E C457 378C D29F 1026 98B3`.
|
||||||
|
|
||||||
Alice can link a User ID to her OpenPGP certificate with a cryptographic signature. To link a User ID, a self-signature is created (usually with the signature type [PositiveCertification](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#sigtype-positive-cert)). This signature is issued by the primary key.
|
Alice can link a User ID to her OpenPGP certificate with a cryptographic signature. To link a User ID, a *certifying self-signature* is created. There are four variant certifying self-signature types. Usually the signature type [positive certification](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#sigtype-positive-cert) (type ID `0x13`) is used to bind User IDs to one's certificate (sometimes, type ID `0x10`, `0x11` or `0x12` may be used instead). This binding signature must be issued by the primary key.
|
||||||
|
|
||||||
|
The resulting certifying self-signature packet is stored as part of the certificate, directly following the User ID packet.
|
||||||
|
|
||||||
```{figure} diag/user_id_certification.png
|
```{figure} diag/user_id_certification.png
|
||||||
---
|
|
||||||
---
|
|
||||||
Linking a User ID to an OpenPGP certificate
|
Linking a User ID to an OpenPGP certificate
|
||||||
```
|
```
|
||||||
|
|
||||||
This signature is calculated over the primary key and User ID.
|
This signature is calculated over the primary key, User ID and the metadata of the signature packet.
|
||||||
|
|
||||||
|
|
||||||
|
### Adding metadata to the primary key
|
||||||
|
|
||||||
|
The signatures that bind subkeys and identity components to a certificate serve two different purposes: Linking components to the certificate and adding metadata to a component.
|
||||||
|
|
||||||
|
The primary key in a certificate doesn't need to be linked to the certificate. It acts as the anchor for linking, itself and thus doesn't require being linked. However, there is nevertheless a need to associate metadata with the primary key.
|
||||||
|
|
||||||
|
There are two mechanisms for adding metadata to the primary key:
|
||||||
|
|
||||||
|
- Via a direct key signature on the primary key, or
|
||||||
|
- via a "primary User ID" binding signature.
|
||||||
|
|
||||||
|
Relevant metadata for the primary key that is defined the above mechanisms includes:
|
||||||
|
|
||||||
|
- Key expiration,
|
||||||
|
- key flags,
|
||||||
|
- algorithm preference signaling.
|
||||||
|
|
||||||
(direct_key_signature)=
|
(direct_key_signature)=
|
||||||
### Direct key signature: Adding metadata to the primary key
|
#### Direct key signature
|
||||||
|
|
||||||
```{admonition} TODO
|
A [*direct key signature*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-direct-key-signature-type-i) is one mechanism to store information about the primary key, and about the entire certificate.
|
||||||
:class: warning
|
|
||||||
|
|
||||||
explain metadata associated with this signature, and that c-r prefers this over primary user id.
|
In OpenPGP v6, a direct key signature is the [preferred mechanism](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#section-5.2.3.10-9).
|
||||||
```
|
|
||||||
|
|
||||||
### Revocations: Invalidating components of a certificate
|
#### Primary User ID binding self-signature
|
||||||
|
|
||||||
```{admonition} TODO
|
In a certificate, one User ID serves as the [*primary* User ID](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-primary-user-id). The metadata in the binding self-signature on this User ID applies to the primary key of the certificate.
|
||||||
:class: warning
|
|
||||||
|
|
||||||
This section only contains notes and still needs to be written
|
### Revocation self-signatures: Invalidating components of a certificate
|
||||||
|
|
||||||
|
One important class of self-signatures are revocations.
|
||||||
|
|
||||||
|
A revocation signature is used to invalidate a component, or retract the statement formed by a prior signature.
|
||||||
|
|
||||||
|
- A [*key revocation signature*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-key-revocation-signature-ty) (type ID `0x20`) marks a primary key as revoked.
|
||||||
|
- a [*subkey revocation signature*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-subkey-revocation-signature) (type ID `0x28`) revokes a prior subkey binding signature, while
|
||||||
|
- a [*certification revocation*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-certification-revocation-si) (type ID `0x30`) revokes a certification signature.
|
||||||
|
|
||||||
|
Typical use-cases for revocations are marking certificates or individual subkeys as unusable (for example, when the private key has been compromised or superseded), or marking User IDs as no longer used.
|
||||||
|
|
||||||
|
```{note}
|
||||||
|
OpenPGP certificates act as append-only data structures, in practice. Elements of a certiciate can not be removed from the copies on key servers and the OpenPGP systems of third parties, once published. Implementations usually merge all available components and signatures.
|
||||||
|
|
||||||
|
Revocations are used as a mechanism to mark components or signatures as invalid.
|
||||||
```
|
```
|
||||||
|
|
||||||
Note: certification signatures [can be made irrevocable](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-revocable).
|
Note: certification signatures [can be made irrevocable](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-revocable).
|
||||||
|
|
||||||
#### Hard vs. soft revocations
|
#### Hard vs. soft revocations
|
||||||
|
|
||||||
A revocation signature may contain a subpacket indicating the reason for revocation. This subpacket contains a code which specifies why the revocation was issued. This code determines, whether the revocation is hard or soft.
|
A revocation signature can contain a subpacket indicating the [*reason for revocation*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-reason-for-revocation). The value of this subpacket contains a code that specifies why the revocation was issued. This code determines whether the revocation is considered a *soft revocation* or a *hard revocation*:
|
||||||
|
|
||||||
A soft revocation is typically used for graceful or planned revocations. A soft revocation can be reverted by re-validating the certificate, User ID or subkey with a fresh binding signature.
|
- A *soft revocation* is typically used for graceful or planned invalidation. Soft revocation of a component invalidates it from the revocation signature's creation time onwards. Uses of the component before the revocation time remain intact. Soft revocations can be reverted by re-validating the invalidated component with a new self-signature.
|
||||||
A soft revocation invalidates the target certificate beginning with the revocations creation time.
|
- A *hard revocation*, by contrast, invalidates the component retroactively, rendering all past and future uses invalid. Hard revocation of a component cannot be undone by re-validating the component.
|
||||||
|
|
||||||
Contrary, a hard revocation cannot be re-validated. Furthermore, a hard-revoked certificate is invalidated retroactively.
|
Soft revocations are typically used when a certificate, subkey or User ID is retired or superseded gracefully, while hard revocations are typically used to signal compromise of secret key material.
|
||||||
|
|
||||||
A missing revocation reason subpacket is equivalent with a hard revocation reason.
|
```{note}
|
||||||
|
A revocation signature that has no *reason for revocation* subpacket is interpreted as a hard revocation.
|
||||||
|
```
|
||||||
|
|
||||||
(third_party_cert)=
|
(third_party_cert)=
|
||||||
## Third-party certifications: Making statements about other people's certificates and identities
|
## Third-party signatures: Authentication statements
|
||||||
|
|
||||||
```{admonition} TODO
|
Signatures on components by third parties mainly encode authentication of identities and delegations of trust decisions.
|
||||||
|
|
||||||
|
Third party signatures can be inspected and reasoned about manually by humans. More powerfully, though, they can also be used as machine-readable artifacts, by OpenPGP software, which can reason about the authenticity of certificates on behalf of its users, based on trust roots that the user has specified.
|
||||||
|
|
||||||
|
### Certifying identity components
|
||||||
|
|
||||||
|
By issuing a certifying signature on an identity, the signer expresses that he has verified that the identity and the certificate are meaningfully linked. The signer vouches for the connection between the certificate and the identity.
|
||||||
|
|
||||||
|
If Alice is certain that the identity `Bob Baker <bob@example.com>` controls the certificate `0xB0B`, she can create a certification signature that binds Bob's User ID and Bob's certificate. Bob will usually distribute this certifying signature from Alice as part of his certificate.
|
||||||
|
|
||||||
|
Effectively, this is a way for Alice to broadcast the statement "I, Alice, have checked that `Bob Baker <bob@example.com>` controls the certificate `0xB0B`." Other users may or may not decide to rely on this statement by Alice.
|
||||||
|
|
||||||
|
### Delegating authentication: Trust signatures
|
||||||
|
|
||||||
|
The OpenPGP standard specifies primitives to delegate authentication decisions to certificates. The standard uses the (somewhat confusing) term "trust" for this mechanism. Delegating authentication decisions to a certificate, using a [*trust signature*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#trust-signature-subpacket) subpacket, makes the target certificate a "trusted introducer."
|
||||||
|
|
||||||
|
A "trusted introducer" acts as a trust root for the user.
|
||||||
|
|
||||||
|
[*Trust signature*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#trust-signature-subpacket) subpackets can be used in two types of signatures:
|
||||||
|
|
||||||
|
- On an identity certification signature (type ID `0x10` - `0x13`), or on a
|
||||||
|
- [*direct key signature*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-direct-key-signature-type-i) (type ID `0x1F`)
|
||||||
|
|
||||||
|
#### Trust depth (or "level")
|
||||||
|
|
||||||
|
OpenPGP's delegation mechanism allows specifying transitive delegation of trust: delegating authentication decisions across more than one hop. The standard refers to certificates as a "meta-introducer," when a "trust signature" subpacket defines it as a trusted introducer with a depth (or "level") of two or more.
|
||||||
|
|
||||||
|
A trust signature subpacket with means that the target certificate may delegate to a second, intermediate, introducer, which in turn has issued a certification signature for an identity.
|
||||||
|
|
||||||
|
**Examples**
|
||||||
|
|
||||||
|
When Alice delegates trust decisions to Trent, designating Trent as a trusted introducer with a *trust depth* of 1, then Alice's OpenPGP implementation will only accept direct certifications by Trent. For example, Trent may have certified that Bob's certificate with the fingerprint `0xB0B` is legitimately connected to Bob's User ID `Bob <bob@example.org>`. If Alice tries to communicate with Bob using his identity `Bob <bob@example.org>`, then Alice's OpenPGP software can automatically determine that the certificate `0xB0B` is appropriate to use.
|
||||||
|
|
||||||
|
However, Alice's OpenPGP software wouldn't accept a series of delegations from Trent via Tristan to a certification of Carol's identity (let's imagine that Trent has designated Tristan a trusted introducer). For Alice's OpenPGP software to accept such a path, she needs to designate Trent as a trusted introducer with the `level` set to 2 or more.
|
||||||
|
|
||||||
|
```{admonition} VISUAL
|
||||||
:class: warning
|
:class: warning
|
||||||
|
|
||||||
write
|
add diagrams?
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Trust amount
|
||||||
|
|
||||||
|
A trust signature can quantify the degree to which the issuer wants to rely on a delegation. This "trust amount" has a numerical value between 0 and 255.
|
||||||
|
|
||||||
|
A trust amount of 120 indicates "complete trust," which means that a certification by that trusted introducer is considered sufficient to consider authentications by that introducer as sufficient.
|
||||||
|
|
||||||
|
**Examples**
|
||||||
|
|
||||||
|
If Alice designates Trent as a trusted introducer at a trust amount of 120, then Alice's OpenPGP software will consider Bob's identity fully authenticated if Trent has certified it.
|
||||||
|
|
||||||
|
However, if Alice only assigns a trust amount of 60 (which indicates "partial trust") to Trent, then her software would not consider Bob's identity fully authenticated. Now let's imagine that Alice additionally assigns a trust amount of 60 to Tristan (a second, independent introducer), and Tristan also certified Bob's identity. In this case, Alice's OpenPGP software will consider Bob's identity fully authenticated, based on the combination of both delegations, and the certifications the two trusted introducers issued.
|
||||||
|
|
||||||
|
```{admonition} VISUAL
|
||||||
|
:class: warning
|
||||||
|
|
||||||
|
add diagrams?
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Limiting the scope of delegations with regular expressions
|
||||||
|
|
||||||
|
When using *trust signature* subpackets, a delegation can be limited to identities that match a [*regular expression*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#regex-subpacket), for example, to limit the email address in a User ID to a specific domain name.
|
||||||
|
|
||||||
|
With this mechanism, it is possible to delegate authentication decisions only for User IDs that match the email domain of an organization.
|
||||||
|
|
||||||
|
**Example**
|
||||||
|
|
||||||
|
For example, Alice could delegate trust decisions only for email addresses in the domain `bob.com` to Bob, if she considers Bob to be a reasonable source of identity certifications for that domain.
|
||||||
|
|
||||||
|
```{admonition} VISUAL
|
||||||
|
:class: warning
|
||||||
|
|
||||||
|
add diagrams?
|
||||||
|
```
|
||||||
|
|
||||||
|
### Decentralized automated trust decisions; or, the "Web of Trust"
|
||||||
|
|
||||||
|
The OpenPGP, the "Web of Trust" is a trust model that performs authentication decisions on a set of certifications and delegations.
|
||||||
|
|
||||||
|
The OpenPGP "Web of Trust" model assumes that every user makes their own choice about who they delegate authentication decisions to. Based on the available certificates and third-party signatures, the user's OpenPGP software uses the Web of Trust mechanism to determine which certificates are considered reliable for an identity.
|
||||||
|
|
||||||
|
The OpenPGP RFC doesn't specify how exactly Web of Trust calculations are performed. It only defines the data formats that these calculations can be performed on. See external resources in {numref}`wot-resources`.
|
||||||
|
|
||||||
|
### Revoking third-party signatures: Undoing previous statements
|
||||||
|
|
||||||
|
The issuer of a third-party signature can undo such a signature by issuing a [*certification revocation signature*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-certification-revocation-si) (type ID `0x30`).
|
||||||
|
|
||||||
## Advanced topics
|
## Advanced topics
|
||||||
|
|
||||||
### Certification Recipes
|
### Certification Recipes
|
||||||
|
@ -251,13 +370,12 @@ The structure of a certification revocation is as follows:
|
||||||
For User ID revocations, the value of the reason subpacket can either be `0` (no reason specified) or `32`, signaling that the User ID is no longer valid.
|
For User ID revocations, the value of the reason subpacket can either be `0` (no reason specified) or `32`, signaling that the User ID is no longer valid.
|
||||||
The latter would result in a soft revocation, while a reason code of `0` is considered a hard revocation.
|
The latter would result in a soft revocation, while a reason code of `0` is considered a hard revocation.
|
||||||
Omitting the reason packet altogether is also equivalent to a hard revocation.
|
Omitting the reason packet altogether is also equivalent to a hard revocation.
|
||||||
It is recommended to issue User ID certifications using a reason code `32` and to do certificate revocations using a direct-key signature.
|
It is recommended to issue User ID revocations using a reason code `32`.
|
||||||
|
|
||||||
(binding_subkeys)=
|
(binding_subkeys)=
|
||||||
#### Add a Subkey
|
#### Add a Subkey
|
||||||
|
|
||||||
For the purpose of key freshness, a user might want to add a new subkey to their certificate.
|
A user might want to add a new subkey to their certificate, for example to replace an old subkey with one that uses a newer cryptographic algorithm.
|
||||||
|
|
||||||
|
|
||||||
The structure is as follows:
|
The structure is as follows:
|
||||||
|
|
||||||
|
@ -287,12 +405,13 @@ The structure of such a signature is rather minimal:
|
||||||
| Issuer Fingerprint | Hashed | True or false | Strongly Recommended | The primary key is the issuer |
|
| Issuer Fingerprint | Hashed | True or false | Strongly Recommended | The primary key is the issuer |
|
||||||
| Reason for Revocation | Hashed | True | False | Decides over soft / hard revocation |
|
| Reason for Revocation | Hashed | True | False | Decides over soft / hard revocation |
|
||||||
|
|
||||||
In `SubkeyRevocation` signatures, the reason subpacket cannot have value `32`, but instead may be from the range of `0-3`.
|
In `SubkeyRevocation` signatures, the [reason subpacket](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-reason-for-revocation) cannot have value `32`, but instead may be from the range of `0-3`.
|
||||||
Values `1` (key superseded) and `3` (key retired and no longer used) are soft reasons, while `0` (no reason) and `2` (key compromised) are considered hard.
|
Values `1` (key superseded) and `3` (key retired and no longer used) are soft reasons, while `0` (no reason) and `2` (key compromised) are considered hard.
|
||||||
|
|
||||||
#### Revoke a Certificate
|
#### Revoke a Certificate
|
||||||
|
|
||||||
A user might want to revoke their whole certificate, rendering it unusable.
|
A user might want to revoke their entire certificate, rendering it unusable.
|
||||||
|
|
||||||
Depending on the circumstances, they might either want to revoke it softly, e.g. in case of migration to a new certificate, or they want to issue a hard revocation, e.g. in case of secret key material compromise. A soft-revoked certificate can be re-validated at a later point in time, by issuing a new certification, while a hard revocation is typically permanent.
|
Depending on the circumstances, they might either want to revoke it softly, e.g. in case of migration to a new certificate, or they want to issue a hard revocation, e.g. in case of secret key material compromise. A soft-revoked certificate can be re-validated at a later point in time, by issuing a new certification, while a hard revocation is typically permanent.
|
||||||
|
|
||||||
The recommended way to revoke a certificate is by issuing a `KeyRevocation` signature (type 0x20).
|
The recommended way to revoke a certificate is by issuing a `KeyRevocation` signature (type 0x20).
|
||||||
|
@ -304,11 +423,11 @@ The structure of a key revocation signature is similar to that of a `Certificati
|
||||||
| Issuer Fingerprint | Hashed | True or false | Strongly Recommended | The primary key is the issuer |
|
| Issuer Fingerprint | Hashed | True or false | Strongly Recommended | The primary key is the issuer |
|
||||||
| Reason for Revocation | Hashed | True | False | Decides over soft / hard revocation |
|
| Reason for Revocation | Hashed | True | False | Decides over soft / hard revocation |
|
||||||
|
|
||||||
For `KeyRevocation` signatures, the same constraints as for `SubkeyRevocation` signatures apply to the reason subpacket.
|
For `KeyRevocation` signatures, the same constraints as for `SubkeyRevocation` signatures apply to the [reason subpacket](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-reason-for-revocation).
|
||||||
|
|
||||||
#### Common Subpackets
|
#### Common Subpackets
|
||||||
|
|
||||||
There are some subpackets that are expected to be included in any type of signature.
|
There are some subpackets that are expected to be included in all types of signatures.
|
||||||
|
|
||||||
* **Signature Creation Time**: Every OpenPGP signature MUST contain a Signature Creation Time subpacket (2) containing the timestamp at which the signature was made. This packet MUST be present in the hashed area of the signature and SHOULD be marked as critical.
|
* **Signature Creation Time**: Every OpenPGP signature MUST contain a Signature Creation Time subpacket (2) containing the timestamp at which the signature was made. This packet MUST be present in the hashed area of the signature and SHOULD be marked as critical.
|
||||||
|
|
||||||
|
@ -325,18 +444,8 @@ Since the issuer fingerprint subpacket is self-authenticating, it can either be
|
||||||
Since the hashed and unhashed areas of a signature are just lists of subpackets, in principle they allow duplicates of the same subpacket, which might lead to conflicts.
|
Since the hashed and unhashed areas of a signature are just lists of subpackets, in principle they allow duplicates of the same subpacket, which might lead to conflicts.
|
||||||
Therefore, packets in the hashed area take precedence over the unhashed area.
|
Therefore, packets in the hashed area take precedence over the unhashed area.
|
||||||
However, there may still be conflicts between packets in the same area, e.g., two conflicting expiration dates, etc.
|
However, there may still be conflicts between packets in the same area, e.g., two conflicting expiration dates, etc.
|
||||||
The [specification recommends](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-notes-on-subpackets) that implementations favor the last occurrence of a conflicting packet in the hashed area.
|
The [specification recommends](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-notes-on-subpackets) that implementations favor the last occurrence of a conflicting packet in the hashed area (that is, the last entry for that subpacket type in the sequence of subpackets in the hashed area).
|
||||||
|
|
||||||
In some cases, duplicate packets with conflicting content even make sense, e.g., if a signature was made by a version 4 issuer key whose key material was migrated from an older OpenPGP version such as v3.
|
In some cases, duplicate packets with conflicting content even make sense, e.g., if a signature was made by a version 4 issuer key whose key material was migrated from an older OpenPGP version such as v3.
|
||||||
In this case, either the v3 or v4 key could be used to validate the v4 signature, but since the key ID calculation scheme was changed between v3 and v4, these identifiers would differ.
|
In this case, either the v3 or v4 key could be used to validate the v4 signature, but since the key ID calculation scheme was changed between v3 and v4, these identifiers would differ.
|
||||||
Therefore, the signature could contain two isuer key ID subpackets with conflicting, but correct values.
|
Therefore, the signature could contain two issuer key ID subpackets with conflicting, but correct values.
|
||||||
|
|
||||||
```{admonition} TODO
|
|
||||||
:class: warning
|
|
||||||
|
|
||||||
- Key Flags
|
|
||||||
- Preferences
|
|
||||||
- Embedded Signature (back sig)
|
|
||||||
- Trust Signatures (amount, depth)
|
|
||||||
- Direct key signatures
|
|
||||||
```
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ SPDX-License-Identifier: CC-BY-SA-4.0
|
||||||
|
|
||||||
[RFC4880](https://www.rfc-editor.org/rfc/rfc4880.html) OpenPGP Message Format [2007], specifies OpenPGP version 4
|
[RFC4880](https://www.rfc-editor.org/rfc/rfc4880.html) OpenPGP Message Format [2007], specifies OpenPGP version 4
|
||||||
|
|
||||||
|
(wot-resources)=
|
||||||
## Web of Trust
|
## Web of Trust
|
||||||
|
|
||||||
[PGP Web of Trust: Core Concepts Behind Trusted Communication](https://www.linux.com/training-tutorials/pgp-web-trust-core-concepts-behind-trusted-communication/),
|
[PGP Web of Trust: Core Concepts Behind Trusted Communication](https://www.linux.com/training-tutorials/pgp-web-trust-core-concepts-behind-trusted-communication/),
|
||||||
|
|
Loading…
Reference in a new issue