Verify cosign signatures in go using sigstore/sigstore


After integrating cosign into the release process of Constellation’s CLI, I also wanted to improve the supply chain security of our metadata that are used for attestation.

Using cosign CLI for signing and verifying blobs or container images is a well documented process. The sigstore/sigstore project is the common go library for all sigstore services and clients and has documented public functions, but I was unable to find examples on how to use them together.

Here is a working example to get you started quickly:

#!/bin/bash
set -e
echo "Any artifact we want to distribute." > artifact.txt
export COSIGN_PASSWORD=$(openssl rand -hex 32)
cosign generate-key-pair
cosign sign-blob --key cosign.key artifact.txt > artifact.txt.sig
cosign verify-blob --key cosign.pub --signature $(cat artifact.txt.sig) artifact.txt
package main

import (
	"bytes"
	"crypto"
	"encoding/base64"
	"fmt"

	"github.com/sigstore/sigstore/pkg/cryptoutils"
	"github.com/sigstore/sigstore/pkg/signature"
)

// VerifySignature checks if the signature of content can be verified
// using publicKey.
// signature is expected to be base64 encoded.
// publicKey is expected to be PEM encoded.
func VerifySignature(content, sig, publicKey []byte) error {
	sigRaw := base64.NewDecoder(base64.StdEncoding, bytes.NewReader(sig))

	pubKeyRaw, err := cryptoutils.UnmarshalPEMToPublicKey(publicKey)
	if err != nil {
		return fmt.Errorf("unable to parse public key: %w", err)
	}
	if err := cryptoutils.ValidatePubKey(pubKeyRaw); err != nil {
		return fmt.Errorf("unable to validate public key: %w", err)
	}

	verifier, err := signature.LoadVerifier(pubKeyRaw, crypto.SHA256)
	if err != nil {
		return fmt.Errorf("unable to load verifier: %w", err)
	}

	if err := verifier.VerifySignature(sigRaw, bytes.NewReader(content)); err != nil {
		return fmt.Errorf("unable to verify signature: %w", err)
	}

	return nil
}

func main() {
	content := "Any artifact we want to distribute.\n"
	sig := "MEQCIEJhWr+c5bCAcWv5gNsUn4Fkjo+qV2ss59SLuS0Gmh8LAiBPoLGy8KkQcV+rDjGN757WE2QS1ujnkuScd9+md+Fzhw=="
	pubKey := "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE+3ZBZe8lNJ4oA5TAPCIQX3IMStdi\nUO6/xsAoZQc3lEKxFu+r1QDWyMS8D/fqLUbMoIW1lPPJV1M3jPiBAhhqPA==\n-----END PUBLIC KEY-----"

	if err := VerifySignature([]byte(content), []byte(sig), []byte(pubKey)); err != nil {
		fmt.Println("Verification failed!", err)
	} else {
		fmt.Println("Verification success!")
	}
}