Packages published to the public npm registry are signed to make it possible to detect if the package content has been tampered with.
Signing and verifying published packages protects against an attacker controlling a registry mirror or proxy where they attempt to intercept and tamper with the package tarball content.
Migrating from PGP to ECDSA signatures
Note: PGP signatures will be deprecated early 2023, in favour of ECDSA registry signatures. More information will soon be provided.
The public npm registry is migrating away from the existing PGP signatures to ECDSA signatures that are more compact and can be verified without extra dependencies in the npm CLI.
Signature verification was previously a multi-step process involving the Keybase CLI, as well as manually retrieving and parsing the signature from the package metadata.
Read more about migrating and verifying signatures using the npm CLI.
Supporting signatures on third-party registries
The npm CLI supports registry signatures and signing keys provided by any registry if the following conventions are followed:
1. Signatures are provided in the package's packument
in each published version within the dist
object:
"dist":{
..omitted..,
"signatures": [{
"keyid": "SHA256:{{SHA256_PUBLIC_KEY}}",
"sig": "a312b9c3cb4a1b693e8ebac5ee1ca9cc01f2661c14391917dcb111517f72370809..."
}],
See this example of a signed package from the public npm registry.
To generate the signature, sign the package name, version and tarball sha integrity: ${package.name}@${package.version}:${package.dist.integrity}
.
The current best practice is to use a Key Management System that does the signing operation on a Hardware Security Module (HSM) in order to not directly handle the private key part, which reduces the attack surface.
The keyid
must match one of the public signing keys below.
2. Public signing keys are provided at registry-host.tld/-/npm/v1/keys
in the following format:
{
"keys": [{
"expires": null,
"keyid": "SHA256:{{SHA256_PUBLIC_KEY}}",
"keytype": "ecdsa-sha2-nistp256",
"scheme": "ecdsa-sha2-nistp256",
"key": "{{B64_PUBLIC_KEY}}"
}]
}
Keys response:
-
expires
: null or a simplified extended ISO 8601 format: YYYY-MM-DDTHH:mm:ss.sssZ
-
keydid
: sha256 fingerprint of the public key
-
keytype
: only ecdsa-sha2-nistp256
is currently supported by the npm CLI
-
scheme
: only ecdsa-sha2-nistp256
is currently supported by the npm CLI
-
key
: base64 encoded public key
See this example key's response from the public npm registry.