Introduction to Witness: Verifying Software Supply Chain Attestations
A practical introduction to Witness: generating keys, recording attestations, signing policy, and verifying a simple Go binary against supply chain requirements.
This is a simple practical walkthrough for getting started with the in-toto/witness project.
Witness is a pluggable framework for software supply chain risk management. It automates, normalizes, and verifies software artifact provenance.
If you want the full official tutorial, start with witness.dev/docs/docs/tutorials/getting-started. This post focuses more on the practical flow.
Create a small Go app
go mod init github.com/manzil-infinity180/hello-world-witness
package main
import "fmt"
func main() {
fmt.Println("hello world!!!!!!")
}
Generate signing keys
openssl genpkey -algorithm ed25519 -outform PEM -out testkey.pem
openssl pkey -in testkey.pem -pubout > testpub.pem
At this point your folder should contain go.mod, main.go, testkey.pem, and testpub.pem.
Create a Witness config
run:
signer-file-key-path: testkey.pem
trace: false
verify:
attestations:
- "test-att.json"
policy: policy-signed.json
publickey: testpub.pem
Record a build attestation
witness run --step build -o test-att.json -a slsa --attestor-slsa-export -- go build -o=testapp .
That produces test-att.json, which contains the attestation payload. If you want to inspect it, decode the base64 payload:
cat test-att.json | jq -r .payload | base64 -d | jq
You can also store and retrieve attestations through Archivista.
Create and sign a policy
The next step is defining which attestations and functionaries are required for your build step. The policy JSON can look like:
{
"steps": {
"build": {
"name": "build",
"attestations": [
{ "type": "https://witness.dev/attestations/material/v0.1", "regopolicies": [] },
{ "type": "https://witness.dev/attestations/command-run/v0.1", "regopolicies": [] },
{ "type": "https://witness.dev/attestations/product/v0.1", "regopolicies": [] }
]
}
}
}
After filling in the public key id and key content, sign the policy:
witness sign -f policy.json --signer-file-key-path testkey.pem --outfile policy-signed.json
Verify the binary
witness verify -f testapp -a test-att.json -p policy-signed.json -k testpub.pem
That is the basic loop: build, attest, sign policy, and verify.
More posts
Alpine Linux Package Management + Practice
Jul 28, 2025 6 min readA hands-on overview of Alpine package management with apk, including update, add, delete, search, inspect, verify, and graphing package dependencies.
CRUD K8s Deployment Implementation using client-go and k8s io api
Feb 20, 2025 6 min readA practical walkthrough for implementing create, read, update, and delete operations for Kubernetes Deployments using client-go, Gin, and YAML input handling.
Creating an Alpine package for a Go application — APKBUILD
Aug 27, 2025 4 min readA practical walkthrough for packaging a simple Go application for Alpine Linux using APKBUILD, from setup and checksums to building and submitting.
Written by Rahul Vishwakarma — this is the first-party home for this article on rahulxf.com. A copy also lives on Medium .