Skip to content

Commit

Permalink
Merge pull request python#4 from trishankatdatadog/trishankatdatadog/…
Browse files Browse the repository at this point in the history
…online-keys

Discuss how to manage online and offline keys
  • Loading branch information
JustinCappos authored Oct 9, 2019
2 parents 39c73df + 0980fc4 commit 2bf2c95
Showing 1 changed file with 99 additions and 22 deletions.
121 changes: 99 additions & 22 deletions pep-0458.txt
Original file line number Diff line number Diff line change
Expand Up @@ -473,21 +473,8 @@ order to be able to run on as many systems as Python supports; and third, TUF
recommends diversity of keys for certain applications.


Number Of Keys Recommended
--------------------------

The *timestamp*, *snapshot*, and *bins* roles require continuous delivery.
Even though their respective keys MUST be online, this PEP requires that the
keys be independent of each other. Different keys for online roles allow for
each of the keys to be placed on separate servers if need be, and prevents side
channel attacks that compromise one key from automatically compromising the
rest of the keys. Therefore, each of the *timestamp*, *snapshot*, and *bins*
roles MUST require (1, 1) keys.

The *bins* role MAY delegate targets in an automated manner to a number of
roles called "bins", as discussed in the previous section. Each of the "bin"
roles SHOULD share the same key as the *bins* role, due to space efficiency,
and because there is no security advantage to requiring separate keys.
Number and Type Of Keys Recommended
-----------------------------------

The *root* role key is critical for security and should very rarely be used.
It is primarily used for key revocation, and it is the locus of trust for all
Expand All @@ -509,22 +496,112 @@ MUST be offline and independent of other keys. For simplicity of key
management, without sacrificing security, it is RECOMMENDED that the keys of
the *targets* role be permanently discarded as soon as they have been created
and used to sign for the role. Therefore, the *targets* role SHOULD require
(1, 1) keys. Again, this is because the keys are going to be permanently
discarded and more offline keys will not help resist key recovery attacks [21]_
unless diversity of keys is maintained.
(2, 2) keys. Again, this is because the keys are going to be permanently
discarded, and more offline keys will not help resist key recovery
attacks [21]_ unless diversity of cryptographic algorithms is maintained.

For similar reasons, the keys for the *bins* role SHOULD be set up similar to
the keys for the *targets* role.

Online and Offline Keys Recommended for Each Role
-------------------------------------------------
In order to support continuous delivery, the keys for the *timestamp*,
*snapshot*, and all *bin-n* roles MUST be online. There is little benefit in
requiring all of these roles to use different online keys, since attackers
would presumably be able to compromise all of them if they compromise PyPI.
Therefore, it is reasonable to use one online key for them all.

In order to support continuous delivery, the *timestamp*, *snapshot*, *bins*
role keys MUST be online.

Managing online keys
---------------------

The online key shared by the *timestamp*, *snapshot*, and all *bin-n* roles
MAY be stored, encrypted or not, on the Python infrastructure. For example,
the key MAY be kept on a self-hosted key management service (e.g. Hashicorp
Vault__), or a third-party one (e.g. AWS KMS__, Google Cloud KMS__, or Azure
Key Vault__).

__ https://www.vaultproject.io/
__ https://aws.amazon.com/kms/
__ https://cloud.google.com/kms/
__ https://docs.microsoft.com/en-us/azure/key-vault/basic-concepts

Some of these key management services allow keys to be stored on Hardware
Security Modules (HSMs) (e.g., Hashicorp Vault__, AWS CloudHSM__, Google
Cloud HSM__, Azure Key Vault__). This prevents attackers from exfiltrating
the online private key (albeit not from using it, although their actions
may now be cryptographically auditable). However, this requires modifying
the reference TUF implementation to support HSMs (WIP__).

__ https://www.vaultproject.io/docs/enterprise/hsm/index.html
__ https://aws.amazon.com/cloudhsm/
__ https://cloud.google.com/hsm/
__ https://docs.microsoft.com/en-us/azure/key-vault/key-vault-hsm-protected-keys
__ https://github.com/secure-systems-lab/securesystemslib/pull/170

Regardless of where and how this online key is kept, its use SHOULD be
carefully logged, monitored, and audited, ideally in a such a manner that
attackers who compromise PyPI are unable to immediately turn off this logging,
monitoring, and auditing.

Managing offline keys
----------------------

As explained in the previous section, the *root* and *targets* role keys MUST
be offline for maximum security: these keys will be offline in the sense that
their private keys MUST NOT be stored on PyPI, though some of them MAY be
online in the private infrastructure of the project.

There SHOULD be an offline key ceremony to generate, backup, and store these
keys in in such a manner that the private keys can be read only by the Python
administrators when necessary (e.g., such as rotating the keys for the
top-level TUF roles). Thus, keys SHOULD be generated—preferably in a physical
location where side-channel attacks__ are not a concern—using:

1. A trusted, airgapped__ computer with a true random number generator
__, and with no **data** persisted after the ceremony
2. A trusted operating system
3. A trusted set of third-party packages (e.g., cryptographic libraries,
the TUF reference implementation)

__ https://en.wikipedia.org/wiki/Side-channel_attack
__ https://en.wikipedia.org/wiki/Air_gap_(networking)
__ https://en.wikipedia.org/wiki/Hardware_random_number_generator

In order to avoid persisting sensitive data (e.g., private keys) other than
on backup media after the ceremony, offline keys SHOULD be generated
encrypted using strong passwords, either on (in decreasing order of trust):
private HSMs (e.g., YubiHSM__), cloud-based HSMs (e.g., those listed above),
in volatile memory (e.g., RAM), or in nonvolatile memory
(e.g., SSD or microSD). If keys must be generated on nonvolatile memory,
then this memory MUST be irrecoverably destroyed after having securely
backed up the keys.

__ https://www.yubico.com/products/yubihsm/

Passwords used to encrypt keys SHOULD be stored somewhere durable and
trustworthy where only Python admins have access.

In order to minimize OPSEC__ errors during the ceremony, scripts SHOULD be
written to automate tedious parts such as:

- Exporting to sneakernet__ all code and data (e.g., previous TUF metadata,
targets, and *root* keys) required to generate new keys and replace old ones
- Tighten the firewall, update the entire operating system in order to
fix security vulnerabilities, and airgap the computer
- Print and save cryptographic hashes of new TUF metadata
- Export *all* new TUF metadata, targets, and keys to encrypted backup media
- Export *only* new TUF metadata, targets, and online keys to encrypted backup
media

__ https://en.wikipedia.org/wiki/Operations_security
__ https://en.wikipedia.org/wiki/Sneakernet

Note the one-time keys for the *targets* and *bins* roles MAY be safely
generated, used, and deleted during the offline key ceremony. Furthermore,
the *root* keys MAY not be generated during the offline key ceremony itself:
instead, a threshold t of n Python administrators, as discussed above, may sign
independently sign the *root* metadata **after** the offline key ceremony used
to generate all other keys.


How Should Metadata be Generated?
=================================
Expand Down

0 comments on commit 2bf2c95

Please sign in to comment.