Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python Enhancement Proposals

PEP 761 – Deprecating PGP signatures for CPython artifacts

Author:
Seth Michael Larson <seth at python.org>
Sponsor:
Hugo van Kemenade
Discussions-To:
Discourse thread
Status:
Draft
Type:
Process
Created:
08-Oct-2024
Python-Version:
3.14
Post-History:
25-Sep-2024, 09-Oct-2024

Table of Contents

Abstract

Since Python 3.11.0, CPython has provided two verifiable digital signatures for all CPython artifacts: PGP and Sigstore.

PGP’s design requires the maintenance and protection of long-lived private keys by trusted parties. PGP’s security and ergonomics have been criticized by security practitioners for many years now, with the biggest issue being that there were few alternatives for “artifact signing” being proposed or adopted.

Sigstore’s design philosophy has focused on the ergonomics of signing and verifying and uses short-lived keys with strongly-bound human-readable identities via OpenID Connect. Sigstore has both development and adoption momentum, seeing adoption by PyPI, NPM, Homebrew, and GitHub, among other ecosystems.

This PEP proposes to move CPython to using Sigstore exclusively for signing artifacts through a deprecation and eventual discontinuance of providing PGP signatures with new release managers.

Motivation

CPython’s releases are release-manager-centric, where a single person maintains multiple CPython releases from pre-release to end-of-life over the course of many years.

Requiring release managers to maintain and protect PGP private keys for seven or more years is an unnecessary burden in the new age of ergonomic and ephemeral signing keys. Comparatively, Sigstore only requires release managers to click a button during the release process to OAuth sign-on to their identity provider. Maintaining the integrity of accounts on identity providers like GitHub is already an expectation of being a Python release manager or core team member, such as through multi-factor authentication and strong unique passwords.

Rationale

Preserve expectations across a Python release

To avoid breaking downstream verifiers, the expectations for verification materials availability SHOULD NOT be changed during a feature release’s lifecycle.

Release managers, not releases

The discontinuation of PGP signatures doesn’t necessarily have to happen on a “release manager boundary”; a new Python release could be a potential boundary.

Because the primary motivation for deprecating PGP is ergonomics, deciding to drop PGP for one release while a release manager still has obligations to provide PGP signatures for other releases for multiple years isn’t much savings of effort.

A new release manager also represents a new PGP public key that downstream verifiers need to adopt. By choosing to make the change during this period, this minimizes the breakage to a place in downstream maintenance where a change will already be necessary.

Gordian knot of signing methods and verifiers

CPython providing both PGP and Sigstore signatures concurrently creates a “Gordian knot” where verifiers are disincentivized to migrate to a new signature method due to the continued and expected availability of an existing signature method, thus propagating the apparent demand for maintaining the existing signature method.

This situation slows down the adoption of new signature methods like Sigstore for both signature-producing projects and signature-verifying ecosystems by not creating a “need” to automate and integrate the signature method into verifier tooling.

By changing the expectation of what future signature methods will be available, the incentive-knot can be broken by spurring the adoption of the new signature method in downstream tooling. This change to verifier tooling also makes other upstream projects able to migrate to publishing only Sigstore signatures, resulting in a positive feedback loop of adoption.

Specification

Because PGP keys are tied to a release manager identity, the change to availability of PGP signatures will be tied to release managers instead of individual releases (3.13, 3.14, etc). This PEP both deprecates and proposes a discontinuation timeline for PGP signatures.

Deprecation and discontinuation of PGP signatures

This PEP deprecates PGP signatures for future CPython releases and recommends verifiers to adopt Sigstore to verify CPython artifacts as an alternative to PGP.

This PEP also removes the expectation that PGP signatures be published by future release managers that don’t already maintain a stable Python release. At the time of writing this would be Hugo van Kemenade, as 3.14 is the next Python version without a stable release.

Releases which already have a stable release (3.13, 3.12, 3.11, etc) are not affected and will continue to provide PGP signatures for artifacts until they are end-of-life. All existing PGP signatures will continue to work as expected.

Delaying discontinuation of PGP signatures

This PEP provides a mechanism to delay the discontinuation of PGP signatures from active and upcoming CPython releases in case of extraordinary circumstances. Deprecation of PGP signatures can’t be changed without a superseding PEP.

