<!--
SPDX-FileCopyrightText: 2023 The "Notes on OpenPGP" project
SPDX-License-Identifier: CC-BY-SA-4.0
-->

(private_key_chapter)=
# Private key material in OpenPGP

This chapter discusses the handling of private key material within OpenPGP.

Private key material is associated with component keys, which are integral parts of [OpenPGP certificates](certificates_chapter). For a discussion of packet structure internals, see the chapter {ref}`zoom_private`.

## Terminology: "certificates" and "private keys"

Recall that in this document, the term *OpenPGP certificate* refers to what are commonly known as "OpenPGP public keys." OpenPGP certificates are the combination of component public keys, identity components, binding self-signatures, and third-party certifications,
as discussed in the previous chapter ({ref}`certificates_chapter`).

This chapter focuses on the corresponding counterpart to the elements of certificates: the *private key material* of component keys.

In this documentation, we treat the private key material as logically separate from the OpenPGP certificate. Operations that use private key material are typically managed by a separate subsystem. It is useful to view OpenPGP certificates and the associated private key material as related but distinct elements[^pkcs11]:

```{figure} diag/OpenPGPCert_with_privatekeystore.png
:name: fig-openpgp-certificate-with-private-key-store
:alt: A diagram on a white background showing an OpenPGP certificate and a private key store. Gray dotted lines connect the green public key symbols of the OpenPGP certificate to red dotted private key symbols in the private key store.

An OpenPGP certificate, with the associated private key material handled in a separate subsystem.
```

