pkg-verify-sig(1)
NAME
pkg-verify-sig - verify the signature on a package manifest
SYNOPSIS
pkg verify-sig manifest
DESCRIPTION
Every manifest ends in a signature block: the algorithm, the public key that signed it, and the signature itself. This command reads a manifest, decodes that key and that signature, and checks the signature over the manifest.
What does it actually prove?
Less than you'd hope. This checks that the manifest is intact, not who signed it. The manifest names its own key, and that's the key it gets checked against. A manifest signed by an attacker's key verifies perfectly.
So use it to answer "is this file intact, and which key claims it". Whether that's the right key is a separate question, and other parts of the system answer it:
- For a remote repository, the TUF trust anchor does; see pkg-repo(1) and pkg-repos.d(5).
- For a composition,
pkg compose --trust-keydoes. It fails any manifest that isn't signed by a key you named. - For a published build, pkg-provenance(1) does, by verifying the signed record that binds the outputs to their inputs.
What is signed?
Not the bytes of the file. The manifest is parsed and put back into its canonical form, with the signature value cleared, and that's what the signature covers. The algorithm and the public key are part of it, so a signature is bound to the key that made it.
That means a comment, extra whitespace or reordered keys don't break the signature. They don't change what the manifest says. Change any value, though, a release number, a file's hash, a path, and it fails.
OPTIONS
No options of its own. All global options apply; see pkg(1).
OUTPUT
signature valid: /srv/build/pkg-meta (pubkey 3a7f...c2e1)
On failure it exits 1, with a message on stderr saying what went wrong: a manifest that doesn't parse, a public key or signature that doesn't decode, an algorithm other than ed25519, or a signature that doesn't verify:
error: sign: signature verification failed
JSON
{ "ok": true, "manifest": "/srv/build/pkg-meta", "public_key": "3a7f...c2e1", "valid": true }
EXAMPLES
One manifest
pkg verify-sig /srv/repo/Common/pkgs/gzip/bin/1.13/4/x86_64/pkg-meta
Installed manifests work the same way:
pkg verify-sig /var/lib/pkg/installed/gzip/bin/manifest.toml
Which key signed it
pkg --json verify-sig \ /srv/repo/Common/pkgs/gzip/bin/1.13/4/x86_64/pkg-meta \ | jq -r .public_key
A whole repository
find /srv/repo/Common/pkgs -name pkg-meta -print0 \ | xargs -0 -n1 pkg verify-sig > /dev/null
Or, keeping only the failures:
find /srv/repo/Common/pkgs -name pkg-meta -print0 \ | while IFS= read -r -d '' m; do pkg verify-sig "$m" > /dev/null 2>&1 || echo "FAIL $m" done
Is it all signed by one key?
find /srv/repo/Common/pkgs -name pkg-meta -print0 \ | xargs -0 -n1 pkg --json verify-sig \ | jq -r .public_key | sort -u
Two lines during a key rotation is expected. Two lines any other time is worth looking into.
After signing
pkg sign /srv/build/gzip/bin/pkg-meta --key /etc/pkg/keys/release.key pkg verify-sig /srv/build/gzip/bin/pkg-meta
A bundle somebody handed you
mkdir /tmp/scratch && tar -xf /mnt/usb/console.pkgtar -C /tmp/scratch find /tmp/scratch/pkgs -name pkg-meta -print0 \ | xargs -0 -n1 pkg --json verify-sig | jq -r .public_key | sort -u
Now compare that key against the one you expected. That's the step that turns "the file is intact" into "the file is ours".
Seeing tampering get caught
m=/tmp/scratch/pkgs/bash/bin/5.3/4/x86_64/pkg-meta sed -i 's/release = 4$/release = 5/' "$m" pkg verify-sig "$m"
- One value changed, and the signature fails
Appending a comment to the same file would not have failed it. A comment isn't part of what's signed.
The whole trust chain for one package
pkg verify-sig /srv/repo/Common/pkgs/gzip/bin/1.13/4/x86_64/pkg-meta pkg provenance verify gzip pkg verify gzip
In order: the manifest is intact and names a key, the build is bound to signed inputs whose hashes check out, and the files on disk match the manifest.
EXIT STATUS
0 when the signature verifies, 1 otherwise.
SEE ALSO
pkg(1), pkg-sign(1), pkg-verify(1), pkg-provenance(1), pkg-info(1), pkg-repo(1), pkg-repos.d(5), pkg-repository-layout(7)
docs/design/trust.md, docs/components/pkg-sign.md