PEP: 761 Title: Deprecating PGP signatures for CPython artifacts Author:
Seth Michael Larson <seth@python.org> Sponsor: Hugo van Kemenade
Discussions-To:
https://discuss.python.org/t/pep-761-deprecating-pgp-signatures-for-cpython-artifacts/67180
Status: Draft Type: Process Created: 08-Oct-2024 Python-Version: 3.14
Post-History: 25-Sep-2024, 09-Oct-2024

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

Copyright

This document is placed in the public domain or under the
CC0-1.0-Universal license, whichever is more permissive.