[^pkcs11]: The distinction between certificates (which combine public key material and identity information) and private key material is similarly made in the data model of [PKCS #11](https://en.wikipedia.org/wiki/PKCS_11) cryptographic systems.

However, there is one exception. Cryptographic private key material is sometimes embedded within an OpenPGP framing format that also contains the certificate: transferable secret keys (TSK).

## Transferable secret key format

Sometimes it is useful to handle OpenPGP certificates combined with private key material in the form of a [*transferable secret key (TSK)*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-transferable-secret-keys). A TSK is a serialized format that combines OpenPGP certificate data with its connected private key material, stored in a single file.

```{figure} diag/TSK.png
:name: fig-transferable-secret-key
:alt: A box on a white background titled "transferable secret key." It resembles the figure depicting an OpenPGP certificate, except that in each component key box, below the green public key symbol,  the red-dotted private key symbol is also shown.

OpenPGP certificate with integrated private key material, as a TSK
```

The TSK format is particularly useful for backups of OpenPGP key material or transferring a key to a different computer[^gpg-tsk]. For insights into the packet structure of a TSK, see the chapter {ref}`zoom_private`.

[^gpg-tsk]: For example, in GnuPG, an OpenPGP key can be exported in (armored) TSK format using the following command: `gpg --export-secret-key --armor <fingerprint>`.

```{admonition} Terminology
:class: note

Transferable secret keys are sometimes colloquially referred to as "OpenPGP private keys."
```

Historically, the concept of TSKs, which combine all components of an OpenPGP certificate with the associated private key material, has sometimes been conflated with OpenPGP private key operations. However, it is more accurate to view TSKs as a specialized format for storage and transport, rather than as a data structure for use in a key store. For further details, see {ref}`key-store-design`.

(encrypted_secrets)=
## Protection of private key material in OpenPGP
 
In the OpenPGP format, private key material can be optionally protected with a [passphrase](https://en.wikipedia.org/wiki/Passphrase). 

This method proves effective in scenarios where an unauthorized party obtains the OpenPGP key data but does not know the passphrase. Such a safeguard renders the key unusable to the attacker, effectively protecting it against unauthorized access or use.

### Transforming a passphrase into a symmetric key

When protecting private key material in OpenPGP, a symmetric key is derived from the user's passphrase. This derived key is then used to protect the OpenPGP private key data.

To facilitate this, the OpenPGP standard defines a set of mechanisms known as [string-to-key (S2K)](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-string-to-key-s2k-specifier). S2K mechanisms are used to generate high-entropy symmetric encryption keys from lower-entropy passphrases, using a [key derivation function (KDF)](https://en.wikipedia.org/wiki/Key_derivation_function).

```{figure} diag/passphrase_using_S2K.png
:name: fig-passphrase-using-s2k
:alt: A diagram on a white background titled "Converting a passphrase into a symmetric key." On the left is a light-yellow box with dotted-yellow borders framing the phrase "correct horse battery staple." A dotted yellow line falls below the box to the term "passphrase." To the right of the box is a light-green arrow with green-dotted borders and the text "S2K mechanism (string-to-key). The arrow points to its right, where a yellow symmetric key symbol is shown.

Deriving a symmetric key from a passphrase
```

This symmetric key is used to protect the private key material it is in a passive state, for example, when stored on disk. To use a passphrase-protected OpenPGP private key, it is first decrypted using the symmetric key and then used for private key operations, remaining temporarily unlocked in memory.

#### Mechanisms for symmetric key generation

Over time, OpenPGP has evolved to include various [S2K mechanisms for generating symmetric keys](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-string-to-key-s2k-types-reg), in line with advancements in cryptographic practices. Currently, two mechanisms are universally recommended:

- [**Argon2**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-argon2): Introduced in OpenPGP version 6, Argon2 is a memory-hard mechanism designed to reduce the efficiency of brute-force attacks using specialized hardware.
- [**Iterated and Salted S2K**](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-iterated-and-salted-s2k): This mechanism is a staple with OpenPGP version 4 implementations.

A third mechanism is conditionally allowed for key generation. Decryption of private keys that use obsolete mechanisms is also allowed.

The RFC uses the terms "String-to-Key (S2K) specifier" or "String-to-Key (S2K) specifier type" for mechanisms used to *generate* a symmetric key from a passphrase.

### Using the symmetric key for encryption 

The generation of a symmetric key from a passphrase leads to its subsequent use in encrypting or decrypting OpenPGP private key material.

The RFC uses the term "String-to-Key Usage (S2K usage)" for the mechanism used to *apply* the symmetric key.

Different mechanisms are specified [for encryption of OpenPGP private key material](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-secret-key-encryption).

### Passphrase-protection acts per-component key

The OpenPGP mechanism for protecting private key material applies individually to each component key:

- Private key material for individual component keys within a single certificate can be protected with different mechanisms or passphrases.
- Individual component keys may be stored in unprotected form, while others are secured.

Commonly, when creating a certificate, the user's software will use the same encryption mechanism and passphrase for all component keys. This might give the erroneous impression that all component private key material is encrypted in one, monolithic operation using a single passphrase.

However, variations are possible, such as when adding new subkeys to an existing certificate. In such cases, a user might choose a different passphrase, or the software might select a different encryption mechanism, for instance, for updated best practices.

(card-priv)=
## OpenPGP card for private keys

[OpenPGP card](https://en.wikipedia.org/wiki/OpenPGP_card) devices are a type of hardware security device.

They are one popular way to handle OpenPGP private key material. Using an OpenPGP card is an alternative to directly handling private key material on the user's computer.

Hardware security devices, such as OpenPGP cards, are designed so that the user's computer never has direct access to the private key material. The goal is to make it impossible to exfiltrate the key material, even when a remote attacker has fully compromised the user's system.

OpenPGP card devices implement an open specification: [Functional Specification of the OpenPGP application on ISO Smart Card Operating Systems, Version 3.4.1](https://gnupg.org/ftp/specs/OpenPGP-smart-card-application-3.4.1.pdf). Multiple vendors produce devices that implement this specification, and there are a number of Free Software implementations (some of which can even be run on open hardware designs).

Effectively, the OpenPGP card specification outlines one model for an OpenPGP private key store subsystem:

OpenPGP card devices do not store a full OpenPGP certificate. Instead, they have three "key slots", one each for *signing*, *decryption* and *authentication*. Each key slot stores the data of one component key[^missing-ecdh], complete with cryptographic private key material. Additionally, the fingerprint for the component key in each key slot is explicitly stored on the card.

[^missing-ecdh]: In the case of ECDH keys, the KDF parameters (hash function ID and a symmetric encryption algorithm ID) are not stored on the OpenPGP card. This is considered a flaw in the OpenPGP card specification. These missing parameters can be handled in two ways, by OpenPGP software running on the host computer: Either by consulting a copy of the component key (e.g. by inspecting a copy of the certificate), or by deducing the missing KDF parameters from the OpenPGP fingerprint that is stored on the card.

Note that explicitly stored fingerprints on OpenPGP cards are in contrast to how OpenPGP's format stores component keys: fingerprints are not explicitly stored, but calculated on the fly from the component key data.

## Private key operations

While OpenPGP as a whole employs a broad range of cryptographic mechanisms, the set of operations that are performed in the core of a private key store are simple and very limited.

Specifically, an OpenPGP private key store implements two primitives:

1. Given private key material whose algorithm supports decryption, it can decrypt a *session key*.
2. Given private key material whose algorithm supports signing, it can calculate a *cryptographic signature* for a hash digest.

All required operations can be performed with access to the component keys, including their private key material. That is, [Secret-Key packets](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-secret-key-packet-formats). Additional packets, such as binding signatures, are not required for the operations in a private key store. 

(key-store-design)=
## Private key stores

### Design options

Designs of private key subsystems in the OpenPGP space differ:

1. Some designs perform the primitive cryptographic operations in a separate backend, only using the cryptographic key material itself. This type of design matches well with general purpose hardware cryptographic devices (such as TPMs).
2. An OpenPGP private key subsystem may be built around component keys - that is, the content of [Secret-Key packets](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-secret-key-packet-formats). These include metadata, which is required for some operations. ECDH operations, in particular, require metadata as KDF parameters.
3. Keeping a copy of full TSKs in the private key subsystem, and using those for private key operations.

Private key store operations require component keys, but do not require access to the rest of the certificate.

```{note}
Design 3, which involves keeping a copy of full TSKs in the private key subsystem can cause "split brain" problems.

For example, the private key store may contain a TSK, with outdated certificate metadata. The certificate may be considered expired, based on data in the TSK, while the copy of the same certificate in the local public key store might show an updated version where the expiration date has been extended[^tb-split].

This class of problem existed in GnuPG 1.x, which held separate copies of full TSKs in its private store component.
```

[^tb-split]: The current design of Thunderbird's OpenPGP subsystem can lead to users experiencing such issues.

### Two tiers

At its core, an OpenPGP private key subsystem performs operations that only require the private cryptographic key material, as in design 1.

However, some operations require additional access to the metadata of the component key. Those operations can be considered supplementary to the core keystore operations, and don't involve the private key material, themselves. When implementing a key store based on hardware cryptographic devices, like [OpenPGP card](card-priv), its design will consist of two layers:

- One that deals immediately with private key material, and
- One that performs additional cryptographic operations, which don't directly use the private key material (in particular: [AES key wrap](https://www.rfc-editor.org/rfc/rfc3394.html) for ECDH).

```{note}
Decryption with ECC algorithms using ECDH in particular is a multi-step procedure.
 
Only one of these steps deals directly with private key material, and is performed by e.g. an OpenPGP card device. This step produces the "shared secret".
 
 An additional ["AES key unwrap"](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-ec-dh-algorithm-ecdh) step happens in software, outside the card. Also see "Advanced Encryption Standard (AES) Key Wrap Algorithm" [RFC 3394](https://www.rfc-editor.org/rfc/rfc3394.html).
```

### Addressing individual keys

An independent design question is how key material is addressed, by users of the keystore.

The fingerprint of the individual component keys is one obvious option.

Depending on what backs the keystore, fingerprints are readily available, such as with software private keys, or OpenPGP card devices. In other cases, the key store needs to keep track of fingerprints by itself, e.g., when based on generic cryptographic hardware such as TPM.

### Assorted other duties

Additionally, a key store may want to keep track of devices that contain particular component keys. It may need to deal with secrets, such as passphrases of software keys, or PINs of OpenPGP card devices. It may need to notify the user that some interaction is required. For example, some OpenPGP card devices can require touch confirmation to authorize each cryptographic operation.

### Visualizing key store operations 

#### Signing

```{admonition} TODO
:class: warning

write
```

```{admonition} VISUAL
:class: warning

show examples for the operations in a private key store.

- reuse the visual elements of the lowest level in the ch6 "how signatures are made" diagram (ch 6): "making a cryptographic signature from a hash digest"
```

#### Decryption

```{admonition} TODO
:class: warning

write
```

```{admonition} VISUAL
:class: warning

show examples for the operations in a private key store.

- once we have a visual for the low level asymmetric decryption operation (in ch11), mirror it here
```

## Advanced topics

### TSKs: Best practices S2K + S2K migration?

```{admonition} TODO
:class: warning

write
```

### The KOpenPGP attack

See [https://www.kopenpgp.com/](https://www.kopenpgp.com/)
