Home > npm Package Signing at the IAB PQ Workshop

2026 Oct

In October 2026 the IAB got together various practitioneers who are interested in accelerating the deployment of post-quantum (maybe better referred to as quantum-resistant) authentication to talk about strategies tried so far, roadblocks encountered, and working together to identify next steps.

There's more information on the homepage of the IAB PQ Workshop, where you can find the paper I submitted on the topic of the path npm is considering for PQC package signing, and you can also find the slides I presented to set the stage for the session on "Code Signing, Keys and Hardware", which are also below with commentary.

We're here to talk about npm's work-in-progress to transition package signing to post-quantum cryptography (PQC).

We'll start out by talking about how npm packages are signed and verified today, what we're thinking this will look like with PQC, and a recap of the open questions we have for discussion.

But before we talk about how packages are signed today; let's talk for a second about what makes package signing and verifying successful in the first place. Of course signing the package prevents it from being tampered with as it's distributed, but schemes for signing packages are not new. However, many previous attempts at package signing have failed when they require individual users to correctly provision, secure, and retire private key material (see for example PyPI's 2023 post on removing PGP signature support.

In response, current package signing schemes make use of the workload identity available in the cloud build system. We'll use GitHub Actions in this example, but many cloud build systems either have or are adding workload identity as well. This workload identity is exchanged with Sigstore's public good service, which as we'll see returns a package signature.

The last party in the signing flow is the package registry. We'll use npm in this example, but this flow is supported by many package registries, including PyPI, Maven Central, RubyGems, and others.

Here's what the data flow between these parties looks like. In GitHub Actions the workload identity is a JWT signed with RSA-2048, and the Sigstore public good instance returns a X.509 certificate containing a ECDSA P-348 signature, as well as a custom transparency log entry that includes a ECDSA P-256 signature. The X.509 certificate and the custom transparency log entry together is referred to as the Sigstore bundle, and at the end of the build the built package and the Sigstore bundle is sent to the registry.

On the verify side we have a slightly different set of parties. Here the verification is being driven by the npm CLI. It will get the package and Sigstore bundle from the npm registry, but it needs the public key material with which to verify those signatures. That content comes from the Sigstore trust root, and uses The Update Framework (TUF) to check for updated verification material each day.

The keys used for signing are actually online intermediate keys, who themselves are signed periodically by a set of people, geographically distributed, who are the key holders.

Here's the dataflow for verifying today. The key holders sign periodically sign the trust root with Yubikey hardware keys that use ECDSA P-256. The keys that they are signing live in a cloud KMS that produces ECDSA P-256 signatures, and as mentioned the signed material ("bundle") is distributed from the registry to the npm CLI.

Here's what signing would look like with PQC. Cloud build systems should transition their JWTs to be signed with some version of ML-DSA (details on which version of ML-DSA and how to transition to be determined). The Sigstore bundle will no longer contain a X.509 certificate, and instead will use an identity and transparency log entry that's a community-maintained C2SP specification.

For verification we will need a hardware key that supports some version of ML-DSA. The keys in the trust root will come from cloud HSMs, which already have broad support for ML-DSA. For some time there will be classical cryptography Sigstore bundles alongside PQC Sigstore bundles being provided by the registry.

We need to determine how the registry decides which bundles to distribute to the CLI, and how to dynamically update the CLI verification policy in a secure way, so we don't need to wait until we release a new version of the CLI.

So to recap, we need help figuring out what PQC JWTs look like, and how to transition OIDC clients. We also need PQC hardware keys for the keyholders to periodically sign the KMS keys in use. If you'd like to contribute directly, come to the Sigstore and TUF community meetings, and help us finish these specifications (after which we will accept pull requests!) Lastly, let us know if there are problems we haven't yet thought of that we should be planning for.