The Steering Council MAY at a future date after this PEP’s acceptance decide to delay the discontinuation of PGP signatures to a future CPython release. If the Steering Council decides to delay the discontinuation of PGP signatures then all active release managers MUST provide PGP signatures for their covered CPython artifacts for the remainder of their tenure as a release manager. This includes all steps required to do so, such as generating a new PGP key and publishing their identity to python.org.

The discontinuation of PGP signatures then is automatically scheduled for the next release manager without a stable release, to be highlighted in the Steering Council decision.

Backwards Compatibility

This proposal would remove the ability to verify future CPython artifacts using PGP. Any downstream verifiers using PGP for CPython artifacts would need to either start using Sigstore, verify their source code of CPython through other means, or stop verification altogether for future CPython releases.

Security Implications

PGP and Sigstore have different security models, so by removing PGP signatures this means that all users only have the option to rely on the security model provided by Sigstore.

In general, the security model required for artifact signatures is being able to detect whether a given artifact is from the expected source and hasn’t been modified, regardless of the security or integrity of the hosting service (in CPython’s case: python.org/downloads).

Sigstore’s security model depends more on centralized infrastructure compared to PGP, such as the “public good” signature transparency log (Rekor), certificate authority and transparency log (Fulcio), and the security of OpenID Connect identity providers like Google and GitHub.

CPython’s development already depends on the security of some of these services and the others are better resourced than any individual release manager to provide long-term public key management.

How to Teach This

CPython already documents how to verify artifacts using Sigstore based on the pre-published identities of release managers. Documentation will be updated to indicate the deprecation and future expectations of PGP signatures.

Verifying signatures of CPython artifacts isn’t something we should expect from new Python users. Instead, Sigstore is more likely to be a part of a downstream integrator’s build pipeline such as a Linux distro, Homebrew, pyenv, or others that programmatically fetch and build CPython from source.

Rejected Ideas

Continue publishing PGP signatures indefinitely

Being a release manager is already a difficult, time-consuming, and long-term commitment that is typically done on a volunteer basis. Thus we see removal of PGP key management duties as a step towards reducing burnout and stress of future release managers and improving the sustainability of CPython.

Appendix

Support for offline verification

During the pre-PEP discussion, there was a question of whether offline verification was supported by Sigstore. Using a Sigstore bundle (.sigstore) file, Sigstore clients support verifying the artifact completely offline.

Using offline verification with Sigstore requires disabling root of trust updates and “pinning” a root of trust in a file to use during verification.

Pinning a root of trust means signatures made after a new root of trust is established would no longer be able to verify using a “pinned” previous root of trust. New roots of trust are expected to be rare events, such as when the root of trust is compromised, and in this case verifiers would want signatures to fail to verify.

Offline verification also makes revocation checks impossible, but this is similar to PGP’s model where revocation of keys requires an online lookup.

Barring rare events like root of trust compromise, using offline verification with Sigstore doesn’t impose additional operations requirements to verifiers.

Support for a pre-compiled executable for verification

During discussion there were requests for a pre-compiled executable that could be used for verifying Sigstore bundles without needing to either install a Go build toolchain to build sigstore-go from source or already have a working Python installation for sigstore-python.

Cosign is another Sigstore project that provides pre-compiled standalone binaries and supports verifying bundles offline:

# Download Cosign
wget https://github.com/sigstore/cosign/releases/download/v2.4.1/cosign-linux-amd64

# For offline verification, also need the Root of Trust. Can be grabbed
# from GitHub at: https://github.com/sigstore/root-signing/blob/main/targets/trusted_root.json
wget https://raw.githubusercontent.com/sigstore/root-signing/refs/heads/main/targets/trusted_root.json

# Download CPython artifacts
wget https://www.python.org/ftp/python/3.13.0/Python-3.13.0.tgz
wget https://www.python.org/ftp/python/3.13.0/Python-3.13.0.tgz.sigstore

./cosign-linux-amd64 verify-blob \
  --new-bundle-format \
  --certificate-oidc-issuer 'https://accounts.google.com' \
  --certificate-identity 'thomas@python.org' \
  --bundle ./Python-3.13.0.tgz.sigstore \
  # --offline and --trust-root optional for offline verification
  --offline \
  --trust-root ./trusted_root.json \
  ./Python-3.13.0.tgz

Source: https://github.com/python/peps/blob/main/peps/pep-0761.rst

Last modified: 2024-10-15 20:40:15 GMT