Merge branch 'draft' into tammi-ch8-heiko

# Conflicts:
#	book/source/08-signing_components.md
This commit is contained in:
Heiko Schaefer 2023-11-25 23:09:12 +01:00
commit 3a921f6528
No known key found for this signature in database
GPG key ID: DAE9A9050FCCF1EB
23 changed files with 552 additions and 174 deletions

View file

@ -10,3 +10,7 @@ License: CC-BY-SA-4.0
Files: book/source/mermaid/*.png Files: book/source/mermaid/*.png
Copyright: 2023 The "Notes on OpenPGP" project Copyright: 2023 The "Notes on OpenPGP" project
License: CC-BY-SA-4.0 License: CC-BY-SA-4.0
Files: book/patches/*.patch
Copyright: 2023 The "Notes on OpenPGP" project
License: CC0-1.0

24
.woodpecker/epub.yml Normal file
View file

@ -0,0 +1,24 @@
# SPDX-FileCopyrightText: 2023 The "Notes on OpenPGP" project
# SPDX-License-Identifier: CC0-1.0
clone:
git:
image: woodpeckerci/plugin-git
settings:
lfs: false
when:
branch: draft
event:
- push
- pull_request
steps:
epub-check:
image: archlinux:latest
commands:
- pacman -Sy --needed --noconfirm archlinux-keyring
- pacman -Syu --needed --noconfirm epubcheck make patch python-myst-parser python-sphinx
# fix sphinx: https://github.com/sphinx-doc/sphinx/issues/11598
- patch -Np1 -d /usr/lib/python3.11/site-packages/ -i "$(pwd)/book/patches/sphinx-11766.patch"
- make -C book epub-check

91
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,91 @@
<!--
SPDX-FileCopyrightText: 2023 The "Notes on OpenPGP" project
SPDX-License-Identifier: CC-BY-SA-4.0
-->
# Contributing
These are the contribution guidelines for "Notes on OpenPGP".
Development takes place at https://codeberg.org/openpgp/notes.
Discussion around this project takes place in [`#notes-on-openpgp:matrix.org`] on [Matrix].
## Providing changes
This project uses [sphinx] and [MyST-parser] to allow building various output formats, such as [HTML] and [EPUB], for the included book projects.
Contributors can provide changes by pull request towards the project.
### Building and testing
The included book projects can be built and tested using a `Makefile`.
The below examples show how to use it with a book named `book`.
To cleanly build the [HTML] output:
```shell
$ make -C book clean build
```
To cleanly build the [EPUB] output:
```shell
$ make -C book clean epub
```
To spell check all files using [codespell]:
```shell
$ make -C book codespell
```
To check the external links in all [HTML] files using [lychee]:
```shell
$ make -C book html-linkcheck
```
### Writing text
The syntax follows what is available in [MyST-parser].
---
**NOTE**: It is advisable to always relate to the [MyST-parser] documentation, as [MyST] itself offers more/ different features!
---
#### Cross-referencing
There are a few guidelines when it comes to cross-referencing, which work around oddities with [sphinx] and [MyST-parser]:
* When referencing chapters by file, use `[](/my-chapter)`, instead of relying on [explicit targets] for a top-level heading.
* To reference a figure by its title, use `[](#my-figure)` for a figure with the `:name:` attribute `my-figure` (and e.g. the title `My Figure`).
* To reference a figure by number (e.g. `Fig. 1`), use ```{numref}`my-figure` ``` for a figure with the `:name:` attribute `my-figure`.
#### Figures
[Figure] environments must have a `:name:` attribute, prefixed with `fig-`, so that they can be referenced elsewhere.
The `:alt:` attribute should explain what is displayed in the picture, as this is an [accessibility] feature. To keep matters brief, components and symbols that are described in other figures already, can be referenced by name instead of explaining them in detail.
## License
All text contributions fall under the terms of the [CC-BY-SA-4.0].
Configuration file contributions fall under the terms of the [CC0-1.0].
[`#notes-on-openpgp:matrix.org`]: https://matrix.to/#/%23notes-on-openpgp%3Amatrix.org
[Matrix]: https://matrix.org
[sphinx]: https://www.sphinx-doc.org/en/master/
[MyST-parser]: https://myst-parser.readthedocs.io/en/latest/
[HTML]: https://en.wikipedia.org/wiki/HTML
[EPUB]: https://en.wikipedia.org/wiki/EPUB
[MyST]: https://mystmd.org/guide/quickstart-myst-markdown
[codespell]: https://github.com/codespell-project/codespell
[lychee]: https://lychee.cli.rs
[explicit targets]: https://myst-parser.readthedocs.io/en/latest/syntax/cross-referencing.html#creating-explicit-targets
[Figure]: https://myst-parser.readthedocs.io/en/latest/syntax/images_and_figures.html#figures-images-with-captions
[accessibility]: https://en.wikipedia.org/wiki/Computer_accessibility
[CC-BY-SA-4.0]: ./LICENSES/CC-BY-SA-4.0.txt
[CC0-1.0]: ./LICENSES/CC0-1.0.txt

View file

@ -1,13 +1,16 @@
# SPDX-FileCopyrightText: 2023 The "Notes on OpenPGP" project # SPDX-FileCopyrightText: 2023 The "Notes on OpenPGP" project
# SPDX-License-Identifier: CC0-1.0 # SPDX-License-Identifier: CC0-1.0
FROM sphinxdoc/sphinx AS build FROM archlinux:latest AS build
RUN pip install myst-parser
COPY book/ /book COPY book/ /book
WORKDIR /book WORKDIR /book
RUN make html # fix EPUB rendering: https://github.com/sphinx-doc/sphinx/issues/11598
RUN make epub RUN \
pacman -Sy --needed --noconfirm archlinux-keyring \
&& pacman -Syu --needed --noconfirm epubcheck make patch python-myst-parser python-sphinx \
&& patch -Np1 -d /usr/lib/python3.11/site-packages/ -i /book/patches/sphinx-11766.patch \
&& make epub html
FROM scratch FROM scratch
COPY --from=build /book/build/html / COPY --from=build /book/build/html /
COPY --from=build /book/build/epub/OpenPGPforapplicationdevelopers.epub / COPY --from=build /book/build/epub/OpenPGPforapplicationdevelopers.epub /

View file

@ -7,6 +7,7 @@
# You can set these variables from the command line, and also # You can set these variables from the command line, and also
# from the environment for the first two. # from the environment for the first two.
CODESPELL ?= codespell CODESPELL ?= codespell
EPUBCHECK ?= epubcheck
SPHINXOPTS ?= -W SPHINXOPTS ?= -W
SPHINXBUILD ?= sphinx-build SPHINXBUILD ?= sphinx-build
LYCHEE ?= lychee LYCHEE ?= lychee
@ -14,6 +15,9 @@ PRINTF ?= printf
SOURCEDIR = source SOURCEDIR = source
BUILDDIR = build BUILDDIR = build
epub-check: clean epub
@$(EPUBCHECK) "$(BUILDDIR)/epub/"*.epub
# Put it first so that "make" without argument is like "make help". # Put it first so that "make" without argument is like "make help".
help: help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

View file

@ -0,0 +1,26 @@
diff --git a/sphinx/builders/html/__init__.py b/sphinx/builders/html/__init__.py
index 85067be0178..91d3647597c 100644
--- a/sphinx/builders/html/__init__.py
+++ b/sphinx/builders/html/__init__.py
@@ -1061,7 +1061,9 @@ def css_tag(css: _CascadingStyleSheet) -> str:
attrs.append(f'{key}="{html.escape(value, quote=True)}"')
uri = pathto(os.fspath(css.filename), resource=True)
if checksum := _file_checksum(outdir, css.filename):
- uri += f'?v={checksum}'
+ # the EPUB format does not allow the use of query components
+ if self.name != 'epub':
+ uri += f'?v={checksum}'
return f'<link {" ".join(sorted(attrs))} href="{uri}" />'
ctx['css_tag'] = css_tag
@@ -1092,7 +1094,9 @@ def js_tag(js: _JavaScript | str) -> str:
# https://github.com/sphinx-doc/sphinx/issues/11658
pass
elif checksum := _file_checksum(outdir, js.filename):
- uri += f'?v={checksum}'
+ # the EPUB format does not allow the use of query components
+ if self.name != 'epub':
+ uri += f'?v={checksum}'
if attrs:
return f'<script {" ".join(sorted(attrs))} src="{uri}"></script>'
return f'<script src="{uri}"></script>'

View file

@ -65,7 +65,7 @@ Some implementations explored other non-standardized extensions. Notably, algori
Today, multiple implementations of OpenPGP play important roles: Today, multiple implementations of OpenPGP play important roles:
- Proton Mail, which provides email encryption services for a large number of users, uses and maintains [OpenPGP.js](https://openpgpjs.org/) as well as [GopenPGP](https://gopenpgp.org/), an OpenPGP wrapper library written in golang. - Proton Mail, which provides email encryption services for a large number of users, uses and maintains [OpenPGP.js](https://openpgpjs.org/) as well as [GopenPGP](https://gopenpgp.org/), an OpenPGP wrapper library written in golang.
- The Mozilla Thunderbird email software uses [RNP](https://www.rnpgp.org/), its C++ implementation of OpenPGP. - The Mozilla Thunderbird email software uses [RNP](https://www.rnpgp.org/), a C++ implementation of OpenPGP.
- The RPM Package Manager software includes an OpenPGP backend based on [Sequoia PGP](https://sequoia-pgp.org/), a modern OpenPGP implementation written in Rust. The Fedora operating system, Fedora Linux 38, [uses Sequoia PGP in rpm](https://sequoia-pgp.org/blog/2023/04/27/rpm-sequoia/). - The RPM Package Manager software includes an OpenPGP backend based on [Sequoia PGP](https://sequoia-pgp.org/), a modern OpenPGP implementation written in Rust. The Fedora operating system, Fedora Linux 38, [uses Sequoia PGP in rpm](https://sequoia-pgp.org/blog/2023/04/27/rpm-sequoia/).
(interop_section)= (interop_section)=

View file

@ -6,14 +6,15 @@ SPDX-License-Identifier: CC-BY-SA-4.0
(cryptography_chapter)= (cryptography_chapter)=
# Cryptographic concepts and terms # Cryptographic concepts and terms
(crypto-hash)=
## Cryptographic hash functions ## Cryptographic hash functions
[Cryptographic hash functions](https://en.wikipedia.org/wiki/Cryptographic_hash_function) take data strings of any length (like a text message or file) and output a fixed-size code, a "hash digest," which is often abbreviated as either "digest" or "hash." A hash digest acts like a unique identifier for the original data. [Cryptographic hash functions](https://en.wikipedia.org/wiki/Cryptographic_hash_function) take data strings of any length (like a text message or file) and output a fixed-size code, a "hash digest," which is often abbreviated as either "digest" or "hash." A hash digest is also sometimes called a "(cryptographic) checksum." A hash digest acts like a unique identifier for the original data.
Here are two important properties of cryptographic hash functions: Cryptographic hash functions have two important properties:
- ["Pre-image resistance"](https://en.wikipedia.org/wiki/Preimage_attack): Given a hash digest, it should be very difficult to determine the original data it represents. - [**Pre-image resistance**](https://en.wikipedia.org/wiki/Preimage_attack): Given a hash digest, it should be very difficult to determine any data that matches this hash digest (including, but not limited to, the original data the hash represents). This property embodies the concept of a [one-way function](https://en.wikipedia.org/wiki/One-way_function) a calculation that is easy to perform, but very hard to reverse.
- ["Collision resistance"](https://en.wikipedia.org/wiki/Collision_resistance): It should be very difficult to find two distinct pieces of data that map to the same hash digest. - [**Collision resistance**](https://en.wikipedia.org/wiki/Collision_resistance): It should be very difficult to find two distinct pieces of data that map to the same hash digest.
## Message authentication codes ## Message authentication codes
@ -39,9 +40,10 @@ For detailed information on KDFs and their role in the OpenPGP protocol, see the
Participants in symmetric-key operations need to exchange the shared secret over a secure channel. Participants in symmetric-key operations need to exchange the shared secret over a secure channel.
```{figure} diag/symmetric_key.png ```{figure} diag/symmetric_key.png
--- :name: fig-symmetric-key
--- :alt: Depicts a box with a white background and the title "Symmetric key". In the box a single key symbol, rendered with full yellow line, is shown pointing to the right hand side.
A symmetric cryptographic key (which acts as a shared secret)
A symmetric cryptographic key (which acts as a shared secret)
``` ```
### Benefits and downsides ### Benefits and downsides
@ -82,7 +84,7 @@ By addressing the malleability problem, AEAD also counters a variation of the EF
[Public-key cryptography](https://en.wikipedia.org/wiki/Public-key_cryptography) uses asymmetric pairs of related keys. Each pair consists of a public key and a private key. These systems support encryption, decryption, and digital signature operations. [Public-key cryptography](https://en.wikipedia.org/wiki/Public-key_cryptography) uses asymmetric pairs of related keys. Each pair consists of a public key and a private key. These systems support encryption, decryption, and digital signature operations.
Unlike symmetric cryptography, participants are not required to pre-arrange a shared secret. In public-key cryptography, the public key material is shared openly for certain cryptographic operations, such as encryption and signature creation, while the private key, kept confidential, is used for operations like decryption and signature verification. Unlike symmetric cryptography, participants are not required to pre-arrange a shared secret. In public-key cryptography, the public key material is shared openly for certain cryptographic operations, such as encryption and signature verification, while the private key, kept confidential, is used for operations like decryption and signature creation.
(asymmetric_key_pair)= (asymmetric_key_pair)=
### Asymmetric cryptographic key pairs ### Asymmetric cryptographic key pairs
@ -90,19 +92,21 @@ Unlike symmetric cryptography, participants are not required to pre-arrange a sh
Throughout this document, we will frequently reference asymmetric cryptographic key pairs: Throughout this document, we will frequently reference asymmetric cryptographic key pairs:
```{figure} diag/asymmetric_keypair.png ```{figure} diag/asymmetric_keypair.png
--- :name: fig-asymmetric-keypair
--- :alt: Depicts a box with white background and the title "Asymmetric keypair". In the box two key symbols with text next to them are shown. The top key symbol is rendered using full green lines, points to the right hand side and has the accompanying text "Public key". The lower key symbol is rendered using dotted red lines, points to the left hand side and has the accompanying text "Private key".
An asymmetric cryptographic key pair An asymmetric cryptographic key pair
``` ```
Each key pair comprises two parts: the public key and the private key. For ease of identification, we will depict the public key in green and the private key in red throughout this document. Each key pair comprises two parts: the public key and the private key. For ease of identification in this documentation, the public key will be shown in green and the private key in red. Additionally, public keys are depicted with a solid border and pointing to the right, while private keys are shown with a dotted border and pointing to the left.
It's important to note that in many scenarios, only the public key is exposed or used (we will expand on these situations in subsequent sections): It's important to note that in many scenarios, only the public key is exposed or used. These situations will be elaborated upon in subsequent sections of this document.
```{figure} diag/public_key.png ```{figure} diag/public_key.png
--- :name: fig-public-key
--- :alt: Depicts a box with white background and the title "Public part of an asymmetric keypair". In the box one key symbol with text next to it is shown. The key symbol is rendered using full green lines, points to the right hand side and has the accompanying text "Public key".
The public parts of an asymmetric key pair
The public part of an asymmetric key pair
``` ```
### Usage and terminology in OpenPGP ### Usage and terminology in OpenPGP
@ -125,20 +129,14 @@ In OpenPGP, digital signatures have diverse applications, extending beyond mere
Digital signatures in OpenPGP are used in two primary contexts: Digital signatures in OpenPGP are used in two primary contexts:
- [Certification statements](component_signatures_chapter)
- [Data signatures](signing_data) - [Data signatures](signing_data)
- [Signatures on components](component_signatures_chapter)
(hybrid_cryptosystems)= (hybrid_cryptosystems)=
## Hybrid cryptosystems ## Hybrid cryptosystems
OpenPGP uses a hybrid cryptosystem. [Hybrid cryptosystems](https://en.wikipedia.org/wiki/Hybrid_cryptosystem) combine the use of symmetric and asymmetric (public-key) cryptography to capitalize on the strengths of each, namely symmetric cryptography's speed and efficiency and public-key cryptography's mechanism for secure key exchange. [Hybrid cryptosystems](https://en.wikipedia.org/wiki/Hybrid_cryptosystem) combine the use of symmetric and asymmetric (public-key) cryptography to capitalize on the strengths of each, namely symmetric cryptography's speed and efficiency and public-key cryptography's mechanism for secure key exchange.
```{admonition} TODO ### Usage and terminology in OpenPGP
:class: warning
Move this to the chapter that details it: OpenPGP uses a hybrid cryptosystem for encryption. This approach involves generating unique shared secrets, known as "session keys," for each session. For detailed information on this topic, please refer to the chapters {ref}`encryption_chapter` and {ref}`decryption_chapter`.
Within OpenPGP's hybrid system, so-called "session keys" are central. They are generated uniquely for each session and are instrumental in both encrypting and decrypting the actual message content, using the efficiency of symmetric-key cryptography.
Using asymmetric (public-key) cryptography, the session keys are also encrypted. This ensures that only the intended recipient, the holder of the corresponding private key, can decrypt and gain access to the session key. With the decrypted session key, they can then use the session key to decrypt the actual message.
```

View file

@ -6,7 +6,17 @@ SPDX-License-Identifier: CC-BY-SA-4.0
(certificates_chapter)= (certificates_chapter)=
# Certificates # Certificates
OpenPGP fundamentally hinges on the concept of "OpenPGP certificates," also known as "OpenPGP keys." These certificates are complex data structures essential for identity verification, data encryption, and digital signatures. Understanding their structure and function is pivotal to effectively applying the OpenPGP standard. OpenPGP fundamentally hinges on the concept of "OpenPGP certificates," also known as "OpenPGP public keys." These certificates are complex data structures essential for identity verification, data encryption, and digital signatures. Understanding their structure and function is pivotal to effectively applying the OpenPGP standard.
An OpenPGP certificate, by definition, does not contain private key material.
Fundamentally, the effective management of certificates and a thorough grasp of their authentication and trust models are crucial for proficient OpenPGP usage. Although this document offers just a brief overview of these aspects, they form a fundamental part of the broader OpenPGP framework and warrant further study.
- For an in-depth exploration of OpenPGP's private key material, refer to {ref}`private_key_chapter`. This chapter provides essential insights into private key management and security practices.
- The bindings that link the components of a certificate are comprehensively discussed in {ref}`component_signatures_chapter`, offering a deeper understanding of certificate structure and integrity.
- Finally, our chapter {ref}`zoom_certificates` discusses the internal structure of certificates in detail.
## Terminology: Understanding "keys" ## Terminology: Understanding "keys"
@ -26,8 +36,6 @@ In OpenPGP, the term "key" may refer to three distinct layers, each serving a un
The following section will delve into the OpenPGP-specific layers (2 and 3) to provide a clearer understanding of their roles within OpenPGP certificates. The following section will delve into the OpenPGP-specific layers (2 and 3) to provide a clearer understanding of their roles within OpenPGP certificates.
For a discussion of private key material in OpenPGP, see the chapter {ref}`private_key_chapter`. Bindings that connect the components of a certificate are discussed in our chapter {ref}`component_signatures_chapter`. For much more detail on the internal (packet) structure of certificates and keys refer to our chapter {ref}`zoom_certificates`. Additionally, managing certificates, and understanding their authentication and trust models are vital topics. While this document briefly touches upon these aspects, they are integral to working proficiently with OpenPGP.
## Structure of OpenPGP certificates ## Structure of OpenPGP certificates
An OpenPGP certificate (or "OpenPGP key") is a collection of an arbitrary number of elements[^packets]: An OpenPGP certificate (or "OpenPGP key") is a collection of an arbitrary number of elements[^packets]:
@ -41,14 +49,16 @@ An OpenPGP certificate (or "OpenPGP key") is a collection of an arbitrary number
This documentation collectively refers to component keys and identity components as "the components of a certificate." This documentation collectively refers to component keys and identity components as "the components of a certificate."
```{figure} diag/OpenPGP_Certificate.png ```{figure} diag/OpenPGP_Certificate.png
:name: fig-openpgp-certificate
:alt: Depicts a box with white background and the title "OpenPGP certificate". In the box several other boxes and accompanying texts, representing component keys and User IDs, are shown. There are three component keys boxes with a green frame, each with a dotted lower-left section, that shows the text "key creation time" and the green public key symbol in the lower right area. All three have a title, a unique fingerprint below the box and a unique capability keyword, perpendicular to the box on the right side. The top-most component key box has a light-green background, with the title "Component Key (primary)" and capability keyword "certification". The second-to-top component key box has a white background, with the title "Component Key" and capability keyword "encryption". The lowest component key box has a white background, with the title "Component Key" and capability keyword "signing". There are two User ID boxes, each with a black frame, open to top left and lower right corner. Both boxes have a user icon on the top left side, the title "User ID" on the top right side and a User ID string at the bottom. The top box has "Alice Adams <alice@example.org>" and the lower box has "Alice" as User ID string.
Typical components in an OpenPGP certificate Typical components in an OpenPGP certificate
``` ```
Every element in an OpenPGP certificate revolves around a central component: the *OpenPGP primary key*. The primary key acts as a personal CA (Certification Authority) for the certificate's owner, enabling cryptographic statements regarding subkeys, identities, expiration, revocation, and more. Every element in an OpenPGP certificate revolves around a central component: the *OpenPGP primary key*. The primary key acts as a personal *certification authority* (CA) for the certificate's owner, enabling cryptographic statements regarding subkeys, identities, expiration, revocation, and more.
```{note} ```{note}
OpenPGP certificates tend to have a long lifespan, with the potential for modifications (typically by their owner) over time. Components may be added or invalidated throughout a certificate's lifetime. OpenPGP certificates tend to have a long lifespan, with the potential for modifications (typically by their owner) over time. Components may be added or invalidated throughout a certificate's lifetime. However, once published, components [cannot be removed](append-only) from certificates.
``` ```
## Component keys ## Component keys
@ -60,19 +70,23 @@ OpenPGP component keys logically consist of an [asymmetric cryptographic keypair
[^ecdh-parameters]: For [ECDH](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-algorithm-specific-part-for-ecd) component keys, two additional algorithm parameters are integral to the component key's constitutive and immutable properties. Those parameters specify a hash function and a symmetric encryption algorithm. [^ecdh-parameters]: For [ECDH](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-algorithm-specific-part-for-ecd) component keys, two additional algorithm parameters are integral to the component key's constitutive and immutable properties. Those parameters specify a hash function and a symmetric encryption algorithm.
```{figure} diag/Component_Key.svg ```{figure} diag/Component_Key.svg
:name: fig-component-key
:alt: Depicts a box with white background and no title. In the box one other box is shown. The inner box has a green frame, with a dotted lower-left section, that shows the text "key creation time" and the green public key symbol, as well as the red-dotted private key symbol in the lower right area. In the top left of the inner box the text reads "Component Key".
An OpenPGP component key An OpenPGP component key
``` ```
In OpenPGP, component keys containing private key material also include metadata specifying the password protection scheme. This is another facet of metadata, akin to the aforementioned creation timestamp and additional parameters for certain algorithms. However, this discussion focuses on OpenPGP certificates, in which the component keys contain only the public part of its cryptographic key data. For information on private keys in OpenPGP, see {numref}`private_key_chapter`. Component keys containing private key material also include metadata specifying the password protection scheme. This is another facet of metadata, akin to the aforementioned creation timestamp and additional parameters for certain algorithms. However, this discussion focuses on OpenPGP certificates, in which the component keys contain only the public part of its cryptographic key data. For information on private keys in OpenPGP, see {numref}`private_key_chapter`.
### Fingerprint ### Fingerprint
Each OpenPGP component key possesses an *OpenPGP fingerprint*. This fingerprint is derived from the public key material, the creation timestamp, and, when relevant, the ECDH parameters. Each OpenPGP component key possesses an *OpenPGP fingerprint*. This fingerprint is derived from the public key material, the creation timestamp, and, when relevant, the ECDH parameters.
```{figure} diag/Fingerprint.png ```{figure} diag/Fingerprint.png
:name: fig-fingerprint
:alt: Depicts a box with white background and the title "Fingerprint of an OpenPGP component key". Inside, another box with a green frame, the title "Component Key", the text "key creation time" on the lower left and a the green public key symbol on the lower right is shown. Below the component key box a fingerprint in a box with a light-yellow background and a yellow dotted line is depicted. The word "Fingerprint" is shown left of the box with the fingerprint and both are connected with a yellow dotted line.
Every OpenPGP component key is identifiable by a fingerprint. Although it's technically possible for different keys to share a fingerprint, cryptographic mechanisms make it exceedingly difficult, if not practically impossible with current technology, to find keys that share a fingerprint. Every OpenPGP component key is identifiable by a fingerprint.
``` ```
The fingerprint of our example OpenPGP component key is `C0A5 8384 A438 E5A1 4F73 7124 26A4 D45D BAEE F4A3 9E6B 30B0 9D55 13F9 78AC CA94`[^keyid]. The fingerprint of our example OpenPGP component key is `C0A5 8384 A438 E5A1 4F73 7124 26A4 D45D BAEE F4A3 9E6B 30B0 9D55 13F9 78AC CA94`[^keyid].
@ -81,6 +95,12 @@ The fingerprint of our example OpenPGP component key is `C0A5 8384 A438 E5A1 4F7
For example, an OpenPGP version 4 certificate with the fingerprint `B3D2 7B09 FBA4 1235 2B41 8972 C8B8 6AC4 2455 4239` might be referenced by the 64-bit Key ID `C8B8 6AC4 2455 4239` or formatted as `0xC8B86AC424554239`. For example, an OpenPGP version 4 certificate with the fingerprint `B3D2 7B09 FBA4 1235 2B41 8972 C8B8 6AC4 2455 4239` might be referenced by the 64-bit Key ID `C8B8 6AC4 2455 4239` or formatted as `0xC8B86AC424554239`.
Historically, even shorter 32-bit identifiers were used, like this: `2455 4239`, or `0x24554239`. Such identifiers still appear in very old documents about PGP. However, [32-bit identifiers have been long deemed unfit for purpose](https://evil32.com/). At one point, 32-bit identifiers were called "short Key ID," while 64-bit identifiers were referred to as "long Key ID." Historically, even shorter 32-bit identifiers were used, like this: `2455 4239`, or `0x24554239`. Such identifiers still appear in very old documents about PGP. However, [32-bit identifiers have been long deemed unfit for purpose](https://evil32.com/). At one point, 32-bit identifiers were called "short Key ID," while 64-bit identifiers were referred to as "long Key ID."
```{note}
In practice, the fingerprint of a component key, while not theoretically unique, functions effectively as a unique identifier. The use of a [cryptographic hash algorithm](crypto-hash) in generating fingerprints makes the occurrence of two different component keys with the same fingerprint extremely unlikely[^finger-unique].
```
[^finger-unique]: For both OpenPGP version 6 and version 4, the likelihood of accidental occurrence of duplicate fingerprints is negligible when key material is generated based on an acceptable source of entropy. A separate question is if an attacker can purposely craft a second key with the same fingerprint as a given pre-existing component key. With the current state of the art, this is not possible for OpenPGP version 6 and version 4 keys. However, at the time of this writing, the SHA-1-based fingerprints of OpenPGP version 4 are considered insufficiently strong at protecting against the generation of pairs of key material with the same fingerprint.
### Primary key ### Primary key
The OpenPGP primary key is a component key that serves a distinct, central role in an OpenPGP certificate: The OpenPGP primary key is a component key that serves a distinct, central role in an OpenPGP certificate:
@ -101,46 +121,12 @@ Modern OpenPGP certificates typically include several subkeys in addition to the
While subkeys have the same structural attributes as the primary key, they fulfill different roles. Subkeys are cryptographically linked with the primary key, a relationship further discussed in {numref}`binding_subkeys`. While subkeys have the same structural attributes as the primary key, they fulfill different roles. Subkeys are cryptographically linked with the primary key, a relationship further discussed in {numref}`binding_subkeys`.
```{figure} diag/Subkeys.png ```{figure} diag/Subkeys.png
:name: Certificate with subkeys :name: fig-subkeys
:alt: Diagram depicting three component keys. The primary key is positioned at the top, designated for certification. Below it, connected by arrows, are two subkeys labeled as "for encryption" and "for signing," respectively. :alt: Diagram depicting three component keys. The primary key is positioned at the top, designated for certification. Below it, connected by arrows, are two subkeys labeled as "for encryption" and "for signing," respectively.
OpenPGP certificates can contain multiple subkeys. OpenPGP certificates can contain multiple subkeys.
``` ```
#### Defining operational capabilities with key flags
Each component key has a set of ["key flags"](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#key-flags) that delineate the operations a key can perform.
Commonly used key flags include:
- **Certification**: enables issuing third-party certifications
- **Signing**: allows the key to sign data
- **Encryption**: allows the key to encrypt data
- **Authentication**: primarily used for OpenPGP authentication
```{note}
Distinct component keys handle specific operations. Only the primary key can be used for certification, although it can have additional capabilities. Subkeys can be used for signing, encryption, and authentication but cannot have the certification capability. It is considered good practice, however, to [use separate keys for each capability](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#section-10.1.5-7).
Notably, in many algorithms, encryption and signing-related functionalities (i.e., certification, signing, authentication) are mutually exclusive, because the algorithms only support one of those two families of operations[^key-flag-sharing]).
```
[^key-flag-sharing]: With ECC algorithms, it's impossible to combine encryption functions with those intended for signing. For example, ed25519 is specifically used for signing; cv25519 is designated for encryption.
### Component key metadata, including key flags
The key flags for a component key are not stored within the component key directly.
Instead, key flags, along with other metadata about that component key, such as the key expiration time, are stored using mechanisms that bind components into an OpenPGP certificate:
- 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.
```{admonition} TODO
:class: warning
Write a section about algorithm preference/feature signaling
```
(identity_components)= (identity_components)=
## Identity components ## Identity components
@ -151,49 +137,44 @@ Identity components in an OpenPGP certificate are used by the certificate holder
OpenPGP certificates can contain multiple [User IDs](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-user-id-packet-tag-13). Each User ID associates the certificate with an identity. OpenPGP certificates can contain multiple [User IDs](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-user-id-packet-tag-13). Each User ID associates the certificate with an identity.
```{figure} diag/user_ids.png ```{figure} diag/user_ids.png
:name: fig-user-ids
:alt: Depicts a diagram with white background and the title "User IDs". Inside, a public primary component key for certification and a User ID is shown. A green arrow points from component key to User ID and is annotated with a signature.
OpenPGP certificates can contain any number of User IDs Relationship of User ID to primary component key in an OpenPGP certificate
```
```{admonition} Warning
This image could be visually improved! The new image should have an alt tag
``` ```
A typical User ID identity is a UTF-8-encoded string composed of a name and an email address. By convention, User IDs align with the format described in [RFC2822](https://www.rfc-editor.org/rfc/rfc2822) as a *name-addr*. A typical User ID identity is a UTF-8-encoded string composed of a name and an email address. By convention, User IDs align with the format described in [RFC2822](https://www.rfc-editor.org/rfc/rfc2822) as a *name-addr*.
For further conventions on User IDs, refer to the document [draft-dkg-openpgp-userid-conventions-00](https://datatracker.ietf.org/doc/draft-dkg-openpgp-userid-conventions/), dated 25 August 2023. For further conventions on User IDs, refer to the document [draft-dkg-openpgp-userid-conventions-00](https://datatracker.ietf.org/doc/draft-dkg-openpgp-userid-conventions/), dated 25 August 2023.
One proposed variant for encoding identities in User ID is to use ["split User IDs"](https://dkg.fifthhorseman.net/blog/2021-dkg-openpgp-transition.html#split-user-ids). **Split User IDs**
```{admonition} Warning One proposed variant for encoding identities in User IDs is to use ["split User IDs"](https://dkg.fifthhorseman.net/blog/2021-dkg-openpgp-transition.html#split-user-ids). Although uncommon, there are currently no significant technical barriers to implementing this format[^dkg-split].
Heiko, please clarify what the value is of this proposal or remove it.
``` [^dkg-split]: Historically, the OpenPGP ecosystem faced challenges in this context. For further details, refer to Daniel Kahn Gillmor's January 2019 article, ["What were Separated User IDs"](https://dkg.fifthhorseman.net/blog/2019-dkg-openpgp-transition.html#what-were-separated-user-ids).
The rationale for split User IDs lies in the distinction between a name and an email address, which represent two separate facets of an individual's identity. Separating these elements simplifies the process for third parties tasked with certifying that an identity is legitimately connected to a certificate.
Consider this scenario: A third party is confident about the email-based identity of an individual (e.g.,`<alice@example.org>`) and is willing to certify it. However, they might not have sufficient knowledge about the person's name-based identity (e.g., `Alice Adams`), so are unwilling to extend the same level of certification. Split User IDs address this dichotomy by allowing distinct certification processes for each type of identity.
(primary_user_id)= (primary_user_id)=
### Implications of the Primary User ID ### Implications of the 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). 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`). When a certificate is used in the context of a specific identity, then the preferences associated with that identity component are used. When a certificate is used without reference to a specific identity, the preferences associated with the direct key signature, or the primary User ID take precedence by default.
```{admonition} TODO The primary User ID was historically the main store for preferences that apply to the certificate as a whole. For more on this, see {ref}`primary-metadata`.
:class: warning
i think crypto-refresh suggests that the direct key signature should hold the default preferences?
we might need to write a more nuanced text here, about how DKS and primary user id interact in v6, and mention the differences to v4?
the primary User ID can also specify metadata about the primary key
```
### User attributes in OpenPGP ### User attributes in OpenPGP
While While
[user attributes](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-user-attribute-packet-tag-1) are similar to User IDs, they are less commonly used. [user attributes](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-user-attribute-packet-tag-1) are similar to User IDs, they are less commonly used.
Currently, the OpenPGP standard prescribes only one format to be stored in user attributes: an [image](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-the-image-attribute-subpack). Typically, this image represents the key owner, although it is not required. Currently, the OpenPGP standard prescribes only one format to be stored in user attributes: an [image](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-the-image-attribute-subpack) in JPEG format. Typically, this image represents the key owner, although it is not required.
## Linking the components ## Linking the components
To form an OpenPGP certificate, individual components are interconnected by the certificate holder using their OpenPGP software. Within OpenPGP, this process is termed "binding," as in "a subkey is bound to the primary key." These bindings are realized using cryptographic signatures. An in-depth discussion of this topic can be found in {ref}`component_signatures_chapter`). To form an OpenPGP certificate, individual components are interconnected by the certificate holder using their OpenPGP software. Within OpenPGP, this process is termed "binding," as in "a subkey is bound to the primary key." These bindings are realized using cryptographic signatures. An in-depth discussion of this topic can be found in {ref}`component_signatures_chapter`.
In very abstract terms, the primary key of a certificate acts as a root of trust or "certification authority." It is responsible for: In very abstract terms, the primary key of a certificate acts as a root of trust or "certification authority." It is responsible for:
@ -202,42 +183,97 @@ In very abstract terms, the primary key of a certificate acts as a root of trust
By binding components using digital signatures, recipients of an OpenPGP certificate need only validate the authenticity of the primary key to use for their communication partner. Traditionally, this is done by manually verifying the *fingerprint* of the primary key. Once the validity of the primary key is confirmed, the validity of the remaining components can be automatically assessed by the user's OpenPGP software. Generally, components are valid parts of a certificate if there is a statement signed by the certificate's primary key endorsing this validity. By binding components using digital signatures, recipients of an OpenPGP certificate need only validate the authenticity of the primary key to use for their communication partner. Traditionally, this is done by manually verifying the *fingerprint* of the primary key. Once the validity of the primary key is confirmed, the validity of the remaining components can be automatically assessed by the user's OpenPGP software. Generally, components are valid parts of a certificate if there is a statement signed by the certificate's primary key endorsing this validity.
## Metadata in certificates
OpenPGP certificates, their component keys, and identities possess metadata that is not stored within the components it pertains to. Instead, this metadata is stored within signature packets, which are integral to the structure of an OpenPGP certificate.
Key attributes, such as capabilities (like *signing* or *encryption*) and expiration times, are examples of metadata not stored in the component key data. How this metadata is stored depends on the component:
- **Primary key metadata** is defined either through a direct key signature on the primary key (preferred in OpenPGP version 6), or by associating the metadata with the [Primary User ID](primary_user_id).
- **Subkey metadata** is defined within the [subkey binding signature](binding_subkeys) that links the subkey to the certificate.
- **Identity component metadata** is associated via the [certifying self-signature](bind_ident) that links the identity (usually in the form of a User ID) to the certificate.
It is crucial to note that the components of an OpenPGP certificate remain static after their creation. The use of signatures to store metadata allows for subsequent modifications without altering the original components. For instance, a certificate holder can update the expiration time of a component by issuing a new, superseding signature.
### Defining operational capabilities of component keys with key flags
Each component key has a set of ["key flags"](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#key-flags) that delineate the operations a key can perform.
Commonly used key flags include:
- **Certification**: enables issuing third-party certifications
- **Signing**: allows the key to sign data
- **Encryption**: allows the key to encrypt data
- **Authentication**: primarily used for SSH authentication[^auth-flag]
[^auth-flag]: It's important to note that the function of the [authentication](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-authentication-via-digital-) key flag is unrelated to the authentication process used in certifying OpenPGP identities and linking them to certificates. Rather, this flag indicates a mechanism that uses cryptographic signatures to confirm control of private key material with a remote system.
```{note}
Distinct component keys handle specific operations. Only the primary key can be used for certification, although it can have additional capabilities. Subkeys can be used for signing, encryption, and authentication but cannot have the certification capability. A component key can technically have multiple capabilities. It is considered good practice, however, to [use separate keys for each capability](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#section-10.1.5-7).
Notably, in many algorithms, encryption and signing-related functionalities (i.e., certification, signing, authentication) are mutually exclusive, because the algorithms only support one of those two families of operations[^key-flag-sharing].
```
[^key-flag-sharing]: With ECC algorithms, it's impossible to combine encryption functions with those intended for signing. For example, ed25519 is specifically used for signing; cv25519 is designated for encryption.
### Algorithm preferences and feature signaling
OpenPGP incorporates significant ["cryptographic agility"](https://en.wikipedia.org/wiki/Cryptographic_agility). It doesn't rely on a single fixed set of algorithms. Instead, it defines a suite of cryptographic primitives from which users (or their applications) can choose.
This agility facilitates the easy adoption of new cryptographic primitives into the standard, allowing for a seamless transition. Users can gradually migrate to new cryptographic mechanisms without disruption.
However, this approach requires that OpenPGP software determine the cryptographic mechanisms that a set of communication partners can handle and prefer. OpenPGP employs several mechanisms for this purpose, which allow negotiation between sender and recipient. It's important to note that OpenPGP is not an online scheme; thus, this negotiation is effectively one-way. The active party interprets the preferences expressed in the certificate of the passive party.
Negotiation mechanisms in OpenPGP include:
- [Preferred hash algorithms](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#preferred-hashes-subpacket)
- [Preferred symmetric ciphers for v1 SEIPD](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#preferred-v1-seipd)
- [Preferred AEAD ciphersuites](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#preferred-v2-seipd)
- [Features subpacket](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#features-subpacket)
- [Preferred compression algorithms](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#preferred-compression-subpacket)
Beyond these explicitly expressed preferences, implementations also deduce capabilities of communication partners based on the version of the OpenPGP certificate they possess.
#### User ID-specific preferences
As a starting point, a certificate has a set of preferences that apply generally. These are defined either in a direct key signature, or via the primary User ID of the certificate.
Additionally, OpenPGP allows modeling User ID-specific preferences. The idea is that a user may prefer a different suite of algorithms on their private email account compared to their work email account. Such identity-specific preferences can be expressed on the certifying signatures that bind User IDs to a certificate.
## Revocations ## Revocations
```{admonition} TODO When a certificate owner needs to invalidate certain components of their certificate, or even the entire certificate, they accomplish this through "revocation." Revoking the primary key renders the entire certificate invalid.
:class: warning
This section needs to be written Notably, revocations are not the only means by which components can become invalid. Other factors, such as the passing of a component's expiration time, can also render components invalid.
```
For more detailed information on revoking specific components of a certificate, see the section on {ref}`self-revocations`.
## Third-party (identity) certifications ## Third-party (identity) certifications
```{admonition} TODO Since its inception, third-party identity certifications have been a cornerstone of the OpenPGP ecosystem. The original PGP designers, starting with Phil Zimmermann, advocated for decentralized trust models over reliance on centralized authorities. This decentralized approach in OpenPGP is known as the ["Web of Trust."](wot)
:class: warning
This section needs to be written Third-party certifications are statements by OpenPGP users confirming that a user with a specific identity is the owner of a particular OpenPGP certificate.
```
Third-party identity certifications have historically played a pivotal role in the OpenPGP ecosystem. For example, Bob's OpenPGP software may issue a certification that Bob has checked that the User ID `Alice Adams <alice@example.org>` and the certificate with the fingerprint `AAA1 8CBB 2546 85C5 8358 3205 63FD 37B6 7F33 00F9 FB0E C457 378C D29F 1026 98B3` are legitimately linked.
Take, for instance, a scenario where Bob's OpenPGP software issues a certification confirming as legitimate the link between the User ID `Alice Adams <alice@example.org>` and the certificate bearing the fingerprint `AAA1 8CBB 2546 85C5 8358 3205 63FD 37B6 7F33 00F9 FB0E C457 378C D29F 1026 98B3`.
This process assumes that Bob knows the person known as `Alice Adams` and is confident that `alice@example.org` is indeed Alice's email address. Bob also verifies that the certificate his OpenPGP software associates with Alice matches the one Alice uses. In essence, both users must have a certificate for Alice with an identical fingerprint. In OpenPGP version 6, manual fingerprint comparison by end-users is discouraged, with a replacement verification mechanism still under development. The verification process must occur over a sufficiently secure channel, such as an end-to-end encrypted video call or a face-to-face meeting.
For more on third-party certifications, see {ref}`third_party_cert`.
(cert-flooding)=
### Security considerations ### Security considerations
While a convenience for consumers, indiscriminately accepting and integrating third-party identity certifications comes with significant risks. While a convenience for consumers, indiscriminately accepting and integrating third-party identity certifications comes with significant risks.
Without any restrictions in place, malicious entities can flood a certificate with excessive certifications. Called "certificate flooding," this form of digital vandalism grossly expands the certificate size, making the certificate cumbersome and impractical for users. Without any restrictions in place, malicious entities can flood a certificate with excessive certifications. Called "certificate flooding," this form of digital vandalism grossly expands the certificate size, making the certificate cumbersome and impractical for users.
It also opens the door to potential denial-of-service attacks, rendering the certificate non-functional or significantly impeding its operation. It also opens the door to potential denial-of-service attacks, rendering the certificate non-functional or significantly impeding its operation.
The popular [SKS keyserver network experienced certificate flooding firsthand](https://dkg.fifthhorseman.net/blog/openpgp-certificate-flooding.html), causing it to shut down operations in 2019.
### Improved mechanisms in OpenPGP v6
```{admonition} TODO
:class: warning
This section needs to be written
```
The popular [SKS keyserver network experienced certificate flooding firsthand](https://dkg.fifthhorseman.net/blog/openpgp-certificate-flooding.html), causing it to shut down operations in 2019.
## Advanced topics ## Advanced topics
@ -247,6 +283,7 @@ This section needs to be written
This section only contains notes and still needs to be written This section only contains notes and still needs to be written
``` ```
(append-only)=
### Certificate management / Evolution of a certificate over time ### Certificate management / Evolution of a certificate over time
Minimized versions, merging, effective "append only" semantics, ... Minimized versions, merging, effective "append only" semantics, ...
@ -305,3 +342,13 @@ references/links missing
``` ```
Some OpenPGP subsystems may add User IDs to a certificate, which are not bound to the primary key by the certificate's owner. This can be useful to store local identity information (e.g., Sequoia's public store attaches "pet-names" to certificates, in this way). Some OpenPGP subsystems may add User IDs to a certificate, which are not bound to the primary key by the certificate's owner. This can be useful to store local identity information (e.g., Sequoia's public store attaches "pet-names" to certificates, in this way).
### Third-party certification flooding
While a convenience for consumers, indiscriminately accepting and integrating third-party identity certifications comes with significant risks.
Without any restrictions in place, malicious entities can flood a certificate with excessive certifications. Called "certificate flooding," this form of digital vandalism grossly expands the certificate size, making the certificate cumbersome and impractical for users.
It also opens the door to potential denial-of-service attacks, rendering the certificate non-functional or significantly impeding its operation.
The popular [SKS keyserver network experienced certificate flooding firsthand](https://dkg.fifthhorseman.net/blog/openpgp-certificate-flooding.html), causing it to shut down operations in 2019.

View file

@ -6,27 +6,43 @@ SPDX-License-Identifier: CC-BY-SA-4.0
(private_key_chapter)= (private_key_chapter)=
# Private key material in OpenPGP # Private key material in OpenPGP
This chapter discusses the handling of private key material, in OpenPGP. Private key material is associated with component keys that are parts of [OpenPGP certificates](certificates_chapter). For a discussion of packet structure internals, see the chapter {ref}`zoom_private` This chapter discusses the handling of private key material in OpenPGP.
Historically, terminology around OpenPGP certificates and keys has often been used inconsistently. The pair of terms "OpenPGP public key" and "OpenPGP private/secret keys" were commonly used (while the shorthand "OpenPGP key" can refer to both, depending on context). Private key material is associated with component keys that are parts of [OpenPGP certificates](certificates_chapter). For a discussion of packet structure internals, see the chapter {ref}`zoom_private`
## Terms ## Terminology: "Certificates" and "private keys"
In this document, we use the term *OpenPGP certificate* to refer "OpenPGP public keys": The combination of component public keys, identity components and bindings. Recall that in this document, we use the term *OpenPGP certificate* to refer to what are often called "OpenPGP public keys": OpenPGP certificates are the combination of component public keys, identity components, binding self-signatures and third-party certifications (as discussed in the previous chapter, {ref}`certificates_chapter`).
This chapter is about the counterpart to the public material in certificates: Here, we discuss the handling of *private key material* in OpenPGP. This chapter is about the remaining counterpart to the elements of certificates: The corresponding *private key material* of component keys.
In this text, we treat the private key material as logically separate from the OpenPGP certificate. Operations that use the private key material are typically handled by a separate subsystem. It is useful to think about OpenPGP certificates on one hand, and the associated private key material, on the other, as two related elements, which are usually handled separately[^pkcs11]:
In this book, we treat the private key material as logically separate from the OpenPGP certificate. A separate subsystem typically handles operations that use private key material. It is useful to think about OpenPGP certificates on one hand, and the associated private key material, on the other, as related but separate elements[^pkcs11]:
```{figure} diag/OpenPGPCert_with_privatekeystore.png ```{figure} diag/OpenPGPCert_with_privatekeystore.png
:name: fig-openpgp-certificate-with-private-key-store
:alt: Depicts a diagram on white background with an OpenPGP Certificate and a private key store. Gray dotted lines connect the green public key symbols of the OpenPGP Certificate with red dotted private key symbols in the private key store.
An OpenPGP certificate, with the associated private key material handled by a key store subsystem. An OpenPGP certificate, with the associated private key material handled in a separate subsystem.
``` ```
[^pkcs11]: This kind of distinction between certificates (which combine public key material and identity information) on the one hand, and private key material on the other, is also applied in the data model of [PKCS #11](https://en.wikipedia.org/wiki/PKCS_11) cryptographic systems. [^pkcs11]: This kind of distinction between certificates (which combine public key material and identity information) on the one hand, and private key material on the other, is also applied in the data model of [PKCS #11](https://en.wikipedia.org/wiki/PKCS_11) cryptographic systems.
However, there is one exception. Raw cryptographic private key material is sometimes embedded in an OpenPGP framing format that additionally contains the certificate: [*Transferable secret keys (TSK)*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-transferable-secret-keys). However, there is one exception. The cryptographic private key material is sometimes embedded in an OpenPGP framing format that also contains the certificate: Transferable secret keys (TSK).
## Transferable secret key format
Sometimes it is useful to handle OpenPGP certificates combined with private key material in the form of [*transferable secret keys (TSK)*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-transferable-secret-keys). Transferable secret keys are a serialized format that combines OpenPGP certificate data with the connected private key material, stored in a single file.
```{figure} diag/TSK.png
:name: fig-transferable-secret-key
:alt: Depicts a box on white background with the title "Transferable secret key". It is identical to the figure depicting an OpenPGP certificate, with the exception, that in each component key box, below the green public key symbol, also the red dotted private key symbol is shown.
OpenPGP certificate with integrated private key material, as a TSK
```
The TSK format can be useful for backups of OpenPGP key material, or to move a key to a different computer[^gpg-tsk]. See the chapter {ref}`zoom_private` for insights into the packet structure of a TSK.
[^gpg-tsk]: For example, with GnuPG, an OpenPGP key can be exported in (armored) TSK format like this: `gpg --export-secret-key --armor <fingerprint>`
```{admonition} Terminology ```{admonition} Terminology
:class: note :class: note
@ -34,89 +50,187 @@ However, there is one exception. Raw cryptographic private key material is somet
Transferable secret keys are sometimes colloquially referred to as "OpenPGP private keys". Transferable secret keys are sometimes colloquially referred to as "OpenPGP private keys".
``` ```
## Transferable secret keys Historically, the concept of TSKs, which combine all aspects of an OpenPGP certificate and the associated private key material, has sometimes been conflated with OpenPGP private key operations. We consider it more helpful to think of TSKs as a specialized format for storage/transport, and not as a data structure for use in a key store. Also see {ref}`key-store-design`.
Sometimes users handle OpenPGP certificates combined with private key material in the form of *transferable secret keys* (TSK). Transferable secret keys are a serialized format that combines the OpenPGP certificate data with the connected private key material, stored in a single file.
```{figure} diag/TSK.png
OpenPGP certificate with integrated private key material, as a TSK
```
The TSK format can be useful for backups of OpenPGP key material, or to move a key to a different computer[^gpg-tsk].
[^gpg-tsk]: For example, with GnuPG, an OpenPGP key can be exported in (armored) TSK format like this: `gpg --export-secret-key --armor <fingerprint>`
See the chapter {ref}`zoom_private` for insights into the packet structure of a TSK.
(encrypted_secrets)= (encrypted_secrets)=
## Protecting private key material with a passphrase (using S2K) ## Protection of private key material in OpenPGP
In OpenPGP format, private key material can optionally be protected with a [passphrase](https://en.wikipedia.org/wiki/Passphrase).
In OpenPGP format, private key material can be optionally protected with a [passphrase](https://en.wikipedia.org/wiki/Passphrase). This mechanism applies symmetric encryption to the private key data in component keys. Protecting private key material with a passphrase can be useful when a third party obtains a copy of the OpenPGP key data, but doesn't know the passphrase. In this scenario, the attacker may have obtained a copy of an OpenPGP key, but is unable to use it, because it is protected with a passphrase that is not known to the attacker.
The symmetric encryption key is derived from a secret that the user knows (the passphrase). ### Transforming a passphrase into a symmetric key
Using a passphrase can be useful when a third party can obtain a copy of the OpenPGP key data, but doesn't know the passphrase. In this scenario, an attacker may have obtained a copy of an OpenPGP key, but is unable to use it, because the private key material is encrypted, and the attacker cannot decrypt it. When protecting private key material in OpenPGP, a symmetric key is derived from the user's passphrase. This key is then used to protect the OpenPGP private key data.
OpenPGP defines a mechanism called [string-to-key (S2K)](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-string-to-key-s2k-specifier) that is used to derive (high-entropy) symmetric encryption keys from (lower-entropy) passphrases, using a [key derivation function (KDF)](https://en.wikipedia.org/wiki/Key_derivation_function). For this purpose, the OpenPGP standard defines a family of mechanisms called [string-to-key (S2K)](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-string-to-key-s2k-specifier). These are used to derive (high-entropy) symmetric encryption keys from (lower-entropy) passphrases, using a [key derivation function (KDF)](https://en.wikipedia.org/wiki/Key_derivation_function).
```{figure} diag/passphrase_using_S2K.png ```{figure} diag/passphrase_using_S2K.png
:name: fig-passphrase-using-s2k
:alt: Depicts a diagram on white background with the title "Converting a passphrase into a symmetric key". On the left hand side a box with dotted yellow frame and light yellow background and the text "correct horse battery staple" is shown. It is connected by a dotted yellow line with the word "Passphrase". Right of the passphrase an arrow with green dotted frame, light green background and the text "S2K mechanism (string-to-key)", pointing to the right is shown. On the right hand side the yellow symmetric key symbol is shown.
Transforming a passphrase into a symmetric key Deriving a symmetric key from a passphrase
``` ```
The private key material for individual component keys of one certificate can be encrypted with different mechanisms, and/or using different passphrases. This symmetric key is used to protect the private key material "at rest." E.g., while it is stored on disk. To use a passphrase-protected OpenPGP private key, it is decrypted using the symmetric key, and used for private key operations, while it is temporarily unlocked, in memory.
However, this is not customarily done. Usually, when creating a certificate, the user's software will use the same encryption mechanism and passphrase for all component keys (to limit complexity). #### Mechanisms for symmetric key generation
However, when adding new subkeys to a certificate at a later date, the user might choose to use a different passphrase. Or the user's software may choose a different encryption mechanism, e.g. based on updated best practices. Over time, OpenPGP has specified different S2K [mechanisms to generate symmetric keys](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-string-to-key-s2k-types-reg), following the state of the art. Of these, two are recommended unconditionally, today:
### S2K mechanisms for symmetric key generation - [Argon2](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-argon2), which was newly added in OpenPGP version 6. It is a memory-hard mechanism, which reduces the efficiency of brute-force attacks with specialised hardware.
- [Iterated and Salted S2K](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-iterated-and-salted-s2k), which OpenPGP version 4 implementations can handle.
Over time, OpenPGP has specified a series of [S2K mechanisms](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-string-to-key-s2k-types-reg), following the current state of the art. Of the specified S2K mechanisms, two remain relevant today: A third mechanism is allowed conditionally for generation. Decryption of private keys that use obsolete mechanisms is allowed.
- [Iterated and Salted S2K](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-iterated-and-salted-s2k), which OpenPGP version 4 implementations can handle The RFC refers to the mechanism that is used to *generate* a symmetric key from a passphrase with the term "String-to-Key (S2K) specifier" or "String-to-Key (S2K) specifier type."
- [Argon2](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-argon2), which was newly added in OpenPGP version 6, and additionally protects the passphrase against brute-force attacks because it is memory-hard (which reduces the efficiency of attacks with specialised hardware)
### Mechanisms for secret key encryption with S2K ### Using the symmetric key for encryption
Different mechanisms are specified [for the encryption of the secret key data](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-secret-key-encryption). So far, we've looked at generating a symmetric key from a passphrase. Following that, the symmetric key is used to encrypt or decrypt the OpenPGP private key material.
The RFC refers to the mechanism that is used to *apply* the symmetric key with the term "String-to-Key Usage (S2K usage)".
## Private key operations Different mechanisms are specified [for encryption of OpenPGP private key material](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-secret-key-encryption).
The core of private key operations doesn't require access to the whole certificate. ### Passphrase-protection acts per-component key
Designs of private key subsystems in the OpenPGP space differ: The OpenPGP mechanism for protecting private key material applies individually to each component key:
- Some designs perform the primitive cryptographic operations in a separate backend, only using the cryptographic key material itself. This type of design matches well with general purpose hardware cryptographic devices (such as TPMs). - Private key material for individual component keys of one certificate can be protected with different mechanisms, and/or
- In other designs, the OpenPGP private key subsystem requires the additional metadata that is stored in the component key (the key creation time, for all keys, and in the case of keys that use ECDH algorithms: the KDF parameters). - using different passphrases.
- Individual component keys may be stored in unprotected form, while others are protected.
Either way: at most, a private key subsystem should need access to individual component keys and the associated private key material. However, usually, when creating a certificate, the user's software will use the same encryption mechanism and passphrase for all component keys. This might give the erroneous impression that all component private key material is internally encrypted in one monolithic operation, necessarily using only one passphrase.
```{note} But for example when adding new subkeys to a certificate at a later date, the user might choose to use a different passphrase. Or the user's software may choose a different encryption mechanism, e.g., based on updated best practices.
Keeping a copy of the full certificate information in the private key subsystem can cause "split brain" problems. E.g.: expiration times could then differ between different subsystems, when they keep different copies of the certificate information. (card-priv)=
## OpenPGP card for private keys
(Thunderbird users currently suffer from such issues, I think) [OpenPGP card](https://en.wikipedia.org/wiki/OpenPGP_card) devices are a type of hardware security device.
```
### OpenPGP card for private keys They are one popular way to handle OpenPGP private key material. Using an OpenPGP card is an alternative to directly handling private key material on the user's computer.
[OpenPGP card](https://en.wikipedia.org/wiki/OpenPGP_card) devices are a type of hardware security device. They are one popular way to handle OpenPGP private key material. Hardware security devices, such as OpenPGP cards, are designed so that the user's computer never has direct access to the private key material. The goal is to make it impossible to exfiltrate the key material, even when a remote attacker has fully compromised the user's system.
OpenPGP card devices implement an open specification: [Functional Specification of the OpenPGP application on ISO Smart Card Operating Systems, Version 3.4.1](https://gnupg.org/ftp/specs/OpenPGP-smart-card-application-3.4.1.pdf). Multiple vendors produce devices that implement this specification, and there are a number of Free Software implementations (some of which can even be run on open hardware designs). OpenPGP card devices implement an open specification: [Functional Specification of the OpenPGP application on ISO Smart Card Operating Systems, Version 3.4.1](https://gnupg.org/ftp/specs/OpenPGP-smart-card-application-3.4.1.pdf). Multiple vendors produce devices that implement this specification, and there are a number of Free Software implementations (some of which can even be run on open hardware designs).
Effectively, the OpenPGP card specification outlines one model for an OpenPGP private key subsystem: Effectively, the OpenPGP card specification outlines one model for an OpenPGP private key store subsystem:
OpenPGP card devices do not store the full OpenPGP certificate. Instead, they have three "key slots": one each for signing, decryption and authentication. Each key slots stores the component key data and the associated cryptographic private key material[^missing-ecdh]. In addition, for each key slot, the OpenPGP fingerprint for the contained component key is explicitly stored on the card (note that storing the fingerprint on the card is different from how OpenPGP key data is usually handled: normally, fingerprints are not explicitly stored, but calculated on the fly from the component key data). OpenPGP card devices do not store a full OpenPGP certificate. Instead, they have three "key slots", one each for *signing*, *decryption* and *authentication*. Each key slot stores the data of one component key[^missing-ecdh], complete with cryptographic private key material. Additionally, the fingerprint for the component key in each key slot is explicitly stored on the card.
[^missing-ecdh]: In the case of ECDH keys, the KDF parameters (hash function ID and a symmetric encryption algorithm ID) are not stored on the OpenPGP card. This is considered a flaw in the OpenPGP card specification. These missing parameters can be handled in two ways, by OpenPGP software running on the host computer: Either by consulting a copy of the component key (e.g. by inspecting a copy of the certificate), or by deducing the missing KDF parameters from the OpenPGP fingerprint that is stored on the card. [^missing-ecdh]: In the case of ECDH keys, the KDF parameters (hash function ID and a symmetric encryption algorithm ID) are not stored on the OpenPGP card. This is considered a flaw in the OpenPGP card specification. These missing parameters can be handled in two ways, by OpenPGP software running on the host computer: Either by consulting a copy of the component key (e.g. by inspecting a copy of the certificate), or by deducing the missing KDF parameters from the OpenPGP fingerprint that is stored on the card.
Note that explicitly stored fingerprints on OpenPGP cards are in contrast to how OpenPGP's format stores component keys: fingerprints are not explicitly stored, but calculated on the fly from the component key data.
## Private key operations
While OpenPGP as a whole employs a broad range of cryptographic mechanisms, the set of operations that are performed in the core of a private key store are simple and very limited.
Specifically, an OpenPGP private key store implements two primitives:
1. Given private key material whose algorithm supports decryption, it can decrypt a *session key*.
2. Given private key material whose algorithm supports signing, it can calculate a *cryptographic signature* for a hash digest.
All required operations can be performed with access to the component keys, including their private key material. That is, [Secret-Key packets](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-secret-key-packet-formats). Additional packets, such as binding signatures, are not required for the operations in a private key store.
(key-store-design)=
## Private key stores
### Design options
Designs of private key subsystems in the OpenPGP space differ:
1. Some designs perform the primitive cryptographic operations in a separate backend, only using the cryptographic key material itself. This type of design matches well with general purpose hardware cryptographic devices (such as TPMs).
2. An OpenPGP private key subsystem may be built around component keys - that is, the content of [Secret-Key packets](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-secret-key-packet-formats). These include metadata, which is required for some operations. ECDH operations, in particular, require metadata as KDF parameters.
3. Keeping a copy of full TSKs in the private key subsystem, and using those for private key operations.
Private key store operations require component keys, but do not require access to the rest of the certificate.
```{note}
Design 3, which involves keeping a copy of full TSKs in the private key subsystem can cause "split brain" problems.
For example, the private key store may contain a TSK, with outdated certificate metadata. The certificate may be considered expired, based on data in the TSK, while the copy of the same certificate in the local public key store might show an updated version where the expiration date has been extended[^tb-split].
This class of problem existed in GnuPG 1.x, which held separate copies of full TSKs in its private store component.
```
[^tb-split]: The current design of Thunderbird's OpenPGP subsystem can lead to users experiencing such issues.
### Two tiers
At its core, an OpenPGP private key subsystem performs operations that only require the private cryptographic key material, as in design 1.
However, some operations require additional access to the metadata of the component key. Those operations can be considered supplementary to the core keystore operations, and don't involve the private key material, themselves. When implementing a key store based on hardware cryptographic devices, like [OpenPGP card](card-priv), its design will consist of two layers:
- One that deals immediately with private key material, and
- One that performs additional cryptographic operations, which don't directly use the private key material (in particular: [AES key wrap](https://www.rfc-editor.org/rfc/rfc3394.html) for ECDH).
```{note}
Decryption with ECC algorithms using ECDH in particular is a multi-step procedure.
Only one of these steps deals directly with private key material, and is performed by e.g. an OpenPGP card device. This step produces the "shared secret".
An additional ["AES key unwrap"](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-ec-dh-algorithm-ecdh) step happens in software, outside the card. Also see "Advanced Encryption Standard (AES) Key Wrap Algorithm" [RFC 3394](https://www.rfc-editor.org/rfc/rfc3394.html).
```
### Addressing individual keys
An independent design question is how key material is addressed, by users of the keystore.
The fingerprint of the individual component keys is one obvious option.
Depending on what backs the keystore, fingerprints are readily available, such as with software private keys, or OpenPGP card devices. In other cases, the key store needs to keep track of fingerprints by itself, e.g., when based on generic cryptographic hardware such as TPM.
### Assorted other duties
Additionally, a key store may want to keep track of devices that contain particular component keys. It may need to deal with secrets, such as passphrases of software keys, or PINs of OpenPGP card devices. It may need to notify the user that some interaction is required. For example, some OpenPGP card devices can require touch confirmation to authorize each cryptographic operation.
### Visualizing key store operations
#### Signing
```{admonition} TODO
:class: warning
write
```
```{admonition} VISUAL
:class: warning
show examples for the operations in a private key store.
- reuse the visual elements of the lowest level in the ch6 "how signatures are made" diagram (ch 6): "making a cryptographic signature from a hash digest"
```
#### Decryption
```{admonition} TODO
:class: warning
write
```
```{admonition} VISUAL
:class: warning
show examples for the operations in a private key store.
- once we have a visual for the low level asymmetric decryption operation (in ch11), mirror it here
```
## Advanced topics ## Advanced topics
### TSKs: Best practices S2K + S2K migration? ### TSKs: Best practices S2K + S2K migration?
```{admonition} TODO
:class: warning
write
```
### The KOpenPGP attack ### The KOpenPGP attack
See [https://www.kopenpgp.com/](https://www.kopenpgp.com/) See [https://www.kopenpgp.com/](https://www.kopenpgp.com/)

View file

@ -17,6 +17,8 @@ Within OpenPGP, the term *signature* can have two different meanings:
- **OpenPGP signature packets**: Defined in the [OpenPGP standard](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-signature-packet-type-id-2), these packets combine a raw cryptographic signature along with a *type* designation and additional metadata. - **OpenPGP signature packets**: Defined in the [OpenPGP standard](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-signature-packet-type-id-2), these packets combine a raw cryptographic signature along with a *type* designation and additional metadata.
```{figure} diag/meaning_of_signatures.png ```{figure} diag/meaning_of_signatures.png
:name: fig-meaning-of-signatures
:alt: Depicts a box on white background with the title "Meanings of signature in OpenPGP", "signature" in italics. The top half of the box shows a green seal symbol with the word "sig" in it on the left side. The symbol is connected to the text "Cryptographic signature" by a black dotted line. The bottom half of the box shows a diagram. On the left hand side a box with green dotted frame and white background provides the title "Signature type", while inside the box the text reads "Signature over Signature data, Signature metadata". The words "Signature metadata" serve as title for a yellow box at the lower half of the signature type box. The yellow box also contains a cryptographic signature symbol. Right of the signature type box, the text "OpenPGP signature packet" is shown, which is connected to the box by a green dotted line. Below the text a list is shown, which reads "signature type, signature over input data, additional metadata and cryptographic signature". The last item is connected to the cryptographic signature symbol in the yellow box by a black dotted line.
Two meanings of the term "signature" in OpenPGP Two meanings of the term "signature" in OpenPGP
``` ```
@ -26,7 +28,7 @@ In this document, "signature" will refer to OpenPGP signature packets.
(signature_types)= (signature_types)=
## Signature types in OpenPGP ## Signature types in OpenPGP
The OpenPGP standard defines a set of [Signature types](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-signature-types), each identified by a numerical *signature type ID*. Signature types define the purpose of a signature and how it should be interpreted. The OpenPGP standard defines a set of [Signature types](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-signature-types), each identified by a numerical *signature type ID*. Signature types define the purpose of a signature packet and how it should be interpreted.
Signature types can be predominantly classified in two ways: Signature types can be predominantly classified in two ways:
@ -39,6 +41,8 @@ Signatures on components are a complex topic, and we discuss them in depth in {r
- the nature of the statement made by the signature, such as certifying an identity or binding component keys into a certificate - the nature of the statement made by the signature, such as certifying an identity or binding component keys into a certificate
```{figure} mermaid/sig-types.png ```{figure} mermaid/sig-types.png
:name: fig-signature-types
:alt: Depicts a diagram, describing different types of OpenPGP signatures. On the right hand side a long yellow box with the title "Signature Types and Targets" is shown, which contains signature type IDs and their names (in gray boxes) and further yellow boxes, grouping other types of signature type IDs. At the top the signature type ID "0x02 Standalone" is shown. Below, another yellow box groups the "Signature Packet"s "0x50 Third-Party Confirmation" and "0x40 Timestamp". Another box groups types of signatures, that apply to "Data" packets "0x00 Binary Data" and "0x01 Canonical Text". Below, a box groups types of signatures, that apply to "Primary Key + User ID/ Attr. Packet"s. The type IDs "0x10 Generic Certification", "0x11 Persona Certification", "0x12 Casual Certification" and "0x13 Positive Certification" are shown together in one gray box and "0x30 Certification Revocation" in another. Another yellow box groups types of signatures, that apply to "Primary Key" packets "0x1F Direct-Key Signature" and "0x20 Key Revocation". The last box groups types of signatures, that apply to "Primary + Subkey" packets. "0x18 Subkey Binding" and "0x19 Primary Key Binding" are shown together in one gray box, "0x28 Subkey Revocation" in another. On the left hand side of the diagram shows gray boxes identifying different types of signatures, with the most basic being "OpenPGP Signature" on the far left. With arrows it points to further signature types ("Signature on Data", "Signature on Component") and several signature type IDs ("0x02", "0x50" and "0x40"). The signature type "Signature on Data" points to "0x00" and "0x01". The signature type "Signature on Component" points to two more specific signature types, namely "Third-Party" and "Self-Signature". "Third-Party" points at the group of "0x10", "0x11", "0x12" and "0x13", as well as "0x30" and "0x1F". "Self-Signature" points at the group of "0x10", "0x11", "0x12" and "0x13", as well as "0x30", "0x1F", the group of "0x18" and "0x19" and finally "0x28".
An overview of signature types in OpenPGP An overview of signature types in OpenPGP
``` ```
@ -56,6 +60,8 @@ As outlined above, an OpenPGP signature is a composite data structure, which com
- **Raw cryptographic signature** - **Raw cryptographic signature**
```{figure} diag/signature_packet.png ```{figure} diag/signature_packet.png
:name: fig-signature-packet
:alt: Depicts a diagram with the title "A signature packet". On the left hand side a box with green dotted frame and white background provides the title "Signature type", while inside the box the text reads "Signature over Signature data, Signature metadata". The words "Signature metadata" serve as title for a yellow box at the lower half of the signature type box. The yellow box also contains a cryptographic signature symbol. Right of the signature type box, the text "OpenPGP signature packet" is shown, which is connected to the box by a green dotted line. Below the text a list is shown, which reads "signature type, signature over input data, additional metadata and raw cryptographic signature". The last item is connected to the cryptographic signature symbol in the yellow box by a black dotted line.
Structure of an OpenPGP signature packet Structure of an OpenPGP signature packet
``` ```
@ -79,6 +85,8 @@ The signature packet consists of two parts:
- The signature is then calculated for this hash digest. - The signature is then calculated for this hash digest.
```{figure} diag/Signature_Creation.png ```{figure} diag/Signature_Creation.png
:name: fig-signature-creation
:alt: Depicts a complex diagram with white background and the title "Signature creation". On the top left side a box with black frame and white background reads "Input Data packets, One or more packets". Below it the symbol of a signature packet is shown (however, instead of the green signature symbol, only a circle with white background and dotted frame is shown). Both are connected (via green dotted arrows) to a green, right pointing arrow symbol with green dotted frame and the title "Hash mechanism". Text above the green arrow symbol reads "A hash digest is calculated from the input data packets and the signature metadata". The "Hash mechanism" arrow points at a box with white background and green frame, which reads "hash digest". At the top right corner of the diagram the symbol for a component key with both public and private key and the title "Signer private key" is shown. Both hash digest and component key symbol point to a large green arrow symbol, with green dotted frame, at the lower right corner of the diagram, using green dotted arrow lines. The large arrow symbol has the title "Signing mechanism" and text overlaid across it reads "A cryptographic signature is calculated over the hash digest, using the private key material of the signer.". It points at a cryptographic signature symbol at the bottom of the diagram. The cryptographic signature symbol is connected (via a green dotted arrow line) to the circle with white background and dotted green frame in the signature packet symbol.
Creating a signature in OpenPGP Creating a signature in OpenPGP
``` ```
@ -95,6 +103,8 @@ The main differences:
After calculating the hash digest from the input data, a signature verification mechanism is employed. This mechanism uses the hash digest, the cryptographic signature from the signature packet, and the public key of the signer. Its purpose is to ascertain the cryptographic validity of the signature. After calculating the hash digest from the input data, a signature verification mechanism is employed. This mechanism uses the hash digest, the cryptographic signature from the signature packet, and the public key of the signer. Its purpose is to ascertain the cryptographic validity of the signature.
```{figure} diag/Signature_Verification.png ```{figure} diag/Signature_Verification.png
:name: fig-signature-verification
:alt: Depicts a complex diagram with white background and the title "Signature verification". On the top left side a box with black frame and white background reads "Input Data packets, One or more packets". Below it the symbol of a signature packet is shown. Both are connected (via green dotted arrows) to a green, right pointing arrow symbol with green dotted frame and the title "Hash mechanism". Text above the green arrow symbol reads "A hash digest is calculated from the input data packates and the signature metadata". The "Hash mechanism" arrow points at a box with white background and green frame, which reads "hash digest". At the top right corner of the diagram the symbol for a component key with only public key and the title "Signer public key" is shown. Hash digest, component key symbol and the cryptographic signature symbol in the signature packet point to a large green arrow symbol, with green dotted frame, at the lower right corner of the diagram, using green dotted arrow lines. The large arrow symbol has the title "Signature verification mechanism" and text overlaid across it reads "A cryptographic signature is verified against the hash digest, using the public key of the signer.". It points at a success and fail symbol at the bottom of the diagram.
Verifying a signature in OpenPGP Verifying a signature in OpenPGP
``` ```

View file

@ -131,7 +131,7 @@ These features are particularly beneficial in scenarios where signed messages ar
The cleartext signature framework includes specific text normalization procedures to ensure the integrity and clarity of the message: 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. - **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. - **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.

View file

@ -91,6 +91,8 @@ A subkey binding signature binds a subkey to a primary key, and it embeds metada
Subkeys designated for signing purposes, identified by the *signing* [key flag](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-key-flags), represent a unique category and are handled differently. See {numref}`bind_subkey_sign`. Subkeys designated for signing purposes, identified by the *signing* [key flag](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-key-flags), represent a unique category and are handled differently. See {numref}`bind_subkey_sign`.
```{figure} diag/subkey_binding_signature.png ```{figure} diag/subkey_binding_signature.png
:name: fig-subkey-binding-signature
:alt: Depicts a diagram on white background with the title "Subkey binding signature". At the top left the symbol of a primary component key with certification capability is shown. At the bottom left the symbol of a component key with encryption capability is shown. The primary component key points at the lower component key with a full green arrow line. In the middle of the connection the small symbol of a signature packet is shown. On the right side of the diagram a detailed version of the signature packet can be found in a box with the title "Subkey binding signature". The text reads "Signature over Primary key, Subkey" and the box with "Signature metadata" contains the list "signature creation time", "key expiration time", "key flags" and "issuer fingerprint". The primary component key points at the detailed signature packet with a dotted green arrow line and the text "Primary key creates a subkey binding signature to bind the subkey to the primary key".
Linking an OpenPGP subkey to the primary key with a binding signature Linking an OpenPGP subkey to the primary key with a binding signature
``` ```
@ -116,6 +118,8 @@ This mutual binding is crucial for security. Without it, an individual (e.g., Al
- the [primary key binding signature](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#sigtype-primary-binding) (type ID `0x19`), created by the subkey itself. This is informally known as an embedded "back signature," because the subkey's signature points back to the 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`), created by the subkey itself. This is informally known as an embedded "back signature," because the subkey's signature points back to the primary key.
```{figure} diag/subkey_binding_signatur_for_signing_sk.png ```{figure} diag/subkey_binding_signatur_for_signing_sk.png
:name: fig-subkey-binding-signature-for-signing-subkeys
:alt: Depicts a diagram on white background with the title "Subkey binding signature for signing subkeys". At the top left the symbol of a primary component key with certification capability is shown. At the bottom left the symbol of a component key with signing capability is shown. The primary component key points at the lower component key with a full green arrow line. In the middle of the connection the small symbol of a signature packet is shown. On the right side of the diagram a detailed version of the signature packet can be found in a box with the title "Subkey binding signature". The text reads "Signature over Primary key, Subkey" and the box with "Signature metadata" in it contains the list "signature creation time", "key expiration time", "key flags" and "issuer fingerprint". Within the signature metadata a box with a green dotted frame extends the list with an inlined signature packet with the title "Embedded Signature; Primary key binding". Its inner text reads "Signature over Primary Key, Signing Subkey". The signature metadata area of this embedded signature holds the list "signature creation time" and "issuer fingerprint". The cryptographic signature symbol overlaps both metadata and general section of the embedded signature. From the signing component key a green dotted arrow line points to the embedded signature in the subkey binding signature with the text "Signing key creates a primary binding signature to associate itself with the primary key" ("primary binding signature" in bold). At the top of the diagram, the primary component key points at the detailed signature packet with a dotted green arrow line and the text "Primary key creates a subkey binding signature to bind the subkey to the primary key".
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
``` ```
@ -134,6 +138,8 @@ There are four types of *certifying self-signature*. The most commonly used type
The certifying self-signature packet calculated over the primary key, User ID, and metadata of the signature packet is then added to the certificate, directly following the User ID packet. The certifying self-signature packet calculated over the primary key, User ID, and metadata of the signature packet is then added to the certificate, directly following the User ID packet.
```{figure} diag/user_id_certification.png ```{figure} diag/user_id_certification.png
:name: fig-user-id-certification
:alt: Depicts a diagram on white background with the title "User ID binding signature". At the top left the symbol of a primary component key with certification capability is shown. At the bottom left the symbol of a User ID reads "Alice Adams <alice@example.org>". The primary component key points at the User ID with a full green arrow line. In the middle of the connection the small symbol of a signature packet is shown. On the right side of the diagram a detailed version of the signature packet can be found in a box with the title "User ID binding signature". The text reads "Signature over Primary key, User ID" and the box with "Signature metadata" in it contains the list "signature creation time", "key expiration time", "primary User ID flag", "algorithm preferences", "key expiration time (primary key)" and "key flags (primary key)". At the top of the diagram, the primary component key points at the detailed signature packet with a dotted green arrow line and the text "Primary key creates a User ID binding signature to associate the User ID with the primary key".
Linking a User ID to an OpenPGP certificate Linking a User ID to an OpenPGP certificate
``` ```
@ -167,6 +173,7 @@ In OpenPGP v6, a direct key signature is the [preferred mechanism](https://www.i
In an OpenPGP 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 certificate's primary key. In an OpenPGP 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 certificate's primary key.
(self-revocations)=
### Revocation self-signatures: Invalidating certificate components ### Revocation self-signatures: Invalidating certificate components
Revocation self-signatures represent an important class of self-signatures, used primarily to invalidate components or retract prior signature statements. Revocation self-signatures represent an important class of self-signatures, used primarily to invalidate components or retract prior signature statements.

View file

@ -0,0 +1,14 @@
<!--
SPDX-FileCopyrightText: 2023 The "Notes on OpenPGP" project
SPDX-License-Identifier: CC-BY-SA-4.0
-->
(versions)=
# Differences between OpenPGP versions
```{admonition} TODO
:class: warning
write about the delta between v4 and v6, most of all
- a starting point? https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-upgrade-guidance-adapting-i
```

View file

@ -48,6 +48,8 @@ alice.pub-9--Signature
```{figure} diag/certificate_packet_list.png ```{figure} diag/certificate_packet_list.png
:name: fig-certificate-packet-list
:alt: Depicts a box with white background and the title "Certificate packet list". Inside, a list of several boxes on white background and varying frame colors represent a list of OpenPGP packets from top to bottom. The first box, with green frame, represents the "Public-Key packet", and includes the green public key symbol. The second box, with yellow frame, represents a "Signature packet" ("Direct Key Signature") and includes the green cryptographic signature symbol. The third box, with black frame, represents a "User ID packet", and includes the black User ID symbol. The fourth box, with yellow frame, represents a "Signature packet" ("Certifying self-signature for User ID"), and includes the green cryptographic signature symbol. The fifth box, with green frame, represents a "Public-Subkey packet" and includes the green public key symbol. The sixth box, with yellow frame, represents a "Signature packet" ("Subkey binding signature") and includes the green cryptographic signature symbol. The seventh box, with green frame, represents a "Public-Subkey packet" and includes the green public key symbol. The eighth box, with yellow frame, represents a "Signature packet" ("Subkey binding signature") and includes the green cryptographic signature symbol. The ninth box, with green frame, represents a "Public-Subkey packet" and includes the green public key symbol. The tenth box, with yellow frame, represents a "Signature packet" ("Subkey binding signature") and includes the green cryptographic signature symbol.
Overview of the packets in Alice's OpenPGP certificate Overview of the packets in Alice's OpenPGP certificate
``` ```
@ -76,6 +78,8 @@ This version of Alice's certificate contains just two packets:
This is the shape of the packets we'll explore in the subsequent sections: This is the shape of the packets we'll explore in the subsequent sections:
```{figure} diag/pubcert-minimal.png ```{figure} diag/pubcert-minimal.png
:name: fig-public-certificate-minimal
:alt: TODO
:width: 40% :width: 40%
A minimal OpenPGP certificate, visualized A minimal OpenPGP certificate, visualized
@ -171,6 +175,8 @@ The packet type ID ("6") defines the semantics of the following data within the
Note that the *Public-Key packet* contains only the public part of the key. Note that the *Public-Key packet* contains only the public part of the key.
```{figure} diag/public-key_packet.png ```{figure} diag/public-key_packet.png
:name: fig-public-key-packet
:alt: Depicts a box with white background and title "Public-Key packet". In the center a box with white background and green frame is shown. Inside it several items are listed, separated by green dotted horizontal lines. The first three are "Version", "Creation Time", "Public-Key Algorithm" written in black. The last one is written in green and reads "Public Key Material" and has the green public key symbol at its right side.
Structure of a Public-Key packet. Structure of a Public-Key packet.
``` ```
@ -361,6 +367,8 @@ The hash digest is calculated from the following data (see [Computing Signatures
The signature is calculated from this hash digest. The signature is calculated from this hash digest.
```{figure} diag/direct_key_signature_packet.png ```{figure} diag/direct_key_signature_packet.png
:name: fig-direct-key-signature-packet
:alt: Depicts a box with white background, title "Signature packet" and subtitle "Direct Key Signature (type ID 0x1F)". In the center a box with white background and yellow frame is shown. Inside it several items are listed, separated by yellow dotted horizontal lines. The first three are "Version", "Public-Key Algorithm" and "Hash Algorithm". The fourth item is called "Hashed area" and confines further sub-items by a light-yellow frame on the top and left side. The sub-items are "Signature Creation Time", "Key Expiration Time", "Preferred Symmetric Ciphers for v1 SEIPD", "Preferred Hash Algorithms", "Key Flags", "Features" and "Issuer Fingerprint". The fifth item is named "Unhashed area" and again introduces an area for sub-items, this time using a light-gray border on the top and left side. The unhashed area has no sub-items though. The last item is called "Cryptographic Signature", with the subtitle "by the primary key over primary key, subkey and signature metadata" and includes the green cryptographic signature symbol on the right side.
Structure of a direct key signature packet. Structure of a direct key signature packet.
``` ```

View file

@ -23,6 +23,8 @@ The output starts with the (primary) [Secret-Key packet](https://www.ietf.org/ar
This is the structure of the Secret-Key packet we will now look at. This is the structure of the Secret-Key packet we will now look at.
```{figure} diag/secret-key_packet.png ```{figure} diag/secret-key_packet.png
:name: fig-secret-key-packet
:alt: Depicts a box with white background and title "Secret-Key packet". In the center a box with white background and red frame is shown. Inside it several items are listed, separated by red dotted horizontal lines. The first three are "Version", "Creation Time", "Public-Key Algorithm" written in black. The fourth one is written in green and reads "Public Key Material" and has the green public key symbol at its right side. The fifth one is again written in black and reads "S2K Usage (Secret Key Encryption)". The sixth item reads "Secret Key Material", written in red and has the red private key symbol at its right side.
Structure of a Secret-Key packet. Structure of a Secret-Key packet.
``` ```
@ -199,4 +201,4 @@ Is the example key wrong?!
``` ```
"Plain or encrypted multiprecision integers comprising the secret key data. This is algorithm-specific and described in Section 5.5.5. If the string-to-key usage octet is 253 (AEAD), then an AEAD authentication tag is at the end of that data." "Plain or encrypted multiprecision integers comprising the secret key data. This is algorithm-specific and described in Section 5.5.5. If the string-to-key usage octet is 253 (AEAD), then an AEAD authentication tag is at the end of that data."

View file

@ -0,0 +1,13 @@
/*
SPDX-FileCopyrightText: 2023 The "Notes on OpenPGP" project
SPDX-License-Identifier: CC0-1.0
*/
div.admonition {
background-color: lightgray;
}
div.warning,
div.admonition-warning {
background-color: palevioletred;
}

View file

@ -24,7 +24,24 @@ source_suffix = ['.md', '.rst']
templates_path = ['_templates'] templates_path = ['_templates']
exclude_patterns = [] exclude_patterns = []
# number code-blocks, figures and tables, if they have a caption
numfig = True
# number figures in flat hierarchy
numfig_secnum_depth = 0
# -- Options for MyST-parser -------------------------------------------------
# https://myst-parser.readthedocs.io/en/latest/configuration.html
# we want to circumvent obscure warnings about footnotes following a heading:
# https://github.com/executablebooks/MyST-Parser/issues/352
myst_footnote_transition = False
# -- Options for EPUB output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-epub-output
epub_css_files = [
'epub/css/custom.css'
]
# -- Options for HTML output ------------------------------------------------- # -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
@ -42,7 +59,3 @@ html_theme_options = {
'show_relbars': 'yes', 'show_relbars': 'yes',
'show_powered_by': False, 'show_powered_by': False,
} }
# we want to circumvent obscure warnings about footnotes following a heading:
# https://github.com/executablebooks/MyST-Parser/issues/352
myst_footnote_transition = False