mirror of
https://codeberg.org/openpgp/notes.git
synced 2025-09-09 11:19:41 +02:00
move "advanced" sections to their own chapters
This commit is contained in:
parent
d628bb7a48
commit
ce992297ab
8 changed files with 346 additions and 330 deletions
|
@ -132,81 +132,3 @@ Specifically, an OpenPGP private keystore implements two primitives:
|
|||
2. Given private key material whose algorithm supports signing, it can calculate a *cryptographic signature* for a hash digest.
|
||||
|
||||
These essential operations require access only to the component keys and their associated private key material, specifically [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.
|
||||
|
||||
## Advanced topics
|
||||
|
||||
(key-store-design)=
|
||||
### Private keystores
|
||||
|
||||
This section examines the diverse architectures and operational mechanics of private keystores in OpenPGP. It focuses on the various design choices, their functional implications, and how they contribute to the secure management of private key material.
|
||||
|
||||
#### Design variations
|
||||
|
||||
The design of private key subsystems within the OpenPGP framework varies, offering different approaches to cryptographic operations:
|
||||
|
||||
1. **Separate backend operations**: Some designs execute the primitive cryptographic operations in a separate backend, using only the cryptographic key material. This approach is particularly compatible with general purpose hardware cryptographic devices, such as [trusted platform modules (TPMs)](https://en.wikipedia.org/wiki/Trusted_Platform_Module).
|
||||
2. **Component key-based systems**: An OpenPGP private key subsystem may be built around component keys, specifically 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 packets contain metadata that is required for some operations. ECDH operations, in particular, require metadata as KDF parameters.
|
||||
3. **Full transferable secret keys**: Some designs maintain copies of full TSKs in the private key subsystem, leveraging these for private key operations.
|
||||
|
||||
While private keystore operations require component keys, they do not require access to the entire OpenPGP certificate.
|
||||
|
||||
```{note}
|
||||
The third design option, involving the storage of full TSKs in the private key subsystem, can cause "split brain" problems.
|
||||
|
||||
For example, a private keystore might contain a TSK with outdated certificate metadata, marking the certificate as expired, while the updated version in the local public keystore could indicate an extended expiration date.
|
||||
|
||||
This problem was notably present in GnuPG 1.x, which held separate TSK copies in its private store component. Similarly, the current design of Thunderbird's OpenPGP subsystem can lead to users experiencing such issues.
|
||||
```
|
||||
|
||||
#### Two-tier architecture
|
||||
|
||||
At its core, an OpenPGP private key subsystem performs operations requiring only the private cryptographic key material, akin to the "separate backend operations" model described above.
|
||||
|
||||
However, the subsystem also supports operations that require additional access to the metadata of the component key. These operations, supplementary to the core keystore operations, do not involve the private key material.
|
||||
|
||||
When implementing a keystore based on hardware cryptographic devices like [OpenPGP card](card-priv), its design will consist of two layers:
|
||||
|
||||
- **core layer**: directly handles private key material, and
|
||||
- **supplementary layer**: performs additional cryptographic operations that don't directly use the private key material, such as [AES key wrap](https://www.rfc-editor.org/rfc/rfc3394.html) for ECDH.
|
||||
|
||||
```{note}
|
||||
The decryption process using ECC algorithms, especially ECDH, has multiple steps. The initial step, potentially performed by devices such as OpenPGP cards, directly uses private key material to produce a "shared secret." Following this, operations like ["AES key unwrap"](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-ec-dh-algorithm-ecdh) are conducted in software outside the hardware device.
|
||||
|
||||
Further details on this process can be found in the "Advanced Encryption Standard (AES) Key Wrap Algorithm" [RFC 3394](https://www.rfc-editor.org/rfc/rfc3394.html).
|
||||
```
|
||||
|
||||
#### Addressing individual keys
|
||||
|
||||
A critical aspect of private keystore design involves determining how users address individual keys.
|
||||
|
||||
One common method is using the fingerprint of each component key. The availability of these fingerprints, however, depends on the underlying technology of the keystore. For instance, in software-based private keystores or OpenPGP cards, fingerprints of component keys are usually readily available. Keystores relying on generic cryptographic hardware, like TPMs, need to implement their own mechanisms for tracking and managing the fingerprints of each key.
|
||||
|
||||
#### Additional keystore duties
|
||||
|
||||
In addition to key management, a keystore often involves various supplementary functions:
|
||||
|
||||
- **Tracking devices**: Keystores may track which devices contain particular component keys.
|
||||
|
||||
- **Handling secrets**: This involves the management of sensitive information such as passphrases for software keys or PINs for OpenPGP cards.
|
||||
|
||||
- **User interaction alerts**: Keystores might also need to prompt users for necessary interactions during certain operations. For example, OpenPGP cards may require user touch confirmation to authorize each cryptographic action.
|
||||
|
||||
### Understanding key overwriting (KO) attacks
|
||||
|
||||
#### What they are
|
||||
|
||||
OpenPGP is subject to specific vulnerabilities known as key overwriting (KO) attacks. These attacks exploit weaknesses in how encrypted private keys or their metadata are handled, potentially leading to the leakage of secret data when the key is used. The core issue lies in OpenPGP's handling of Secret-Key packets, where corruption of the non-encrypted fields can cause the unaltered private key material to be used with altered parameters. This mismatch can result in private key leakage.
|
||||
|
||||
Importantly, KO attacks are particularly relevant when an attacker is responsible for storing a user's encrypted private key. By altering the algorithm field in the Secret-Key packet, the attacker may cause the user to perform a cryptographic operation with a different algorithm. E.g., performing a DSA operation with ECC private key material. By observing the output of that attacker-corrupted operation, the attacker can recover the user's unencrypted private key material, even though the attacker had no direct access to it.
|
||||
|
||||
#### Mitigation
|
||||
|
||||
Understanding KO attacks is crucial due to their potential to compromise the integrity and confidentiality of encrypted communications, and the risk of complete private key material compromise. KO attacks highlight the necessity for robust key validation procedures and the dangers of storing keys in insecure environments. OpenPGP application developers should consider if this attack class is a concern in their applications.
|
||||
|
||||
Private keys that are protected with [S2K usage mode 253 (AEAD)](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-secret-key-encryption), are not vulnerable to KO attacks. This mode ensures the integrity of the private key by using its unencrypted fields (including the algorithm field) as the *authentication tag* for integrity verification in the decryption process. When an attacker alters the unencrypted part of the packet, then decryption of the private key material will fail, and the user is prevented from e.g. accidentally using the key material with an altered attacker-controlled algorithm.
|
||||
|
||||
Note that while S2K usage mode 253 (AEAD) has been introduced in the OpenPGP version 6 specification, it can also be applied to OpenPGP version 4 key material (also see {ref}`migration_s2k`).
|
||||
|
||||
#### Resources
|
||||
|
||||
For comprehensive information on KO attacks, including background, attack vectors, countermeasures, and technical analyses, visit [KOpenPGP.com](https://www.kopenpgp.com/). It is based on the paper "Victory by KO: Attacking OpenPGP Using Key Overwriting" written by Lara Bruseghini, Daniel Huigens, and Kenneth G. Paterson for the Proceedings of ACM Conference on Computer and Communications Security, Los Angeles, November 2022.
|
||||
|
|
|
@ -148,54 +148,3 @@ This mechanism accounts for different {term}`OpenPGP implementations<OpenPGP Imp
|
|||
Consider a scenario where an {term}`implementation<OpenPGP Implementation>` does not recognize a {term}`subpacket<OpenPGP Signature Subpacket>` indicating {term}`signature<OpenPGP Signature Packet>` {term}`expiration`. Without understanding this concept, the {term}`implementation<OpenPGP Implementation>` might erroneously accept an already {term}`expired<Expiration>` {term}`signature<OpenPGP Signature Packet>`. By marking the {term}`signature expiration time subpacket` as {term}`critical<Criticality Flag>`, the creator of the {term}`signature<OpenPGP Signature Packet>` ensures that any recipient who cannot process this {term}`subpacket<OpenPGP Signature Subpacket>` will reject the {term}`signature<OpenPGP Signature Packet>` as {term}`invalid<Validation>`.
|
||||
|
||||
For specific guidelines on which {term}`subpackets<OpenPGP Signature Subpacket>` should be marked as {term}`critical<Criticality Flag>`, refer to the {term}`RFC` sections [5.2.3.11](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-signature-creation-time) to [5.2.3.36](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-intended-recipient-fingerpr).
|
||||
|
||||
## Advanced topics
|
||||
|
||||
(notation_signature_subpackets)=
|
||||
### Notation signature subpackets
|
||||
|
||||
[Notation signature subpackets](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#notation-data) can be used to effectively extend the otherwise limited set of {term}`signature subpacket types<OpenPGP Signature Subpacket Type>` in OpenPGP with user-defined {term}`notations<Notation>`. {term}`Issuers<Issuer>` can use these {term}`notations<Notation>` to add name-value pairs to an {term}`OpenPGP signature<OpenPGP Signature Packet>`.
|
||||
|
||||
{term}`Notation` names - strings encoded in UTF-8 - may reside in the "user namespace." This namespace is characterized by a {term}`notation tag`, followed by a DNS domain name, both in UTF-8 format.
|
||||
|
||||
{term}`Notations<Notation>`, as described earlier, allow for user-defined extensions to the {term}`OpenPGP signature subpacket types<OpenPGP Signature Subpacket Type>`. A practical and popular application of this functionality is seen in Keyoxide, a decentralized {term}`identity verification` service. Keyoxide uses {term}`notations<Notation>` in the `ariadne.id` namespace. For the details of this {term}`implementation<OpenPGP Implementation>`, refer to the [Keyoxide documentation](https://docs.keyoxide.org/wiki/ariadne-identity/).
|
||||
|
||||
### Choosing the hash algorithm for a signature
|
||||
|
||||
A central element of signature packets is the hash digest of the input data. Most OpenPGP software supports a set of different hash mechanisms, of which one is chosen for each signature packet (this is one aspect of OpenPGP's *cryptographic agility*), and used to calculate the hash digest.
|
||||
|
||||
Different hash mechanisms offer different trade-offs:
|
||||
|
||||
- *Hash digest size*: Larger hash size tends to correspond with greater strength against cryptanalysis, and hash digests are relatively small: at the time of this writing, typical sizes are 32 to 64 bytes. However, for some use cases - especially where small messages are sent over a bandwidth-limited transport - larger hash sizes may unacceptably increase message size.
|
||||
- *Computational cost*: Different hash algorithms may have different computational costs. Some OpenPGP users may prefer to limit this cost, for example on constrained computing environments.
|
||||
|
||||
The following sections discuss how the hash algorithm is chosen, based on preferences that are associated with the involved OpenPGP certificates.
|
||||
|
||||
#### Typically: Local determination
|
||||
|
||||
Often, signature creation isn't targeted at a specific receiver. Many signatures are issued for an indeterminate set of "anyone who receives the signature."
|
||||
|
||||
For example, self-signatures that form a certificate are aimed at everyone who interacts with that certificate. Similarly, when creating a data signature for a software package, this signature is aimed at "anyone who will check the signature," often over a long period of time, easily spanning years.
|
||||
|
||||
In such cases, the issuer of that signature chooses the hash algorithm locally, without following preferences of a third party.
|
||||
|
||||
#### With a specific recipient: "Negotiation" based on recipient's preferences
|
||||
|
||||
In contrast, when a message is created for a specific recipient, the sender can - and should - choose the hash algorithm for the signature packet [based on the recipient's hash algorithm preference](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-hash-algorithm-preferences).
|
||||
|
||||
The recipient's hash algorithm preference is defined in metadata of their certificate, see {ref}`algo-pref` for more details.
|
||||
|
||||
In this workflow, the signed hash digest is created with a hash algorithm that follows the recipient's preferences, and its intersection with the sender's capabilities and preferences.
|
||||
|
||||
### Signature versions
|
||||
|
||||
As described in the [RFC](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-signature-packet-type-id-2), the version of a generated signature packet must conform to the version of the key that issues the signature.
|
||||
|
||||
That is:
|
||||
|
||||
- OpenPGP version 6 keys must generate version 6 signature packets
|
||||
- OpenPGP version 4 keys must generate version 4 signature packets
|
||||
|
||||
Note that some historical version 3 signature packets may still be relevant for applications that handle old OpenPGP data[^sig-v3]. These version 3 signature packets will have been generated by version 4 keys.
|
||||
|
||||
[sig-v3]Version 4 signature packets were introduced in [RFC 2440](https://datatracker.ietf.org/doc/html/rfc2440#section-5.2) in 1998, which specifies that applications SHOULD generate v4 signature, however generation of v3 signature packets has remained allowed through [RFC 4880](https://www.rfc-editor.org/rfc/rfc4880.html#section-5.2).
|
|
@ -137,51 +137,3 @@ The {term}`cleartext signature framework` includes specific text normalization p
|
|||
Despite their widespread adoption, {term}`cleartext signatures<Cleartext Signature>` have their limitations and are sometimes viewed as a "legacy method"[^csf-gnupg]. The {term}`RFC` details the [pitfalls of cleartext signatures](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-issues-with-the-cleartext-s), such as incompatibility with semantically meaningful whitespace, challenges with large messages, and security vulnerabilities related to misleading Hash header manipulations. Given these issues, safer alternatives like {term}`inline<Inline Signature>` and {term}`detached signature` forms are advised.
|
||||
|
||||
[^csf-gnupg]: https://lists.gnupg.org/pipermail/gnupg-devel/2023-November/035428.html
|
||||
|
||||
## Advanced topics
|
||||
|
||||
### Nesting of one-pass signatures
|
||||
|
||||
Signing a message using the one-pass mechanism involves prepending a *One-Pass-Signature* (OPS) packet to the message and appending the corresponding signature, sandwiching the signed content.
|
||||
|
||||
An OpenPGP message can contain multiple signatures added that way.
|
||||
|
||||
```{note}
|
||||
One-Pass-Signatures are nested, meaning the outermost One-Pass-Signature packet corresponds to the outermost signature packet.
|
||||
```
|
||||
|
||||
When a message is signed, the signature is always calculated over the contents of the literal data packet, not the literal data packet itself.
|
||||
This means, that if a message, which is compressed using a compressed data packet is wrapped using a one-pass-signature, the signature is still being calculated over the plaintext inside the literal data packet.
|
||||
|
||||
There is one exception though.
|
||||
```{note}
|
||||
Of course there is.
|
||||
```
|
||||
|
||||
The OPS packet has a "nested" flag[^nested-flag], which can either be `1` or `0`.
|
||||
If this flag is set to `0`, it indicates that further OPSs will follow this packet, which are calculated over the same plaintext data as this OPS is. A value of `1` indicates, that either no further OPS packets will follow (this OPS is the last), or that this OPS is calculated over the the usual plaintext data, but wrapped inside any OPS+Signature combinations that follow this OPS.
|
||||
|
||||
[^nested-flag]: See [description of the nested flag](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#section-5.4-3.8.1).
|
||||
|
||||
This mechanism enables attested signatures, where the signer signs an already one-pass-signed message including the already contained signature.
|
||||
|
||||
As a practical example, consider the following notation:
|
||||
* `LIT("Hello World")` represents a literal data packet with the content `Hello World`.
|
||||
* `COMP(XYZ)` represents a compressed data packet over some other packet `XYZ`.
|
||||
* `OPS₁` represents a one-pass-signature packet with the nested flag set to `1`. Analogous, `OPS₀` has the nested flag set to `0`.
|
||||
* `SIG` represents a signature packet.
|
||||
|
||||
A normal, one-pass-signed message looks like this:
|
||||
`OPS₁ LIT("Hello World") SIG`
|
||||
|
||||
Here, the signature is calculated over the plaintext `Hello World`, as is it in a message that has the following form: `OPS₁ COMP(LIT("Hello World")) SIG`.
|
||||
|
||||
A message, where multiple one-pass-signatures are calculated over the same plaintext looks the following:
|
||||
`OPS₀ OPS₀ OPS₁ LIT("Hello World") SIG SIG SIG`
|
||||
|
||||
All three signatures are calculated over the same plaintext `Hello World`.
|
||||
|
||||
Now, a message, where the signer attests an already signed message has the following format:
|
||||
`OPS₁ OPS₁ LIT("Hello World") SIG SIG`
|
||||
|
||||
While the inner signature is calculated over the usual plaintext `Hello World`, the outer signature is instead calculated over `OPS₁ Hello World SIG`.
|
||||
|
|
|
@ -282,156 +282,3 @@ The {term}`OpenPGP RFC<RFC>` doesn't specify exactly how {term}`Web of Trust` ca
|
|||
### Revoking third-party signatures
|
||||
|
||||
To reverse a previously issued {term}`third-party signature`, the {term}`issuer` can generate a [*certification revocation signature*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-certification-revocation-si) ({term}`type ID<Signature Type ID>` `0x30`). The {term}`revocation` must be issued by the same {term}`key<Component Key>` that created the original {term}`signature<OpenPGP Signature Packet>` or, in deprecated practice, by a designated [Revocation Key](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-revocation-key).
|
||||
|
||||
## Advanced topics
|
||||
|
||||
### Certification recipes
|
||||
|
||||
Different {term}`signatures<OpenPGP Signature Packet>` in OpenPGP serve various specific purposes. This section provides practical guidance on creating these {term}`signatures<OpenPGP Signature Packet>`, illustrating each with concrete examples.
|
||||
|
||||
(change_algorithm_preferences)=
|
||||
#### Change algorithm preferences
|
||||
|
||||
To modify the preferred {term}`symmetric<Symmetric Cryptography>`, compression, {term}`hash<Hash Function>`, or {term}`AEAD algorithms<Authenticated Encryption With Associated Data>` for a {term}`key<Transferable Secret Key>`, the {term}`key owner<Certificate Holder>` needs to issue a {term}`direct key signature` ({term}`type ID<Signature Type ID>` `0x1F`) on the {term}`primary key<OpenPGP Primary Key>`.
|
||||
|
||||
This {term}`signature<OpenPGP Signature Packet>` should have the following structure:
|
||||
|
||||
| {term}`Subpacket<OpenPGP Signature Subpacket>` | Area | {term}`Critical<Criticality Flag>` | Mandatory | Notes |
|
||||
|---------------------------------------------------------------------------------------------|-----------------------------|------------------------------------------|----------------------|----------------------------------------------------------------------------------------|
|
||||
| {term}`Signature Creation Time<Signature Creation Time Subpacket>` | {term}`Hashed<Hashed Area>` | True | True | Current time |
|
||||
| {term}`Issuer Fingerprint<Issuer Fingerprint Subpacket>` | {term}`Hashed<Hashed Area>` | True or False | Strongly Recommended | The {term}`primary key` is the {term}`issuer` |
|
||||
| {term}`Key Flags<Key Flag>` | {term}`Hashed<Hashed Area>` | True | False | Retain {term}`key flags<Key Flag>` from the previous {term}`self-signature` |
|
||||
| {term}`Features<Features Subpacket>` | {term}`Hashed<Hashed Area>` | True | False | Retain {term}`features<Features Subpacket>` from the previous {term}`self-signature` |
|
||||
| {term}`Key Expiration Time<Key Expiration Time Subpacket>` | {term}`Hashed<Hashed Area>` | True | False | Retain {term}`expiration time` from the previous {term}`self-signature`, if applicable |
|
||||
| {term}`Hash Algorithm Preferences<Preferred Hash Algorithms Subpacket>` | {term}`Hashed<Hashed Area>` | False | False | New {term}`preferences<Algorithm Preferences>` |
|
||||
| {term}`Compression Algorithm Preferences<Preferred Compression Algorithms Subpacket>` | {term}`Hashed<Hashed Area>` | False | False | New {term}`preferences<Algorithm Preferences>` |
|
||||
| {term}`Symmetric Algorithm Preferences<Preferred Symmetric Ciphers for v1 SEIPD Subpacket>` | {term}`Hashed<Hashed Area>` | False | False | New {term}`preferences<Algorithm Preferences>` |
|
||||
| {term}`AEAD Algorithm Preferences<Preferred AEAD Ciphersuites Subpacket>` | {term}`Hashed<Hashed Area>` | False | False | New {term}`preferences<Algorithm Preferences>` |
|
||||
|
||||
#### Change expiration time
|
||||
|
||||
To adjust the {term}`expiration time` of an {term}`OpenPGP certificate`, a new *{term}`DirectKey<Direct Key Signature>`* {term}`signature<OpenPGP Signature Packet>` ({term}`type ID<Signature Type ID>` `0x1F`) with a modified {term}`Key Expiration Time subpacket` must be issued. The structure of this {term}`signature<OpenPGP Signature Packet>` is identical to the one outlined in the previous section on changing {term}`algorithm preferences`.
|
||||
|
||||
Additionally, the {term}`expiration time` can be altered for individual {term}`User IDs<User ID>` (detailed below) or separate {term}`subkeys<OpenPGP Subkey>` (see {numref}`bind_subkey`).
|
||||
|
||||
#### Add User ID
|
||||
|
||||
To {term}`bind<Binding>` a {term}`User ID` to an {term}`OpenPGP certificate` a {term}`certification signature<Certification>` ({term}`type ID<Signature Type ID>` `0x10`-`0x13`) is used which should have the following structure:
|
||||
|
||||
| {term}`Subpacket<OpenPGP Signature Subpacket>` | Area | {term}`Critical<Criticality Flag>` | Mandatory | Notes |
|
||||
|------------------------------------------------------------------------|-----------------------------|------------------------------------------|----------------------|-------------------------------------------------------------------------------------|
|
||||
| {term}`Signature Creation Time<Signature Creation Time Subpacket>` | {term}`Hashed<Hashed Area>` | True | True | Current time |
|
||||
| {term}`Issuer Fingerprint<Issuer Fingerprint Subpacket>` | {term}`Hashed<Hashed Area>` | True or False | Strongly Recommended | The {term}`primary key<OpenPGP Primary Key>` is the {term}`issuer` |
|
||||
| {term}`Primary User ID<Primary User ID Subpacket>` | {term}`Hashed<Hashed Area>` | True | False | Optional |
|
||||
| {term}`Signature Expiration Time<Signature Expiration Time Subpacket>` | {term}`Hashed<Hashed Area>` | True | False | Optional |
|
||||
|
||||
In addition to these {term}`subpackets<OpenPGP Signature Subpacket>`, {term}`self-certifications<Self-certification>` for {term}`User IDs<User ID>` can include others – such as {term}`key flags<Key Flag>`, {term}`features<Features Subpacket>`, and {term}`algorithm preferences` – as shown in the previous table. This enables the specification of unique capabilities and {term}`preferences<Algorithm Preferences>` for each {term}`identity` associated with the {term}`certificate<OpenPGP Certificate>`.
|
||||
|
||||
#### Remove or revoke a User ID
|
||||
|
||||
Since {term}`OpenPGP certificates<OpenPGP certificate>` are often distributed by the means of {term}`key servers<Key Server>`, new {term}`signatures<OpenPGP Signature Packet>` on a {term}`certificate<OpenPGP Certificate>` are often "merged" into existing copies of the {term}`certificate<OpenPGP Certificate>` locally by the recipient.
|
||||
|
||||
```{admonition} TODO
|
||||
:class: warning
|
||||
|
||||
Link to the "Merging" section in chapter 4, once merged.
|
||||
```
|
||||
|
||||
This integration process means it is practically impossible to directly remove {term}`signatures<OpenPGP Signature Packet>` or {term}`User IDs<User ID>` from a {term}`certificate<OpenPGP Certificate>`, as there is no way to communicate the intention of {term}`packet<OpenPGP Signature Packet>` deletion to the recipient.
|
||||
|
||||
To effectively mark a {term}`User ID` as invalid, the user can publish a copy of their {term}`certificate<OpenPGP Certificate>` with a {term}`Certification Revocation signature<Certification Revocation Signature Packet>` ({term}`type ID<Signature Type ID>` `0x30`) attached to the invalidated {term}`User ID`. This {term}`signature<OpenPGP Signature Packet>` signals that the specified {term}`User ID` is no longer valid or associated with the {term}`certificate holder`.
|
||||
|
||||
The structure of a {term}`Certification Revocation signature<Certification Revocation Signature Packet>` is as follows:
|
||||
|
||||
| {term}`Subpacket<OpenPGP Signature Subpacket>` | Area | {term}`Critical<Criticality Flag>` | Mandatory | Notes |
|
||||
|--------------------------------------------------------------------|-----------------------------|------------------------------------------|----------------------|-------------------------------------------------------------------------------------|
|
||||
| {term}`Signature Creation Time<Signature Creation Time Subpacket>` | {term}`Hashed<Hashed Area>` | True | True | Current time |
|
||||
| {term}`Issuer Fingerprint<Issuer Fingerprint Subpacket>` | {term}`Hashed<Hashed Area>` | True or False | Strongly Recommended | The {term}`primary key<OpenPGP Primary Key>` is the {term}`issuer` |
|
||||
| {term}`Reason for Revocation<Reason for Revocation Subpacket>` | {term}`Hashed<Hashed Area>` | True | False | Determines {term}`soft<Soft Revocation>` or {term}`hard revocation` |
|
||||
|
||||
For {term}`User ID` {term}`revocations<Revocation>`, the *{term}`Reason for Revocation<Reason for Revocation Subpacket>`* {term}`subpacket<OpenPGP Signature Subpacket>` is crucial. A value of `0` means no specific reason, leading to a {term}`hard revocation`, while `32` indicates the {term}`User ID` is no longer valid, resulting in a {term}`soft revocation`. Omitting the {term}`reason subpacket<Reason For Revocation Subpacket>` is also equivalent to a {term}`hard revocation`.
|
||||
|
||||
It is generally advisable to use reason code `32` for revoking {term}`User IDs<User ID>`.
|
||||
|
||||
(binding_subkeys)=
|
||||
#### Add a subkey
|
||||
|
||||
As part of {term}`life-cycle management`, users may need to add a new {term}`subkey<OpenPGP Subkey>` to their {term}`OpenPGP certificate`, often for reasons such as upgrading to a {term}`subkey<OpenPGP Subkey>` with more advanced cryptographic algorithms. The process involves creating a specific {term}`signature<OpenPGP Signature Packet>` structure:
|
||||
|
||||
| {term}`Subpacket<OpenPGP Signature Subpacket>` | Area | {term}`Critical<Criticality Flag>` | Mandatory | Notes |
|
||||
|---------------------------------------------------------------------------------------------|-----------------------------|------------------------------------------|-------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| {term}`Signature Creation Time<Signature Creation Time Subpacket>` | {term}`Hashed<Hashed Area>` | True | True | Current time |
|
||||
| {term}`Issuer Fingerprint<Issuer Fingerprint Subpacket>` | {term}`Hashed<Hashed Area>` | True or False | Strongly Recommended | The {term}`primary key<OpenPGP Primary Key>` is the {term}`issuer` |
|
||||
| {term}`Key Flags<Key Flag>` | {term}`Hashed<Hashed Area>` | True | Strongly Recommended | Determine the usage of the {term}`key<OpenPGP Subkey>` |
|
||||
| {term}`Key Expiration Time<Key Expiration Time Subpacket>` | {term}`Hashed<Hashed Area>` | True | False | Specifies the {term}`expiration time` of the {term}`subkey<OpenPGP Subkey>` |
|
||||
| {term}`Embedded Signature<Embedded Signature Subpacket>` | {term}`Hashed<Hashed Area>` | True | If {term}`Key Flags<Key Flag>` contains **{term}`S<Signing Key Flag>`** | {term}`Signing subkeys<OpenPGP Signing Subkey>` require embedded *{term}`Primary Key Binding<Primary Key Binding Signature>`* {term}`signature<OpenPGP Signature Packet>` |
|
||||
| {term}`Hash Algorithm Preferences<Preferred Hash Algorithms Subpacket>` | {term}`Hashed<Hashed Area>` | False | False | Per {term}`key<Component Key>` {term}`preferences<Algorithm Preferences>` |
|
||||
| {term}`Compression Algorithm Preferences<Preferred Compression Algorithms Subpacket>` | {term}`Hashed<Hashed Area>` | False | False | Per {term}`key<Component Key>` {term}`preferences<Algorithm Preferences>` |
|
||||
| {term}`Symmetric Algorithm Preferences<Preferred Symmetric Ciphers for v1 SEIPD Subpacket>` | {term}`Hashed<Hashed Area>` | False | False | Per {term}`key<Component Key>` {term}`preferences<Algorithm Preferences>` |
|
||||
| {term}`AEAD Algorithm Preferences<Preferred AEAD Ciphersuites Subpacket>` | {term}`Hashed<Hashed Area>` | False | False | Per {term}`key<Component Key>` {term}`preferences<Algorithm Preferences>` |
|
||||
|
||||
In addition to these {term}`subpackets<OpenPGP Signature Subpacket>`, users can specify {term}`algorithm preferences` for each {term}`subkey<OpenPGP Subkey>`, distinct from those set in the {term}`certificate<OpenPGP Certificate>`'s *{term}`Direct Key<Direct Key Signature>`* {term}`signature<OpenPGP Signature Packet>`.
|
||||
|
||||
#### Revoke a subkey
|
||||
|
||||
{term}`Subkeys<OpenPGP subkey>`, like {term}`User IDs<User ID>`, can be individually revoked in OpenPGP.
|
||||
This is done by issuing a {term}`Subkey Revocation signature<Subkey Revocation Signature Packet>` ({term}`type ID<Signature Type ID>` `0x28`) using the {term}`primary key<OpenPGP Primary Key>`.
|
||||
|
||||
The structure of such a {term}`signature<OpenPGP Signature Packet>` is straightforward:
|
||||
|
||||
| {term}`Subpacket<OpenPGP Signature Subpacket>` | Area | {term}`Critical<Criticality Flag>` | Mandatory | Notes |
|
||||
|--------------------------------------------------------------------|-----------------------------|------------------------------------------|----------------------|-------------------------------------------------------------------------------------|
|
||||
| {term}`Signature Creation Time<Signature Creation Time Subpacket>` | {term}`Hashed<Hashed Area>` | True | True | Current time |
|
||||
| {term}`Issuer Fingerprint<Issuer Fingerprint Subpacket>` | {term}`Hashed<Hashed Area>` | True or False | Strongly Recommended | The {term}`primary key<OpenPGP Primary Key>` is the {term}`issuer` |
|
||||
| {term}`Reason for Revocation<Reason For Revocation Subpacket>` | {term}`Hashed<Hashed Area>` | True | False | Determines {term}`soft<Soft Revocation>` or {term}`hard revocation` |
|
||||
|
||||
|
||||
In {term}`Subkey Revocation signatures<Subkey Revocation Signature Packet>`, the [reason for revocation](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-reason-for-revocation) {term}`subpacket<OpenPGP Signature Subpacket>` can only have values in the range of `0-3`. The values `1` ({term}`key<OpenPGP Subkey>` superseded) and `3` ({term}`key<OpenPGP Subkey>` retired and no longer used) indicate {term}`soft revocations<Soft Revocation>`, whereas values `0` (no reason) and `2` ({term}`key<OpenPGP Subkey>` compromised) indicate {term}`hard revocations<Hard Revocation>`.
|
||||
|
||||
Note that a value of `32` is not applicable in these {term}`signatures<OpenPGP Signature Packet>`.
|
||||
|
||||
```{admonition} TODO
|
||||
:class: warning
|
||||
|
||||
Research and explain hardness in the context of subkey revocations. What does a hard subkey revocation express concretely?
|
||||
```
|
||||
|
||||
#### Revoke a certificate
|
||||
|
||||
Users may find themselves needing to revoke their entire {term}`OpenPGP certificate`, rendering it unusable. This could be for various reasons, such as migrating to a new {term}`certificate<OpenPGP certificate>` or in response to a compromise of the {term}`certificate<OpenPGP certificate>`'s {term}`secret key material<Private Key Material>`.
|
||||
|
||||
While a {term}`soft-revoked<Soft Revocation>` {term}`certificate<OpenPGP Certificate>` can be re-validated at a later time with a new {term}`certification`, a {term}`hard revocation` is permanent.
|
||||
|
||||
The recommended way to {term}`revoke<Revocation>` a {term}`certificate<OpenPGP Certificate>` is by issuing a {term}`Key Revocation signature<Key Revocation Signature Packet>` ({term}`type ID<Signature Type ID>` `0x20`). Its structure is similar to that of a {term}`Certification Revocation signature<Certification Revocation Signature Packet>`.
|
||||
|
||||
| {term}`Subpacket<OpenPGP Signature Subpacket>` | Area | {term}`Critical<Criticality Flag>` | Mandatory | Notes |
|
||||
|--------------------------------------------------------------------|-----------------------------|------------------------------------------|----------------------|-------------------------------------------------------------------------------------|
|
||||
| {term}`Signature Creation Time<Signature Creation Time Subpacket>` | {term}`Hashed<Hashed Area>` | True | True | Current time |
|
||||
| {term}`Issuer Fingerprint<Issuer Fingerprint Subpacket>` | {term}`Hashed<Hashed Area>` | True or False | Strongly Recommended | The {term}`primary key<OpenPGP Primary Key>` is the {term}`issuer` |
|
||||
| {term}`Reason for Revocation<Reason For Revocation Subpacket>` | {term}`Hashed<Hashed Area>` | True | False | Determines {term}`soft<Soft Revocation>` or {term}`hard revocation` |
|
||||
|
||||
For {term}`Key Revocation signatures<Key Revocation Signature Packet>`, the guidelines regarding the [*Reason for Revocation* subpacket](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-reason-for-revocation) are the same as those for {term}`Subkey Revocation signatures<Subkey Revocation Signature Packet>`.
|
||||
|
||||
#### Common subpackets in OpenPGP signatures
|
||||
|
||||
In OpenPGP, certain {term}`subpackets<OpenPGP Signature Subpacket>` are universally expected across all types of {term}`signatures<OpenPGP Signature Packet>`, serving fundamental roles in the {term}`signature<OpenPGP Signature Packet>`'s structure, {term}`verification` and {term}`validation`:
|
||||
|
||||
* **{term}`Signature Creation Time<Signature Creation Time Subpacket>`**: This is a mandatory {term}`subpacket<OpenPGP Signature Subpacket>` in every {term}`OpenPGP signature<OpenPGP Signature Packet>`. It contains the timestamp of when the {term}`signature<OpenPGP Signature Packet>` was created. For security and integrity, this {term}`subpacket<OpenPGP Signature Subpacket>` must be located in the {term}`hashed area` of the {term}`signature<OpenPGP Signature Packet>` and is recommended to be marked as {term}`critical<Criticality Flag>`.
|
||||
|
||||
* **{term}`Issuer Fingerprint<Issuer Fingerprint Subpacket>`**: Essential for {term}`signature<OpenPGP Signature Packet>` {term}`validation`, this {term}`subpacket<OpenPGP Signature Subpacket>` identifies the {term}`key<OpenPGP Primary Key>` (or {term}`subkey<OpenPGP Subkey>`) that was used to create the {term}`signature<OpenPGP Signature Packet>`. OpenPGP v6 {term}`signatures<OpenPGP Signature Packet>` should include the {term}`Issuer Fingerprint subpacket`, containing the 32-byte {term}`fingerprint<OpenPGP Fingerprint>` of the {term}`key<Component Key>`.
|
||||
|
||||
```{note}
|
||||
The {term}`key<Component Key>` used as the {term}`issuer` in the {term}`signature<OpenPGP Signature Packet>` might be a {term}`subkey<OpenPGP Subkey>` of the {term}`certificate<OpenPGP Certificate>`.
|
||||
```
|
||||
|
||||
These {term}`subpackets<OpenPGP Signature Subpacket>` can be placed in either the {term}`hashed<Hashed Area>` or {term}`unhashed area` due to its self-{term}`authenticating<Authentication>` nature. However, we recommend including them in the {term}`signature<OpenPGP Signature Packet>`'s {term}`hashed area`.
|
||||
|
||||
### Managing subpacket conflicts and duplication
|
||||
|
||||
In {term}`OpenPGP signatures<OpenPGP Signature Packet>`, both the {term}`hashed<Hashed Area>` and {term}`unhashed areas<Unhashed Area>` are composed of lists of {term}`subpackets<OpenPGP Signature Subpacket>`. Inherently, this structure permits the duplication of the same {term}`subpacket<OpenPGP Signature Subpacket>`, which could lead to conflicts. To manage these potential conflicts, the following strategies are used:
|
||||
|
||||
- **Precedence of {term}`hashed area`**: {term}`Subpackets<OpenPGP Signature Subpacket>` within the {term}`hashed area` of a {term}`signature<OpenPGP Signature Packet>` take precedence over those in the {term}`unhashed area`. This hierarchy helps resolve conflicts when the same {term}`subpacket<OpenPGP Signature Subpacket>` appears in both areas.
|
||||
|
||||
- **Handling conflicts within the same area**: Conflicts can still arise within the same area, such as when two {term}`subpackets<OpenPGP Signature Subpacket>` have different {term}`expiration times<Expiration Time>`. In such cases, the [OpenPGP specification](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-notes-on-subpackets) advises that {term}`implementations<OpenPGP Implementation>` should favor the last occurrence of a conflicting {term}`subpacket<OpenPGP Signature Subpacket>` in the {term}`hashed area`.
|
||||
|
||||
In certain scenarios, having duplicate {term}`subpackets<OpenPGP Signature Subpacket>` with conflicting content is logical and even necessary. For example, consider a {term}`signature<OpenPGP Signature Packet>` created by a version 4 {term}`issuer` {term}`key<Component Key>`, which was upgraded from an older OpenPGP version (like v3). Since the {term}`key ID` calculation scheme changed from v3 to v4, the identifiers for the same {term}`key<Component Key>` would differ between these versions. Therefore, a v4 signature might contain two {term}`issuer key ID subpackets<Issuer Fingerprint Subpacket>`, each with different, yet correct values for v3 and v4 {term}`keys<Component Key>`, respectively. This allows for backward compatibility and ensures the {term}`signature<OpenPGP Signature Packet>` can be {term}`validated<Validation>` under both {term}`key ID` calculation schemes.
|
||||
|
|
82
book/source/17b-adv-private.md
Normal file
82
book/source/17b-adv-private.md
Normal file
|
@ -0,0 +1,82 @@
|
|||
<!--
|
||||
SPDX-FileCopyrightText: 2023 The "Notes on OpenPGP" project
|
||||
SPDX-License-Identifier: CC-BY-SA-4.0
|
||||
-->
|
||||
|
||||
# Advanced material: Private key material in OpenPGP
|
||||
|
||||
(key-store-design)=
|
||||
## Private keystores
|
||||
|
||||
This section examines the diverse architectures and operational mechanics of private keystores in OpenPGP. It focuses on the various design choices, their functional implications, and how they contribute to the secure management of private key material.
|
||||
|
||||
### Design variations
|
||||
|
||||
The design of private key subsystems within the OpenPGP framework varies, offering different approaches to cryptographic operations:
|
||||
|
||||
1. **Separate backend operations**: Some designs execute the primitive cryptographic operations in a separate backend, using only the cryptographic key material. This approach is particularly compatible with general purpose hardware cryptographic devices, such as [trusted platform modules (TPMs)](https://en.wikipedia.org/wiki/Trusted_Platform_Module).
|
||||
2. **Component key-based systems**: An OpenPGP private key subsystem may be built around component keys, specifically 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 packets contain metadata that is required for some operations. ECDH operations, in particular, require metadata as KDF parameters.
|
||||
3. **Full transferable secret keys**: Some designs maintain copies of full TSKs in the private key subsystem, leveraging these for private key operations.
|
||||
|
||||
While private keystore operations require component keys, they do not require access to the entire OpenPGP certificate.
|
||||
|
||||
```{note}
|
||||
The third design option, involving the storage of full TSKs in the private key subsystem, can cause "split brain" problems.
|
||||
|
||||
For example, a private keystore might contain a TSK with outdated certificate metadata, marking the certificate as expired, while the updated version in the local public keystore could indicate an extended expiration date.
|
||||
|
||||
This problem was notably present in GnuPG 1.x, which held separate TSK copies in its private store component. Similarly, the current design of Thunderbird's OpenPGP subsystem can lead to users experiencing such issues.
|
||||
```
|
||||
|
||||
### Two-tier architecture
|
||||
|
||||
At its core, an OpenPGP private key subsystem performs operations requiring only the private cryptographic key material, akin to the "separate backend operations" model described above.
|
||||
|
||||
However, the subsystem also supports operations that require additional access to the metadata of the component key. These operations, supplementary to the core keystore operations, do not involve the private key material.
|
||||
|
||||
When implementing a keystore based on hardware cryptographic devices like [OpenPGP card](card-priv), its design will consist of two layers:
|
||||
|
||||
- **core layer**: directly handles private key material, and
|
||||
- **supplementary layer**: performs additional cryptographic operations that don't directly use the private key material, such as [AES key wrap](https://www.rfc-editor.org/rfc/rfc3394.html) for ECDH.
|
||||
|
||||
```{note}
|
||||
The decryption process using ECC algorithms, especially ECDH, has multiple steps. The initial step, potentially performed by devices such as OpenPGP cards, directly uses private key material to produce a "shared secret." Following this, operations like ["AES key unwrap"](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-ec-dh-algorithm-ecdh) are conducted in software outside the hardware device.
|
||||
|
||||
Further details on this process can be found in the "Advanced Encryption Standard (AES) Key Wrap Algorithm" [RFC 3394](https://www.rfc-editor.org/rfc/rfc3394.html).
|
||||
```
|
||||
|
||||
### Addressing individual keys
|
||||
|
||||
A critical aspect of private keystore design involves determining how users address individual keys.
|
||||
|
||||
One common method is using the fingerprint of each component key. The availability of these fingerprints, however, depends on the underlying technology of the keystore. For instance, in software-based private keystores or OpenPGP cards, fingerprints of component keys are usually readily available. Keystores relying on generic cryptographic hardware, like TPMs, need to implement their own mechanisms for tracking and managing the fingerprints of each key.
|
||||
|
||||
### Additional keystore duties
|
||||
|
||||
In addition to key management, a keystore often involves various supplementary functions:
|
||||
|
||||
- **Tracking devices**: Keystores may track which devices contain particular component keys.
|
||||
|
||||
- **Handling secrets**: This involves the management of sensitive information such as passphrases for software keys or PINs for OpenPGP cards.
|
||||
|
||||
- **User interaction alerts**: Keystores might also need to prompt users for necessary interactions during certain operations. For example, OpenPGP cards may require user touch confirmation to authorize each cryptographic action.
|
||||
|
||||
## Understanding key overwriting (KO) attacks
|
||||
|
||||
### What they are
|
||||
|
||||
OpenPGP is subject to specific vulnerabilities known as key overwriting (KO) attacks. These attacks exploit weaknesses in how encrypted private keys or their metadata are handled, potentially leading to the leakage of secret data when the key is used. The core issue lies in OpenPGP's handling of Secret-Key packets, where corruption of the non-encrypted fields can cause the unaltered private key material to be used with altered parameters. This mismatch can result in private key leakage.
|
||||
|
||||
Importantly, KO attacks are particularly relevant when an attacker is responsible for storing a user's encrypted private key. By altering the algorithm field in the Secret-Key packet, the attacker may cause the user to perform a cryptographic operation with a different algorithm. E.g., performing a DSA operation with ECC private key material. By observing the output of that attacker-corrupted operation, the attacker can recover the user's unencrypted private key material, even though the attacker had no direct access to it.
|
||||
|
||||
### Mitigation
|
||||
|
||||
Understanding KO attacks is crucial due to their potential to compromise the integrity and confidentiality of encrypted communications, and the risk of complete private key material compromise. KO attacks highlight the necessity for robust key validation procedures and the dangers of storing keys in insecure environments. OpenPGP application developers should consider if this attack class is a concern in their applications.
|
||||
|
||||
Private keys that are protected with [S2K usage mode 253 (AEAD)](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-secret-key-encryption), are not vulnerable to KO attacks. This mode ensures the integrity of the private key by using its unencrypted fields (including the algorithm field) as the *authentication tag* for integrity verification in the decryption process. When an attacker alters the unencrypted part of the packet, then decryption of the private key material will fail, and the user is prevented from e.g. accidentally using the key material with an altered attacker-controlled algorithm.
|
||||
|
||||
Note that while S2K usage mode 253 (AEAD) has been introduced in the OpenPGP version 6 specification, it can also be applied to OpenPGP version 4 key material (also see {ref}`migration_s2k`).
|
||||
|
||||
#### Resources
|
||||
|
||||
For comprehensive information on KO attacks, including background, attack vectors, countermeasures, and technical analyses, visit [KOpenPGP.com](https://www.kopenpgp.com/). It is based on the paper "Victory by KO: Attacking OpenPGP Using Key Overwriting" written by Lara Bruseghini, Daniel Huigens, and Kenneth G. Paterson for the Proceedings of ACM Conference on Computer and Communications Security, Los Angeles, November 2022.
|
55
book/source/17c-adv-signatures.md
Normal file
55
book/source/17c-adv-signatures.md
Normal file
|
@ -0,0 +1,55 @@
|
|||
<!--
|
||||
SPDX-FileCopyrightText: 2023 The "Notes on OpenPGP" project
|
||||
SPDX-License-Identifier: CC-BY-SA-4.0
|
||||
-->
|
||||
|
||||
# Advanced material: OpenPGP Signatures
|
||||
|
||||
(notation_signature_subpackets)=
|
||||
## Notation signature subpackets
|
||||
|
||||
[Notation signature subpackets](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#notation-data) can be used to effectively extend the otherwise limited set of {term}`signature subpacket types<OpenPGP Signature Subpacket Type>` in OpenPGP with user-defined {term}`notations<Notation>`. {term}`Issuers<Issuer>` can use these {term}`notations<Notation>` to add name-value pairs to an {term}`OpenPGP signature<OpenPGP Signature Packet>`.
|
||||
|
||||
{term}`Notation` names - strings encoded in UTF-8 - may reside in the "user namespace." This namespace is characterized by a {term}`notation tag`, followed by a DNS domain name, both in UTF-8 format.
|
||||
|
||||
{term}`Notations<Notation>`, as described earlier, allow for user-defined extensions to the {term}`OpenPGP signature subpacket types<OpenPGP Signature Subpacket Type>`. A practical and popular application of this functionality is seen in Keyoxide, a decentralized {term}`identity verification` service. Keyoxide uses {term}`notations<Notation>` in the `ariadne.id` namespace. For the details of this {term}`implementation<OpenPGP Implementation>`, refer to the [Keyoxide documentation](https://docs.keyoxide.org/wiki/ariadne-identity/).
|
||||
|
||||
## Choosing the hash algorithm for a signature
|
||||
|
||||
A central element of signature packets is the hash digest of the input data. Most OpenPGP software supports a set of different hash mechanisms, of which one is chosen for each signature packet (this is one aspect of OpenPGP's *cryptographic agility*), and used to calculate the hash digest.
|
||||
|
||||
Different hash mechanisms offer different trade-offs:
|
||||
|
||||
- *Hash digest size*: Larger hash size tends to correspond with greater strength against cryptanalysis, and hash digests are relatively small: at the time of this writing, typical sizes are 32 to 64 bytes. However, for some use cases - especially where small messages are sent over a bandwidth-limited transport - larger hash sizes may unacceptably increase message size.
|
||||
- *Computational cost*: Different hash algorithms may have different computational costs. Some OpenPGP users may prefer to limit this cost, for example on constrained computing environments.
|
||||
|
||||
The following sections discuss how the hash algorithm is chosen, based on preferences that are associated with the involved OpenPGP certificates.
|
||||
|
||||
### Typically: Local determination
|
||||
|
||||
Often, signature creation isn't targeted at a specific receiver. Many signatures are issued for an indeterminate set of "anyone who receives the signature."
|
||||
|
||||
For example, self-signatures that form a certificate are aimed at everyone who interacts with that certificate. Similarly, when creating a data signature for a software package, this signature is aimed at "anyone who will check the signature," often over a long period of time, easily spanning years.
|
||||
|
||||
In such cases, the issuer of that signature chooses the hash algorithm locally, without following preferences of a third party.
|
||||
|
||||
### With a specific recipient: "Negotiation" based on recipient's preferences
|
||||
|
||||
In contrast, when a message is created for a specific recipient, the sender can - and should - choose the hash algorithm for the signature packet [based on the recipient's hash algorithm preference](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-hash-algorithm-preferences).
|
||||
|
||||
The recipient's hash algorithm preference is defined in metadata of their certificate, see {ref}`algo-pref` for more details.
|
||||
|
||||
In this workflow, the signed hash digest is created with a hash algorithm that follows the recipient's preferences, and its intersection with the sender's capabilities and preferences.
|
||||
|
||||
## Signature versions
|
||||
|
||||
As described in the [RFC](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-signature-packet-type-id-2), the version of a generated signature packet must conform to the version of the key that issues the signature.
|
||||
|
||||
That is:
|
||||
|
||||
- OpenPGP version 6 keys must generate version 6 signature packets
|
||||
- OpenPGP version 4 keys must generate version 4 signature packets
|
||||
|
||||
Note that some historical version 3 signature packets may still be relevant for applications that handle old OpenPGP data[^sig-v3]. These version 3 signature packets will have been generated by version 4 keys.
|
||||
|
||||
[sig-v3]Version 4 signature packets were introduced in [RFC 2440](https://datatracker.ietf.org/doc/html/rfc2440#section-5.2) in 1998, which specifies that applications SHOULD generate v4 signature, however generation of v3 signature packets has remained allowed through [RFC 4880](https://www.rfc-editor.org/rfc/rfc4880.html#section-5.2).
|
52
book/source/17d-adv-sign-data.md
Normal file
52
book/source/17d-adv-sign-data.md
Normal file
|
@ -0,0 +1,52 @@
|
|||
<!--
|
||||
SPDX-FileCopyrightText: 2023 The "Notes on OpenPGP" project
|
||||
SPDX-License-Identifier: CC-BY-SA-4.0
|
||||
-->
|
||||
|
||||
# Advanced material: Signatures over data
|
||||
|
||||
## Nesting of one-pass signatures
|
||||
|
||||
Signing a message using the one-pass mechanism involves prepending a *One-Pass-Signature* (OPS) packet to the message and appending the corresponding signature, sandwiching the signed content.
|
||||
|
||||
An OpenPGP message can contain multiple signatures added that way.
|
||||
|
||||
```{note}
|
||||
One-Pass-Signatures are nested, meaning the outermost One-Pass-Signature packet corresponds to the outermost signature packet.
|
||||
```
|
||||
|
||||
When a message is signed, the signature is always calculated over the contents of the literal data packet, not the literal data packet itself.
|
||||
This means, that if a message, which is compressed using a compressed data packet is wrapped using a one-pass-signature, the signature is still being calculated over the plaintext inside the literal data packet.
|
||||
|
||||
There is one exception though.
|
||||
```{note}
|
||||
Of course there is.
|
||||
```
|
||||
|
||||
The OPS packet has a "nested" flag[^nested-flag], which can either be `1` or `0`.
|
||||
If this flag is set to `0`, it indicates that further OPSs will follow this packet, which are calculated over the same plaintext data as this OPS is. A value of `1` indicates, that either no further OPS packets will follow (this OPS is the last), or that this OPS is calculated over the the usual plaintext data, but wrapped inside any OPS+Signature combinations that follow this OPS.
|
||||
|
||||
[^nested-flag]: See [description of the nested flag](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#section-5.4-3.8.1).
|
||||
|
||||
This mechanism enables attested signatures, where the signer signs an already one-pass-signed message including the already contained signature.
|
||||
|
||||
As a practical example, consider the following notation:
|
||||
* `LIT("Hello World")` represents a literal data packet with the content `Hello World`.
|
||||
* `COMP(XYZ)` represents a compressed data packet over some other packet `XYZ`.
|
||||
* `OPS₁` represents a one-pass-signature packet with the nested flag set to `1`. Analogous, `OPS₀` has the nested flag set to `0`.
|
||||
* `SIG` represents a signature packet.
|
||||
|
||||
A normal, one-pass-signed message looks like this:
|
||||
`OPS₁ LIT("Hello World") SIG`
|
||||
|
||||
Here, the signature is calculated over the plaintext `Hello World`, as is it in a message that has the following form: `OPS₁ COMP(LIT("Hello World")) SIG`.
|
||||
|
||||
A message, where multiple one-pass-signatures are calculated over the same plaintext looks the following:
|
||||
`OPS₀ OPS₀ OPS₁ LIT("Hello World") SIG SIG SIG`
|
||||
|
||||
All three signatures are calculated over the same plaintext `Hello World`.
|
||||
|
||||
Now, a message, where the signer attests an already signed message has the following format:
|
||||
`OPS₁ OPS₁ LIT("Hello World") SIG SIG`
|
||||
|
||||
While the inner signature is calculated over the usual plaintext `Hello World`, the outer signature is instead calculated over `OPS₁ Hello World SIG`.
|
157
book/source/17e-adv-sig-component.md
Normal file
157
book/source/17e-adv-sig-component.md
Normal file
|
@ -0,0 +1,157 @@
|
|||
<!--
|
||||
SPDX-FileCopyrightText: 2023 The "Notes on OpenPGP" project
|
||||
SPDX-License-Identifier: CC-BY-SA-4.0
|
||||
-->
|
||||
|
||||
# Advanced material: Signatures on components
|
||||
|
||||
## Certification recipes
|
||||
|
||||
Different {term}`signatures<OpenPGP Signature Packet>` in OpenPGP serve various specific purposes. This section provides practical guidance on creating these {term}`signatures<OpenPGP Signature Packet>`, illustrating each with concrete examples.
|
||||
|
||||
(change_algorithm_preferences)=
|
||||
### Change algorithm preferences
|
||||
|
||||
To modify the preferred {term}`symmetric<Symmetric Cryptography>`, compression, {term}`hash<Hash Function>`, or {term}`AEAD algorithms<Authenticated Encryption With Associated Data>` for a {term}`key<Transferable Secret Key>`, the {term}`key owner<Certificate Holder>` needs to issue a {term}`direct key signature` ({term}`type ID<Signature Type ID>` `0x1F`) on the {term}`primary key<OpenPGP Primary Key>`.
|
||||
|
||||
This {term}`signature<OpenPGP Signature Packet>` should have the following structure:
|
||||
|
||||
| {term}`Subpacket<OpenPGP Signature Subpacket>` | Area | {term}`Critical<Criticality Flag>` | Mandatory | Notes |
|
||||
|---------------------------------------------------------------------------------------------|-----------------------------|------------------------------------------|----------------------|----------------------------------------------------------------------------------------|
|
||||
| {term}`Signature Creation Time<Signature Creation Time Subpacket>` | {term}`Hashed<Hashed Area>` | True | True | Current time |
|
||||
| {term}`Issuer Fingerprint<Issuer Fingerprint Subpacket>` | {term}`Hashed<Hashed Area>` | True or False | Strongly Recommended | The {term}`primary key` is the {term}`issuer` |
|
||||
| {term}`Key Flags<Key Flag>` | {term}`Hashed<Hashed Area>` | True | False | Retain {term}`key flags<Key Flag>` from the previous {term}`self-signature` |
|
||||
| {term}`Features<Features Subpacket>` | {term}`Hashed<Hashed Area>` | True | False | Retain {term}`features<Features Subpacket>` from the previous {term}`self-signature` |
|
||||
| {term}`Key Expiration Time<Key Expiration Time Subpacket>` | {term}`Hashed<Hashed Area>` | True | False | Retain {term}`expiration time` from the previous {term}`self-signature`, if applicable |
|
||||
| {term}`Hash Algorithm Preferences<Preferred Hash Algorithms Subpacket>` | {term}`Hashed<Hashed Area>` | False | False | New {term}`preferences<Algorithm Preferences>` |
|
||||
| {term}`Compression Algorithm Preferences<Preferred Compression Algorithms Subpacket>` | {term}`Hashed<Hashed Area>` | False | False | New {term}`preferences<Algorithm Preferences>` |
|
||||
| {term}`Symmetric Algorithm Preferences<Preferred Symmetric Ciphers for v1 SEIPD Subpacket>` | {term}`Hashed<Hashed Area>` | False | False | New {term}`preferences<Algorithm Preferences>` |
|
||||
| {term}`AEAD Algorithm Preferences<Preferred AEAD Ciphersuites Subpacket>` | {term}`Hashed<Hashed Area>` | False | False | New {term}`preferences<Algorithm Preferences>` |
|
||||
|
||||
### Change expiration time
|
||||
|
||||
To adjust the {term}`expiration time` of an {term}`OpenPGP certificate`, a new *{term}`DirectKey<Direct Key Signature>`* {term}`signature<OpenPGP Signature Packet>` ({term}`type ID<Signature Type ID>` `0x1F`) with a modified {term}`Key Expiration Time subpacket` must be issued. The structure of this {term}`signature<OpenPGP Signature Packet>` is identical to the one outlined in the previous section on changing {term}`algorithm preferences`.
|
||||
|
||||
Additionally, the {term}`expiration time` can be altered for individual {term}`User IDs<User ID>` (detailed below) or separate {term}`subkeys<OpenPGP Subkey>` (see {numref}`bind_subkey`).
|
||||
|
||||
### Add User ID
|
||||
|
||||
To {term}`bind<Binding>` a {term}`User ID` to an {term}`OpenPGP certificate` a {term}`certification signature<Certification>` ({term}`type ID<Signature Type ID>` `0x10`-`0x13`) is used which should have the following structure:
|
||||
|
||||
| {term}`Subpacket<OpenPGP Signature Subpacket>` | Area | {term}`Critical<Criticality Flag>` | Mandatory | Notes |
|
||||
|------------------------------------------------------------------------|-----------------------------|------------------------------------------|----------------------|-------------------------------------------------------------------------------------|
|
||||
| {term}`Signature Creation Time<Signature Creation Time Subpacket>` | {term}`Hashed<Hashed Area>` | True | True | Current time |
|
||||
| {term}`Issuer Fingerprint<Issuer Fingerprint Subpacket>` | {term}`Hashed<Hashed Area>` | True or False | Strongly Recommended | The {term}`primary key<OpenPGP Primary Key>` is the {term}`issuer` |
|
||||
| {term}`Primary User ID<Primary User ID Subpacket>` | {term}`Hashed<Hashed Area>` | True | False | Optional |
|
||||
| {term}`Signature Expiration Time<Signature Expiration Time Subpacket>` | {term}`Hashed<Hashed Area>` | True | False | Optional |
|
||||
|
||||
In addition to these {term}`subpackets<OpenPGP Signature Subpacket>`, {term}`self-certifications<Self-certification>` for {term}`User IDs<User ID>` can include others – such as {term}`key flags<Key Flag>`, {term}`features<Features Subpacket>`, and {term}`algorithm preferences` – as shown in the previous table. This enables the specification of unique capabilities and {term}`preferences<Algorithm Preferences>` for each {term}`identity` associated with the {term}`certificate<OpenPGP Certificate>`.
|
||||
|
||||
### Remove or revoke a User ID
|
||||
|
||||
Since {term}`OpenPGP certificates<OpenPGP certificate>` are often distributed by the means of {term}`key servers<Key Server>`, new {term}`signatures<OpenPGP Signature Packet>` on a {term}`certificate<OpenPGP Certificate>` are often "merged" into existing copies of the {term}`certificate<OpenPGP Certificate>` locally by the recipient.
|
||||
|
||||
```{admonition} TODO
|
||||
:class: warning
|
||||
|
||||
Link to the "Merging" section in chapter 4, once merged.
|
||||
```
|
||||
|
||||
This integration process means it is practically impossible to directly remove {term}`signatures<OpenPGP Signature Packet>` or {term}`User IDs<User ID>` from a {term}`certificate<OpenPGP Certificate>`, as there is no way to communicate the intention of {term}`packet<OpenPGP Signature Packet>` deletion to the recipient.
|
||||
|
||||
To effectively mark a {term}`User ID` as invalid, the user can publish a copy of their {term}`certificate<OpenPGP Certificate>` with a {term}`Certification Revocation signature<Certification Revocation Signature Packet>` ({term}`type ID<Signature Type ID>` `0x30`) attached to the invalidated {term}`User ID`. This {term}`signature<OpenPGP Signature Packet>` signals that the specified {term}`User ID` is no longer valid or associated with the {term}`certificate holder`.
|
||||
|
||||
The structure of a {term}`Certification Revocation signature<Certification Revocation Signature Packet>` is as follows:
|
||||
|
||||
| {term}`Subpacket<OpenPGP Signature Subpacket>` | Area | {term}`Critical<Criticality Flag>` | Mandatory | Notes |
|
||||
|--------------------------------------------------------------------|-----------------------------|------------------------------------------|----------------------|-------------------------------------------------------------------------------------|
|
||||
| {term}`Signature Creation Time<Signature Creation Time Subpacket>` | {term}`Hashed<Hashed Area>` | True | True | Current time |
|
||||
| {term}`Issuer Fingerprint<Issuer Fingerprint Subpacket>` | {term}`Hashed<Hashed Area>` | True or False | Strongly Recommended | The {term}`primary key<OpenPGP Primary Key>` is the {term}`issuer` |
|
||||
| {term}`Reason for Revocation<Reason for Revocation Subpacket>` | {term}`Hashed<Hashed Area>` | True | False | Determines {term}`soft<Soft Revocation>` or {term}`hard revocation` |
|
||||
|
||||
For {term}`User ID` {term}`revocations<Revocation>`, the *{term}`Reason for Revocation<Reason for Revocation Subpacket>`* {term}`subpacket<OpenPGP Signature Subpacket>` is crucial. A value of `0` means no specific reason, leading to a {term}`hard revocation`, while `32` indicates the {term}`User ID` is no longer valid, resulting in a {term}`soft revocation`. Omitting the {term}`reason subpacket<Reason For Revocation Subpacket>` is also equivalent to a {term}`hard revocation`.
|
||||
|
||||
It is generally advisable to use reason code `32` for revoking {term}`User IDs<User ID>`.
|
||||
|
||||
(binding_subkeys)=
|
||||
### Add a subkey
|
||||
|
||||
As part of {term}`life-cycle management`, users may need to add a new {term}`subkey<OpenPGP Subkey>` to their {term}`OpenPGP certificate`, often for reasons such as upgrading to a {term}`subkey<OpenPGP Subkey>` with more advanced cryptographic algorithms. The process involves creating a specific {term}`signature<OpenPGP Signature Packet>` structure:
|
||||
|
||||
| {term}`Subpacket<OpenPGP Signature Subpacket>` | Area | {term}`Critical<Criticality Flag>` | Mandatory | Notes |
|
||||
|---------------------------------------------------------------------------------------------|-----------------------------|------------------------------------------|-------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| {term}`Signature Creation Time<Signature Creation Time Subpacket>` | {term}`Hashed<Hashed Area>` | True | True | Current time |
|
||||
| {term}`Issuer Fingerprint<Issuer Fingerprint Subpacket>` | {term}`Hashed<Hashed Area>` | True or False | Strongly Recommended | The {term}`primary key<OpenPGP Primary Key>` is the {term}`issuer` |
|
||||
| {term}`Key Flags<Key Flag>` | {term}`Hashed<Hashed Area>` | True | Strongly Recommended | Determine the usage of the {term}`key<OpenPGP Subkey>` |
|
||||
| {term}`Key Expiration Time<Key Expiration Time Subpacket>` | {term}`Hashed<Hashed Area>` | True | False | Specifies the {term}`expiration time` of the {term}`subkey<OpenPGP Subkey>` |
|
||||
| {term}`Embedded Signature<Embedded Signature Subpacket>` | {term}`Hashed<Hashed Area>` | True | If {term}`Key Flags<Key Flag>` contains **{term}`S<Signing Key Flag>`** | {term}`Signing subkeys<OpenPGP Signing Subkey>` require embedded *{term}`Primary Key Binding<Primary Key Binding Signature>`* {term}`signature<OpenPGP Signature Packet>` |
|
||||
| {term}`Hash Algorithm Preferences<Preferred Hash Algorithms Subpacket>` | {term}`Hashed<Hashed Area>` | False | False | Per {term}`key<Component Key>` {term}`preferences<Algorithm Preferences>` |
|
||||
| {term}`Compression Algorithm Preferences<Preferred Compression Algorithms Subpacket>` | {term}`Hashed<Hashed Area>` | False | False | Per {term}`key<Component Key>` {term}`preferences<Algorithm Preferences>` |
|
||||
| {term}`Symmetric Algorithm Preferences<Preferred Symmetric Ciphers for v1 SEIPD Subpacket>` | {term}`Hashed<Hashed Area>` | False | False | Per {term}`key<Component Key>` {term}`preferences<Algorithm Preferences>` |
|
||||
| {term}`AEAD Algorithm Preferences<Preferred AEAD Ciphersuites Subpacket>` | {term}`Hashed<Hashed Area>` | False | False | Per {term}`key<Component Key>` {term}`preferences<Algorithm Preferences>` |
|
||||
|
||||
In addition to these {term}`subpackets<OpenPGP Signature Subpacket>`, users can specify {term}`algorithm preferences` for each {term}`subkey<OpenPGP Subkey>`, distinct from those set in the {term}`certificate<OpenPGP Certificate>`'s *{term}`Direct Key<Direct Key Signature>`* {term}`signature<OpenPGP Signature Packet>`.
|
||||
|
||||
### Revoke a subkey
|
||||
|
||||
{term}`Subkeys<OpenPGP subkey>`, like {term}`User IDs<User ID>`, can be individually revoked in OpenPGP.
|
||||
This is done by issuing a {term}`Subkey Revocation signature<Subkey Revocation Signature Packet>` ({term}`type ID<Signature Type ID>` `0x28`) using the {term}`primary key<OpenPGP Primary Key>`.
|
||||
|
||||
The structure of such a {term}`signature<OpenPGP Signature Packet>` is straightforward:
|
||||
|
||||
| {term}`Subpacket<OpenPGP Signature Subpacket>` | Area | {term}`Critical<Criticality Flag>` | Mandatory | Notes |
|
||||
|--------------------------------------------------------------------|-----------------------------|------------------------------------------|----------------------|-------------------------------------------------------------------------------------|
|
||||
| {term}`Signature Creation Time<Signature Creation Time Subpacket>` | {term}`Hashed<Hashed Area>` | True | True | Current time |
|
||||
| {term}`Issuer Fingerprint<Issuer Fingerprint Subpacket>` | {term}`Hashed<Hashed Area>` | True or False | Strongly Recommended | The {term}`primary key<OpenPGP Primary Key>` is the {term}`issuer` |
|
||||
| {term}`Reason for Revocation<Reason For Revocation Subpacket>` | {term}`Hashed<Hashed Area>` | True | False | Determines {term}`soft<Soft Revocation>` or {term}`hard revocation` |
|
||||
|
||||
|
||||
In {term}`Subkey Revocation signatures<Subkey Revocation Signature Packet>`, the [reason for revocation](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-reason-for-revocation) {term}`subpacket<OpenPGP Signature Subpacket>` can only have values in the range of `0-3`. The values `1` ({term}`key<OpenPGP Subkey>` superseded) and `3` ({term}`key<OpenPGP Subkey>` retired and no longer used) indicate {term}`soft revocations<Soft Revocation>`, whereas values `0` (no reason) and `2` ({term}`key<OpenPGP Subkey>` compromised) indicate {term}`hard revocations<Hard Revocation>`.
|
||||
|
||||
Note that a value of `32` is not applicable in these {term}`signatures<OpenPGP Signature Packet>`.
|
||||
|
||||
```{admonition} TODO
|
||||
:class: warning
|
||||
|
||||
Research and explain hardness in the context of subkey revocations. What does a hard subkey revocation express concretely?
|
||||
```
|
||||
|
||||
### Revoke a certificate
|
||||
|
||||
Users may find themselves needing to revoke their entire {term}`OpenPGP certificate`, rendering it unusable. This could be for various reasons, such as migrating to a new {term}`certificate<OpenPGP certificate>` or in response to a compromise of the {term}`certificate<OpenPGP certificate>`'s {term}`secret key material<Private Key Material>`.
|
||||
|
||||
While a {term}`soft-revoked<Soft Revocation>` {term}`certificate<OpenPGP Certificate>` can be re-validated at a later time with a new {term}`certification`, a {term}`hard revocation` is permanent.
|
||||
|
||||
The recommended way to {term}`revoke<Revocation>` a {term}`certificate<OpenPGP Certificate>` is by issuing a {term}`Key Revocation signature<Key Revocation Signature Packet>` ({term}`type ID<Signature Type ID>` `0x20`). Its structure is similar to that of a {term}`Certification Revocation signature<Certification Revocation Signature Packet>`.
|
||||
|
||||
| {term}`Subpacket<OpenPGP Signature Subpacket>` | Area | {term}`Critical<Criticality Flag>` | Mandatory | Notes |
|
||||
|--------------------------------------------------------------------|-----------------------------|------------------------------------------|----------------------|-------------------------------------------------------------------------------------|
|
||||
| {term}`Signature Creation Time<Signature Creation Time Subpacket>` | {term}`Hashed<Hashed Area>` | True | True | Current time |
|
||||
| {term}`Issuer Fingerprint<Issuer Fingerprint Subpacket>` | {term}`Hashed<Hashed Area>` | True or False | Strongly Recommended | The {term}`primary key<OpenPGP Primary Key>` is the {term}`issuer` |
|
||||
| {term}`Reason for Revocation<Reason For Revocation Subpacket>` | {term}`Hashed<Hashed Area>` | True | False | Determines {term}`soft<Soft Revocation>` or {term}`hard revocation` |
|
||||
|
||||
For {term}`Key Revocation signatures<Key Revocation Signature Packet>`, the guidelines regarding the [*Reason for Revocation* subpacket](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-reason-for-revocation) are the same as those for {term}`Subkey Revocation signatures<Subkey Revocation Signature Packet>`.
|
||||
|
||||
### Common subpackets in OpenPGP signatures
|
||||
|
||||
In OpenPGP, certain {term}`subpackets<OpenPGP Signature Subpacket>` are universally expected across all types of {term}`signatures<OpenPGP Signature Packet>`, serving fundamental roles in the {term}`signature<OpenPGP Signature Packet>`'s structure, {term}`verification` and {term}`validation`:
|
||||
|
||||
* **{term}`Signature Creation Time<Signature Creation Time Subpacket>`**: This is a mandatory {term}`subpacket<OpenPGP Signature Subpacket>` in every {term}`OpenPGP signature<OpenPGP Signature Packet>`. It contains the timestamp of when the {term}`signature<OpenPGP Signature Packet>` was created. For security and integrity, this {term}`subpacket<OpenPGP Signature Subpacket>` must be located in the {term}`hashed area` of the {term}`signature<OpenPGP Signature Packet>` and is recommended to be marked as {term}`critical<Criticality Flag>`.
|
||||
|
||||
* **{term}`Issuer Fingerprint<Issuer Fingerprint Subpacket>`**: Essential for {term}`signature<OpenPGP Signature Packet>` {term}`validation`, this {term}`subpacket<OpenPGP Signature Subpacket>` identifies the {term}`key<OpenPGP Primary Key>` (or {term}`subkey<OpenPGP Subkey>`) that was used to create the {term}`signature<OpenPGP Signature Packet>`. OpenPGP v6 {term}`signatures<OpenPGP Signature Packet>` should include the {term}`Issuer Fingerprint subpacket`, containing the 32-byte {term}`fingerprint<OpenPGP Fingerprint>` of the {term}`key<Component Key>`.
|
||||
|
||||
```{note}
|
||||
The {term}`key<Component Key>` used as the {term}`issuer` in the {term}`signature<OpenPGP Signature Packet>` might be a {term}`subkey<OpenPGP Subkey>` of the {term}`certificate<OpenPGP Certificate>`.
|
||||
```
|
||||
|
||||
These {term}`subpackets<OpenPGP Signature Subpacket>` can be placed in either the {term}`hashed<Hashed Area>` or {term}`unhashed area` due to its self-{term}`authenticating<Authentication>` nature. However, we recommend including them in the {term}`signature<OpenPGP Signature Packet>`'s {term}`hashed area`.
|
||||
|
||||
## Managing subpacket conflicts and duplication
|
||||
|
||||
In {term}`OpenPGP signatures<OpenPGP Signature Packet>`, both the {term}`hashed<Hashed Area>` and {term}`unhashed areas<Unhashed Area>` are composed of lists of {term}`subpackets<OpenPGP Signature Subpacket>`. Inherently, this structure permits the duplication of the same {term}`subpacket<OpenPGP Signature Subpacket>`, which could lead to conflicts. To manage these potential conflicts, the following strategies are used:
|
||||
|
||||
- **Precedence of {term}`hashed area`**: {term}`Subpackets<OpenPGP Signature Subpacket>` within the {term}`hashed area` of a {term}`signature<OpenPGP Signature Packet>` take precedence over those in the {term}`unhashed area`. This hierarchy helps resolve conflicts when the same {term}`subpacket<OpenPGP Signature Subpacket>` appears in both areas.
|
||||
|
||||
- **Handling conflicts within the same area**: Conflicts can still arise within the same area, such as when two {term}`subpackets<OpenPGP Signature Subpacket>` have different {term}`expiration times<Expiration Time>`. In such cases, the [OpenPGP specification](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-notes-on-subpackets) advises that {term}`implementations<OpenPGP Implementation>` should favor the last occurrence of a conflicting {term}`subpacket<OpenPGP Signature Subpacket>` in the {term}`hashed area`.
|
||||
|
||||
In certain scenarios, having duplicate {term}`subpackets<OpenPGP Signature Subpacket>` with conflicting content is logical and even necessary. For example, consider a {term}`signature<OpenPGP Signature Packet>` created by a version 4 {term}`issuer` {term}`key<Component Key>`, which was upgraded from an older OpenPGP version (like v3). Since the {term}`key ID` calculation scheme changed from v3 to v4, the identifiers for the same {term}`key<Component Key>` would differ between these versions. Therefore, a v4 signature might contain two {term}`issuer key ID subpackets<Issuer Fingerprint Subpacket>`, each with different, yet correct values for v3 and v4 {term}`keys<Component Key>`, respectively. This allows for backward compatibility and ensures the {term}`signature<OpenPGP Signature Packet>` can be {term}`validated<Validation>` under both {term}`key ID` calculation schemes.
|
Loading…
Add table
Add a link
Reference in a new issue