mirror of
https://codeberg.org/openpgp/notes.git
synced 2024-11-22 23:52:05 +01:00
ch5: edits
This commit is contained in:
parent
5ce162b7f1
commit
d9ebc63721
1 changed files with 101 additions and 43 deletions
|
@ -6,18 +6,17 @@ SPDX-License-Identifier: CC-BY-SA-4.0
|
||||||
(private_key_chapter)=
|
(private_key_chapter)=
|
||||||
# Private key material in OpenPGP
|
# Private key material in OpenPGP
|
||||||
|
|
||||||
This chapter discusses the handling of private key material, in OpenPGP. Private key material is associated with component keys that are parts of [OpenPGP certificates](certificates_chapter). For a discussion of packet structure internals, see the chapter {ref}`zoom_private`
|
This chapter discusses the handling of private key material in OpenPGP.
|
||||||
|
|
||||||
Historically, terminology around OpenPGP certificates and keys has often been used inconsistently. The pair of terms "OpenPGP public key" and "OpenPGP private/secret keys" were commonly used (while the shorthand "OpenPGP key" can refer to both, depending on context).
|
Private key material is associated with component keys that are parts of [OpenPGP certificates](certificates_chapter). For a discussion of packet structure internals, see the chapter {ref}`zoom_private`
|
||||||
|
|
||||||
## Terms
|
## Terminology: "Certificates" and "private keys"
|
||||||
|
|
||||||
In this document, we use the term *OpenPGP certificate* to refer "OpenPGP public keys": The combination of component public keys, identity components and bindings.
|
In this document, we use the term *OpenPGP certificate* to refer to what are often called "OpenPGP public keys": OpenPGP certificates are the combination of component public keys, identity components, binding self-signatures and third-party certifications.
|
||||||
|
|
||||||
This chapter is about the counterpart to the public material in certificates: Here, we discuss the handling of *private key material* in OpenPGP.
|
This chapter is about the counterpart to the material in certificates: The corresponding *private key material* of component keys.
|
||||||
|
|
||||||
In this text, we treat the private key material as logically separate from the OpenPGP certificate. Operations that use the private key material are typically handled by a separate subsystem. It is useful to think about OpenPGP certificates on one hand, and the associated private key material, on the other, as two related elements, which are usually handled separately[^pkcs11]:
|
|
||||||
|
|
||||||
|
In this book, we treat the private key material as logically separate from the OpenPGP certificate. A separate subsystem typically handles operations that use private key material. It is useful to think about OpenPGP certificates on one hand, and the associated private key material, on the other, as related but separate elements[^pkcs11]:
|
||||||
|
|
||||||
```{figure} diag/OpenPGPCert_with_privatekeystore.png
|
```{figure} diag/OpenPGPCert_with_privatekeystore.png
|
||||||
:name: fig-openpgp-certificate-with-private-key-store
|
:name: fig-openpgp-certificate-with-private-key-store
|
||||||
|
@ -28,17 +27,13 @@ An OpenPGP certificate, with the associated private key material handled by a ke
|
||||||
|
|
||||||
[^pkcs11]: This kind of distinction between certificates (which combine public key material and identity information) on the one hand, and private key material on the other, is also applied in the data model of [PKCS #11](https://en.wikipedia.org/wiki/PKCS_11) cryptographic systems.
|
[^pkcs11]: This kind of distinction between certificates (which combine public key material and identity information) on the one hand, and private key material on the other, is also applied in the data model of [PKCS #11](https://en.wikipedia.org/wiki/PKCS_11) cryptographic systems.
|
||||||
|
|
||||||
However, there is one exception. Raw cryptographic private key material is sometimes embedded in an OpenPGP framing format that additionally contains the certificate: [*Transferable secret keys (TSK)*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-transferable-secret-keys).
|
However, there is one exception. The cryptographic private key material is sometimes embedded in an OpenPGP framing format that also contains the certificate: Transferable secret keys (TSK).
|
||||||
|
|
||||||
```{admonition} Terminology
|
Historically, terminology around OpenPGP certificates and keys has often been used inconsistently. The pair of terms "OpenPGP public key" and "OpenPGP private/secret keys" were commonly used (while the shorthand "OpenPGP key" can refer to both, depending on context).
|
||||||
:class: note
|
|
||||||
|
|
||||||
Transferable secret keys are sometimes colloquially referred to as "OpenPGP private keys".
|
## Transferable secret key format
|
||||||
```
|
|
||||||
|
|
||||||
## Transferable secret keys
|
Sometimes it is useful to handle OpenPGP certificates combined with private key material in the form of [*transferable secret keys (TSK)*](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-transferable-secret-keys). Transferable secret keys are a serialized format that combines OpenPGP certificate data with the connected private key material, stored in a single file.
|
||||||
|
|
||||||
Sometimes users handle OpenPGP certificates combined with private key material in the form of *transferable secret keys* (TSK). Transferable secret keys are a serialized format that combines the OpenPGP certificate data with the connected private key material, stored in a single file.
|
|
||||||
|
|
||||||
```{figure} diag/TSK.png
|
```{figure} diag/TSK.png
|
||||||
:name: fig-transferable-secret-key
|
:name: fig-transferable-secret-key
|
||||||
|
@ -47,86 +42,118 @@ Sometimes users handle OpenPGP certificates combined with private key material i
|
||||||
OpenPGP certificate with integrated private key material, as a TSK
|
OpenPGP certificate with integrated private key material, as a TSK
|
||||||
```
|
```
|
||||||
|
|
||||||
The TSK format can be useful for backups of OpenPGP key material, or to move a key to a different computer[^gpg-tsk].
|
The TSK format can be useful for backups of OpenPGP key material, or to move a key to a different computer[^gpg-tsk]. See the chapter {ref}`zoom_private` for insights into the packet structure of a TSK.
|
||||||
|
|
||||||
[^gpg-tsk]: For example, with GnuPG, an OpenPGP key can be exported in (armored) TSK format like this: `gpg --export-secret-key --armor <fingerprint>`
|
[^gpg-tsk]: For example, with GnuPG, an OpenPGP key can be exported in (armored) TSK format like this: `gpg --export-secret-key --armor <fingerprint>`
|
||||||
|
|
||||||
See the chapter {ref}`zoom_private` for insights into the packet structure of a TSK.
|
```{admonition} Terminology
|
||||||
|
:class: note
|
||||||
|
|
||||||
|
Transferable secret keys are sometimes colloquially referred to as "OpenPGP private keys".
|
||||||
|
```
|
||||||
|
|
||||||
|
Historically, the concept of TSKs, which combine all aspects of an OpenPGP certificate and the associated private key material, has sometimes been conflated with OpenPGP private key operations.
|
||||||
|
|
||||||
(encrypted_secrets)=
|
(encrypted_secrets)=
|
||||||
## Protecting private key material with a passphrase (using S2K)
|
## Protection of private key material in OpenPGP
|
||||||
|
|
||||||
|
In OpenPGP format, private key material can optionally be protected with a [passphrase](https://en.wikipedia.org/wiki/Passphrase).
|
||||||
|
|
||||||
In OpenPGP format, private key material can be optionally protected with a [passphrase](https://en.wikipedia.org/wiki/Passphrase). This mechanism applies symmetric encryption to the private key data in component keys.
|
Protecting private key material with a passphrase can be useful when a third party obtains a copy of the OpenPGP key data, but doesn't know the passphrase. In this scenario, the attacker may have obtained a copy of an OpenPGP key, but is unable to use it, because it is protected with a passphrase that is not known to the attacker.
|
||||||
|
|
||||||
The symmetric encryption key is derived from a secret that the user knows (the passphrase).
|
### Passphrases to symmetric keys (S2K)
|
||||||
|
|
||||||
Using a passphrase can be useful when a third party can obtain a copy of the OpenPGP key data, but doesn't know the passphrase. In this scenario, an attacker may have obtained a copy of an OpenPGP key, but is unable to use it, because the private key material is encrypted, and the attacker cannot decrypt it.
|
When protecting private key material in OpenPGP, a symmetric key is derived from the user's passphrase.
|
||||||
|
|
||||||
OpenPGP defines a mechanism called [string-to-key (S2K)](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-string-to-key-s2k-specifier) that is used to derive (high-entropy) symmetric encryption keys from (lower-entropy) passphrases, using a [key derivation function (KDF)](https://en.wikipedia.org/wiki/Key_derivation_function).
|
For this purpose, OpenPGP defines a mechanism called [string-to-key (S2K)](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-string-to-key-s2k-specifier) that is used to derive (high-entropy) symmetric encryption keys from (lower-entropy) passphrases, using a [key derivation function (KDF)](https://en.wikipedia.org/wiki/Key_derivation_function).
|
||||||
|
|
||||||
```{figure} diag/passphrase_using_S2K.png
|
```{figure} diag/passphrase_using_S2K.png
|
||||||
:name: fig-passphrase-using-s2k
|
:name: fig-passphrase-using-s2k
|
||||||
:alt: Depicts a diagram on white background with the title "Converting a passphrase into a symmetric key". On the left hand side a box with dotted yellow frame and light yellow background and the text "correct horse battery staple" is shown. It is connected by a dotted yellow line with the word "Passphrase". Right of the passphrase an arrow with green dotted frame, light green background and the text "S2K mechanism (string-to-key)", pointing to the right is shown. On the right hand side the yellow symmetric key symbol is shown.
|
:alt: Depicts a diagram on white background with the title "Converting a passphrase into a symmetric key". On the left hand side a box with dotted yellow frame and light yellow background and the text "correct horse battery staple" is shown. It is connected by a dotted yellow line with the word "Passphrase". Right of the passphrase an arrow with green dotted frame, light green background and the text "S2K mechanism (string-to-key)", pointing to the right is shown. On the right hand side the yellow symmetric key symbol is shown.
|
||||||
|
|
||||||
Transforming a passphrase into a symmetric key
|
Deriving a symmetric key from a passphrase
|
||||||
```
|
```
|
||||||
|
|
||||||
The private key material for individual component keys of one certificate can be encrypted with different mechanisms, and/or using different passphrases.
|
This symmetric key is used to protect the private key material "at rest." That is, while it is stored on-disk. To use a passphrase-protected OpenPGP private key, it is decrypted using the symmetric key, and then used for a set of private key operations.
|
||||||
|
|
||||||
However, this is not customarily done. Usually, when creating a certificate, the user's software will use the same encryption mechanism and passphrase for all component keys (to limit complexity).
|
#### S2K mechanisms for symmetric key generation
|
||||||
|
|
||||||
However, when adding new subkeys to a certificate at a later date, the user might choose to use a different passphrase. Or the user's software may choose a different encryption mechanism, e.g. based on updated best practices.
|
|
||||||
|
|
||||||
### S2K mechanisms for symmetric key generation
|
|
||||||
|
|
||||||
Over time, OpenPGP has specified a series of [S2K mechanisms](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-string-to-key-s2k-types-reg), following the current state of the art. Of the specified S2K mechanisms, two remain relevant today:
|
Over time, OpenPGP has specified a series of [S2K mechanisms](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-string-to-key-s2k-types-reg), following the current state of the art. Of the specified S2K mechanisms, two remain relevant today:
|
||||||
|
|
||||||
- [Iterated and Salted S2K](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-iterated-and-salted-s2k), which OpenPGP version 4 implementations can handle
|
- [Iterated and Salted S2K](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-iterated-and-salted-s2k), which OpenPGP version 4 implementations can handle
|
||||||
- [Argon2](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-argon2), which was newly added in OpenPGP version 6, and additionally protects the passphrase against brute-force attacks because it is memory-hard (which reduces the efficiency of attacks with specialised hardware)
|
- [Argon2](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-11.html#name-argon2), which was newly added in OpenPGP version 6, and additionally protects the passphrase against brute-force attacks because it is memory-hard (which reduces the efficiency of attacks with specialised hardware)
|
||||||
|
|
||||||
### Mechanisms for secret key encryption with S2K
|
### Encryption of private key material with a symmetric key
|
||||||
|
|
||||||
Different mechanisms are specified [for the encryption of the secret key data](https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-secret-key-encryption).
|
So far, we've looked at generating a symmetric key from a passphrase. Following that, the symmetric key is used to encrypt or decrypt the OpenPGP private key material.
|
||||||
|
|
||||||
|
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 of one certificate can be protected with different mechanisms, and/or
|
||||||
|
- using different passphrases.
|
||||||
|
- Individual component keys may be stored in unprotected form, while others are protected.
|
||||||
|
|
||||||
|
However, usually, when creating a certificate, the user's software will use the same encryption mechanism and passphrase for all component keys. This might give the erroneous impression that all component private key material are internally encrypted in one monolithic operation, necessarily using only one passphrase.
|
||||||
|
|
||||||
|
But for example when adding new subkeys to a certificate at a later date, the user might choose to use a different passphrase. Or the user's software may choose a different encryption mechanism, e.g., based on updated best practices.
|
||||||
|
|
||||||
## Private key operations
|
## Private key operations
|
||||||
|
|
||||||
The core of private key operations doesn't require access to the whole certificate.
|
The core of private key operations doesn't require access to the whole certificate.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
### Key store design options
|
||||||
|
|
||||||
Designs of private key subsystems in the OpenPGP space differ:
|
Designs of private key subsystems in the OpenPGP space differ:
|
||||||
|
|
||||||
- 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).
|
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).
|
||||||
- In other designs, the OpenPGP private key subsystem requires the additional metadata that is stored in the component key (the key creation time, for all keys, and in the case of keys that use ECDH algorithms: the KDF parameters).
|
2. An OpenPGP private key subsystem may also require the additional metadata that is stored in the component key (the key creation time, for all keys, and in the case of keys that use ECDH algorithms: the KDF parameters).
|
||||||
|
3. Keeping a copy of full TSKs in the private key subsystem, and using those for private key operations.
|
||||||
|
|
||||||
Either way: at most, a private key subsystem should need access to individual component keys and the associated private key material.
|
Either way: An OpenPGP private key subsystem performs operations that only require the private cryptographic key material.
|
||||||
|
|
||||||
|
An independent concern is how key material is selected, when using the keystore. The fingerprint of the component key is an obvious option. This requirement can be solved by design 2, which allows calculation of component key fingerprints.
|
||||||
|
|
||||||
```{note}
|
```{note}
|
||||||
|
Design 3, which involves keeping a copy of full TSKs in the private key subsystem can cause "split brain" problems.
|
||||||
|
|
||||||
Keeping a copy of the full certificate information in the private key subsystem can cause "split brain" problems. E.g.: expiration times could then differ between different subsystems, when they keep different copies of the certificate information.
|
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].
|
||||||
|
|
||||||
(Thunderbird users currently suffer from such issues, I think)
|
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.
|
||||||
|
|
||||||
### OpenPGP card for private keys
|
### 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.
|
[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.
|
||||||
|
|
||||||
OpenPGP card devices implement an open specification: [Functional Specification of the OpenPGP application on ISO Smart Card Operating Systems, Version 3.4.1](https://gnupg.org/ftp/specs/OpenPGP-smart-card-application-3.4.1.pdf). Multiple vendors produce devices that implement this specification, and there are a number of Free Software implementations (some of which can even be run on open hardware designs).
|
OpenPGP card devices implement an open specification: [Functional Specification of the OpenPGP application on ISO Smart Card Operating Systems, Version 3.4.1](https://gnupg.org/ftp/specs/OpenPGP-smart-card-application-3.4.1.pdf). Multiple vendors produce devices that implement this specification, and there are a number of Free Software implementations (some of which can even be run on open hardware designs).
|
||||||
|
|
||||||
Effectively, the OpenPGP card specification outlines one model for an OpenPGP private key subsystem:
|
Effectively, the OpenPGP card specification outlines one model for an OpenPGP private key store subsystem:
|
||||||
|
|
||||||
OpenPGP card devices do not store the full OpenPGP certificate. Instead, they have three "key slots": one each for signing, decryption and authentication. Each key slots stores the component key data and the associated cryptographic private key material[^missing-ecdh]. In addition, for each key slot, the OpenPGP fingerprint for the contained component key is explicitly stored on the card (note that storing the fingerprint on the card is different from how OpenPGP key data is usually handled: normally, fingerprints are not explicitly stored, but calculated on the fly from the component key data).
|
OpenPGP card devices do not store a full OpenPGP certificate. Instead, they have three "key slots", one each for *signing*, *decryption* and *authentication*. Each key slot stores the data of one component key[^missing-ecdh], complete with cryptographic private key material. Additionally, the fingerprint for the component key in each key slot is explicitly stored on the card.
|
||||||
|
|
||||||
[^missing-ecdh]: In the case of ECDH keys, the KDF parameters (hash function ID and a symmetric encryption algorithm ID) are not stored on the OpenPGP card. This is considered a flaw in the OpenPGP card specification. These missing parameters can be handled in two ways, by OpenPGP software running on the host computer: Either by consulting a copy of the component key (e.g. by inspecting a copy of the certificate), or by deducing the missing KDF parameters from the OpenPGP fingerprint that is stored on the card.
|
[^missing-ecdh]: In the case of ECDH keys, the KDF parameters (hash function ID and a symmetric encryption algorithm ID) are not stored on the OpenPGP card. This is considered a flaw in the OpenPGP card specification. These missing parameters can be handled in two ways, by OpenPGP software running on the host computer: Either by consulting a copy of the component key (e.g. by inspecting a copy of the certificate), or by deducing the missing KDF parameters from the OpenPGP fingerprint that is stored on the card.
|
||||||
|
|
||||||
## What a private key store does
|
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.
|
||||||
|
|
||||||
```{admonition} TODO
|
```{note}
|
||||||
:class: warning
|
The ECDH mechanism for decryption on an OpenPGP card produces the "shared secret". The unwrapping step happens in software, outside the card.
|
||||||
|
|
||||||
write
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Details about the operation of an OpenPGP key store
|
||||||
|
|
||||||
```{admonition} VISUAL
|
```{admonition} VISUAL
|
||||||
:class: warning
|
:class: warning
|
||||||
|
|
||||||
|
@ -136,6 +163,37 @@ show examples for the operations in a private key store.
|
||||||
- analogous: once we have a visual for the low level asymmetric decryption operation (in ch11), mirror it here
|
- analogous: once we have a visual for the low level asymmetric decryption operation (in ch11), mirror it here
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Signing
|
||||||
|
|
||||||
|
```{admonition} TODO
|
||||||
|
:class: warning
|
||||||
|
|
||||||
|
write
|
||||||
|
```
|
||||||
|
|
||||||
|
### Decryption
|
||||||
|
|
||||||
|
```{admonition} TODO
|
||||||
|
:class: warning
|
||||||
|
|
||||||
|
write
|
||||||
|
```
|
||||||
|
|
||||||
|
```{note}
|
||||||
|
Decryption with ECC algorithms, using ECDH, is a multi-step procedure. Only one of these steps is handled by the card.
|
||||||
|
|
||||||
|
The ECDH mechanism on the card produces a "shared secret" in compliance with the Elliptic Curve Key Agreement Scheme from Diffie-Hellman. Further processing (such as the key derivation function) happens in software.
|
||||||
|
|
||||||
|
<https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-ec-dh-algorithm-ecdh>
|
||||||
|
|
||||||
|
ECDH: Key Wrap Algorithm (RFC 3394)
|
||||||
|
|
||||||
|
<https://www.rfc-editor.org/rfc/rfc3394.html>
|
||||||
|
|
||||||
|
- [Decrypt unwrap in Sequoias ecdh.rs](https://gitlab.com/sequoia-pgp/sequoia/-/blob/main/openpgp/src/crypto/ecdh.rs?ref_type=heads#L120) should be a good place to start
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Advanced topics
|
## Advanced topics
|
||||||
|
|
||||||
### TSKs: Best practices S2K + S2K migration?
|
### TSKs: Best practices S2K + S2K migration?
|
||||||
|
|
Loading…
Reference in a new issue