--- title: How to verify downloaded cosign signatures tags: cosign, images, containers --- We're currently working on a way to update the containers we're using for [Dangerzone](https://dangerzone.rocks) without having to issue new releases. In order to do that, we push new container images to a container registry, and sign them with an hardware key. In addition, we want to do the verification part without issuing HTTP requests, to avoid leaking the fact we're doing the check. Signing the image is pretty straighforward, but verifying wasn't. There are tools for this but they mainly expect you're online and its okay to make network requests. ## Signing the image In order to use `--sk`, you need to compile your own version of `cosign`, which adds suport for hardware keys. ```bash git clone https://github.com/sigstore/cosign.git cd cosign make cosign-pivkey-pkcs11key ``` Then, initialize the key.: ```bash cosign piv-tool generate-key # Or in case you want to disable the "touch" requirement cosign piv-tool generate-key --touch-policy=never ``` And sign: ```bash docker login ./cosign sign --sk ghcr.io/almet/dangerzone/dangerzone@sha256:fa948726aac29a6ac49f01ec8fbbac18522b35b2491fdf716236a0b3502a2ca7 ``` You might also need the public key handy. Here is how to get it: ```bash ./dev/cosign/cosign public-key --sk > pub.key ``` ## Verifying the signature First, download the signatures locally and store them in `signature.json` ```bash cosign download signature ghcr.io/almet/dangerzone/dangerzone@sha256:fa948726aac29a6ac49f01ec8fbbac18522b35b2491fdf716236a0b3502a2ca7 > signatures.json ``` Then, we will need to extract the information from this `signatures.json` file, and verify it in two different ways: Either just check the signature against the payload, but bear in mind this won't do all the bells and whistles that come with sigstore / cosign. It will just verify that the signature matches the provided key. ```bash # Extract the payload and the signature cat signatures.json | tail -1 | jq -r .Base64Signature | base64 -d > signature cat signatures.json | tail -1 | jq -r .Payload | base64 -d > payload # Then, verify it with openssl openssl dgst -sha256 -verify pub.key -signature signature payload # Or with cosign cosign verify-blob --key pub.key -signature signature payload ``` If you want (and you probably do) to verify the signature for the payload, the signed entry timestamp for rekor and the integrity of the rest of the properties (Sigstore SET), we will need to convert some of the keys to match the expected ones, and then invoke cosign: ```bash # Convert the signature to a format known by --bundle cat signatures.json | tail -1 | jq -r .Payload | base64 -d > payload cat signatures.json | tail -1 | jq '{base64Signature: .Base64Signature, Payload, cert: .Cert, chain: .Chain, rekorBundle: {SignedEntryTimestamp: .Bundle.SignedEntryTimestamp, Payload: {body: .Bundle.Payload.body, integratedTime: .Bundle.Payload.integratedTime, logIndex: .Bundle.Payload.logIndex, logID: .Bundle.Payload.logID}}, RFC3161Timestamp}' > bundle.json # And then use it when verifying cosign verify-blob --key pub.key --bundle bundle.json payload ``` And :tada:, we've verified the signature offline!