How to Verify File Signatures with Rekor or curl
You can use the rekor-cli
tool to verify signatures of artifacts other than container images. For example, you can verify the signature of a binary file that has been signed using a keyless signature as part of its release process. By querying the Rekor transparency log, you can verify that the binary file you downloaded matches the one that was signed using Cosign. If you prefer, you can also query the Rekor API directly using curl
.
In this tutorial, we’ll demonstrate how to verify a binary file using rekor-cli
and curl
. We’ll use apko as an example, since all its releases are signed with Cosign. The methods in this tutorial apply to any blob file that Cosign has signed with a keyless signature.
Preparation
To follow up with all commands in this tutorial, you need to have curl
and the rekor-cli
tool installed. You can install it by following our How to Install the Rekor CLI guide. Alternatively, you can follow the official docs for instructions on how to build Rekor CLI from source. You also need to have the jq
utility installed to parse the output of rekor-cli
and curl
.
Download the Example File
We’ll use the apko_0.20.1_linux_amd64.tar.gz
tar archive from the apko GitHub Release v0.20.1 page for the examples in this tutorial. You can download the file using curl
or your browser:
curl -L -O https://github.com/chainguard-dev/apko/releases/download/v0.20.1/apko_0.20.1_linux_amd64.tar.gz
Then, set up a shell variable to store the SHA256 hash of the apko_0.20.1_linux_amd64.tar.gz
release file:
SHASUM=$(shasum -a 256 apko_0.20.1_linux_amd64.tar.gz |awk '{print $1}')
You can verify that the variable has been set correctly by running:
echo $SHASUM
You should get output similar to this:
442d8baafc0c3a873b21a3add32f5c65f538fb5cbcf4a4a69ba098a2b730c5d2
With this environment variable set up, you can proceed to the rest of this guide.
Verifying a Binary with rekor-cli
We’ll now use the rekor-cli
tool to verify the signature of the apko_0.20.1_linux_amd64.tar.gz
binary file. First, we’ll search the Rekor log for the hash of the binary file. Then, we’ll retrieve the Rekor log entry for the hash and extract the signature and public key to verify the binary file.
To search for the hash in the Rekor log using rekor-cli
, run the following command:
rekor-cli search --sha "${SHASUM?}"
You will receive output like the following:
Found matching entries (listed by UUID):
108e9186e8c5677a8d6736bdd79170adf94bd127aea751274d1d62504e88b058af7552d91dea0f26
Set a shell variable called UUID
to the returned entry:
UUID="108e9186e8c5677a8d6736bdd79170adf94bd127aea751274d1d62504e88b058af7552d91dea0f26"
Now you can use the returned UUID to retrieve the associated Rekor log entry:
rekor-cli get --uuid "${UUID?}"
This will return a long payload that you can parse using jq
in order to extract the relevant fields. You can skip to the Fetching a Signature and Public Certificate section to learn how to verify your binary matches what is in the Rekor log.
Verifying a Binary with curl
To query the Rekor API directly for the hash using curl
, you’ll need to make a POST request to the https://rekor.sigstore.dev/api/v1/index/retrieve
endpoint, passing along the hash as a JSON payload. You can then use the returned UUID to retrieve the associated Rekor log entry.
Run the following command to query the Rekor API for the hash:
curl -X POST -H "Content-type: application/json" 'https://rekor.sigstore.dev/api/v1/index/retrieve' --data-raw "{\"hash\":\"sha256:$SHASUM\"}"
You will get output like this:
["108e9186e8c5677a8d6736bdd79170adf94bd127aea751274d1d62504e88b058af7552d91dea0f26"]
Next, set a shell variable called UUID
to the returned entry:
UUID="108e9186e8c5677a8d6736bdd79170adf94bd127aea751274d1d62504e88b058af7552d91dea0f26"
Now you can use the returned UUID to retrieve the associated Rekor log entry:
curl -X GET "https://rekor.sigstore.dev/api/v1/log/entries/${UUID?}"
This will return a long payload that you can parse using jq
in order to extract the relevant fields. To verify the signature and decode the data, you’ll also need base64
and openssl
.
Fetching a Signature and Public Certificate
If you would like to extract the signature and public key to verify your binary matches what is in the Rekor log, you will need to parse the output. You will need to use tools like base64
to decode the data, jq
to extract the relevant fields, and openssl
to verify the signature.
If you’re using rekor-cli
The following commands will fetch the Rekor entry for a release using rekor-cli
, parse and extract the signature and public certificate using jq
, and decode it using base64
:
rekor-cli get --uuid "${UUID?}" --format json \
| jq -r '.Body .HashedRekordObj .signature .content' \
| base64 -d > apko_0.20.1_linux_amd64.tar.gz.sig
rekor-cli get --uuid "${UUID?}" --format json \
| jq -r '.Body .HashedRekordObj .signature .publicKey .content' \
| base64 -d > apko_0.20.1_linux_amd64.tar.gz.crt
If you’re using curl
The following commands will fetch the Rekor entry for a release using curl
, parse and extract the signature and public certificate using jq
, and decode it using base64
:
curl -s -X GET "https://rekor.sigstore.dev/api/v1/log/entries/${UUID?}" \
| jq -r '.[] | .body' \
| base64 -d |jq -r '.spec .signature .content' \
| base64 -d > apko_0.20.1_linux_amd64.tar.gz.sig
curl -s -X GET "https://rekor.sigstore.dev/api/v1/log/entries/${UUID?}" \
| jq -r '.[] | .body' \
| base64 -d |jq -r '.spec .signature .publicKey .content' \
| base64 -d > apko_0.20.1_linux_amd64.tar.gz.crt
Verifying a signature using openssl
After running both commands from the previous section and whether you used rekor-cli
or curl
, you should have two new files in your current directory: apko_0.20.1_linux_amd64.tar.gz.sig
and apko_0.20.1_linux_amd64.tar.gz.crt
. These are the signature and public certificate files for the apko release, respectively. We can now use openssl
to verify the binary file against the signature.
First, extract the public key portion of the apko_0.20.1_linux_amd64.tar.gz.crt
certificate file:
openssl x509 -in apko_0.20.1_linux_amd64.tar.gz.crt -noout -pubkey > apko_0.20.1_linux_amd64.tar.gz.pubkey.crt
Now you can use openssl
to verify the signature against your local apko binary. Run the following command:
openssl sha256 -verify apko_0.20.1_linux_amd64.tar.gz.pubkey.crt -signature apko_0.20.1_linux_amd64.tar.gz.sig apko_0.20.1_linux_amd64.tar.gz
If your apko_0.20.1_linux_amd64.tar.gz
download matches the one that was signed using Cosign, you will receive the following line of output:
Verified OK
This output indicates that your apko_0.20.1_linux_amd64.tar.gz
version is authentic and was signed by the ephemeral private key corresponding to the public certificate that you retrieved from the Rekor log.
Last updated: 2024-12-12 15:22