openpgp-notes/book/source/06-signatures.md
David Runge 83a07f0001
Add name and alt attributes for all figures
Signed-off-by: David Runge <dave@sleepmap.de>
2023-11-20 19:13:19 +01:00

17 KiB
Raw Blame History

OpenPGP Signatures

Signatures are a fundamental mechanism within OpenPGP. They provide the syntax for forming and interpreting comprehensive statements about certificates and their components, as well as for ensuring the integrity and authenticity of data.

Without signatures, keys would remain unassociated with any certificate or owner. Signatures are crucial for binding component keys and identity components into hierarchical certificates and for establishing the authenticity of messages.

Terminology

Within OpenPGP, the term signature can have two different meanings:

  • Cryptographic signature: a sequence of bytes created by cryptographic keys, calculated according to a signature scheme.
  • OpenPGP signature packets: Defined in the OpenPGP standard, these packets combine a raw cryptographic signature along with a type designation and additional metadata.
: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

In this document, "signature" will refer to OpenPGP signature packets.

(signature_types)=

Signature types in OpenPGP

The OpenPGP standard defines a set of 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:

  • Signatures over data: These signatures are denoted by type IDs 0x00 for binary documents and 0x01 for canonical text documents. The signer uses these signatures to claim ownership, assert creation, or certify the immutability of the document.
  • Signatures on components: These are signatures that are associated with component keys or identity components of a certificate.

Signatures on components are a complex topic, and we discuss them in depth in {ref}component_signatures_chapter. They are grouped based on two criteria:

  • the origin of the signature, distinguishing between a self-signature and a third-party signature
  • the nature of the statement made by the signature, such as certifying an identity or binding component keys into a certificate
: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

This chapter will cover the overarching principles applicable to all OpenPGP signature types.

For more detail about specific types of signatures, see the chapters on {ref}signing_data and {ref}component_signatures_chapter, respectively.

Structure of an OpenPGP signature packet

As outlined above, an OpenPGP signature is a composite data structure, which combines:

  • Signature type ID: specifies the signature's intended meaning, as detailed above
  • Metadata: varies based, in part, on the signature type ID; mostly encoded as "subpackets" (see {ref}signature_subpackets)
  • Raw cryptographic signature
: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

Creating an OpenPGP signature packet

Creating an OpenPGP signature packet involves encoding a statement about a specific set of data within the packet.

The input data of a signature packet includes:

  • Packets being signed: Typically one or more packets, though sometimes none, depending on the context. These are the packets to which the signature statement pertains.
  • Data within the signature packet: This includes information that specifies the intent of the signature.

The input data is determined by the signature type and consists of the exact content that the signature statement addresses.

The signature packet consists of two parts:

  1. Statement definition: This part of the packet defines the meaning or intent of the signature.
  2. Cryptographic digital signature: This is the formal endorsement by the signer, created as follows:
    • A hash digest is calculated from the input data.
    • The signature is then calculated for this hash digest.
: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

(sig-verify)=

Verifying an OpenPGP signature packet

Verifying an OpenPGP signature packet is similar to its creation, with some crucial differences that facilitate the verification by entities other than the signer.

The main differences:

  • Access to public key: Unlike the creation process, which is exclusive to the signer, verification can be performed by anyone who has access to the public key of the signer.
  • Use of signature verification mechanism: 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.
: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

(signature_subpackets)=

Signature subpackets

In the OpenPGP protocol, signature subpackets enhance the expressiveness of a signature beyond what is conveyed by just the bare cryptographic signature and the signature type ID. These subpackets, introduced in RFC 2440, are essential for embedding additional metadata within signature packets.

Signature subpackets serve as sub-elements within signature packets, providing extra context and meaning to a signature. They are formatted as key-value pairs, where the keys are defined as subpacket type IDs by the RFC. The RFC also provides the format and interpretation of the values.

Examples of signature subpackets

  • The issuer fingerprint subpacket encodes the fingerprint of the component key that issued the signature.
  • The key flags subpacket defines the capabilities that are assigned to a component key within a certificate.

Hashed and unhashed signature subpackets

Signature subpackets within OpenPGP can reside in one of two distinct areas of a signature packet, each serving a different purpose.

  • Hashed area: Hashed subpackets are included in the hash digest of the signature and are thus covered by its cryptographic signature. They reliably express the signer's intent.
  • Unhashed area: Unhashed subpackets, conversely, are not included in the hash digest for the signature. They are thus not protected against tampering and can be used to retroactively add, change, or remove metadata in a signature packet without affecting its validity. They are primarily used for advisory purposes or in scenarios where the integrity of the subpacket content can be self-authenticated. An example is the issuer fingerprint subpacket, which can be validated through successful signature verification using the referenced issuer key.

The majority of signature subpackets are stored in the hashed area.

For detailed information and specifications, refer to Hashed vs. Unhashed Subpackets in the OpenPGP RFC.

Criticality of subpackets

In the OpenPGP protocol, each signature subpacket can be marked with a criticality flag. This flag plays a pivotal role in the interpretation and validation of the signature. When set, it instructs any receiving implementation encountering an unrecognized subpacket type to treat this as a significant error and to invalidate the signature.

This mechanism accounts for different OpenPGP implementations that may support only certain subsets of the standard. Moreover, it anticipates the evolution of the standard, including the addition of new subpacket types.

Consider a scenario where an implementation does not recognize a subpacket indicating signature expiration. Without understanding this concept, the implementation might erroneously accept an already expired signature. By marking the expiration date subpacket as critical, the creator of the signature ensures that any recipient who cannot process this subpacket will reject the signature as invalid.

For specific guidelines on which subpackets should be marked as critical, refer to the RFC sections 5.2.3.11 to 5.2.3.36.

Advanced topics

Notation signature subpackets

Notation signature subpackets can be used to effectively extend the otherwise limited set of signature subpacket types in OpenPGP with user-defined notations. Issuers can use these notations to add name-value pairs to an OpenPGP signature.

Notation names strings encoded in UTF-8 may reside in the "user namespace." This namespace is characterized by a notation tag, followed by a DNS domain name, both in UTF-8 format.

Notations, as described earlier, allow for user-defined extensions to the OpenPGP signature subpacket types. A practical and popular application of this functionality is seen in Keyoxide, a decentralized identity verification service. Keyoxide uses notations in the ariadne.id namespace. For the details of this implementation, refer to the Keyoxide documentation.

"Negotiating" signature hash algorithm based on recipients preference subpackets

:class: warning

investigate, discuss: GnuPG uses preference packets for the User ID that was addressed while sequoia completely omits User ID preferences and either uses Direct Key Sigs or (I think) primary User ID.

Explore viability of having multiple signatures, e.g. v4+v6?

:class: warning

C-R 5.2. says: An implementation MUST generate a version 6 signature when signing with a version 6 key. An implementation MUST generate a version 4 signature when signing with a version 4 key.