sigstore/cosign

`cosign.VerifyImageAttestations` fails to verify attestations, returns `unable to verify bundle: matching bundle to payload: invalid kind value: "dsse"`"

justpolidor opened this issue · 1 comments

Description
I am coding an application that verifies attestations but when calling the func verifiedAttestations, _, err := cosign.VerifyImageAttestations(ctx, ref, &cosign.CheckOpts...) I get :

unable to verify bundle: matching bundle to payload: invalid kind value: "dsse".

The code is like this:

func processAttestations(ctx context.Context, keys []string) ([]externaldata.Item, error) {
	results := []externaldata.Item{}
	verifier, err := loadPublicKeyVerifier()
	if err != nil {
		return nil, err
	}

	for _, key := range keys {
		ref, err := name.ParseReference(key)
		if err != nil {
			return appendError(results, key, fmt.Sprintf("Error parsing reference: %v", err))
		}

		verifiedAttestations, _, err := cosign.VerifyImageAttestations(ctx, ref, &cosign.CheckOpts{
			SigVerifier:   verifier,
			ClaimVerifier: cosign.IntotoSubjectClaimVerifier, // Do I need this?
		})

		log.Printf("Verified attestations %v ", verifiedAttestations)

		if err != nil {
			return appendError(results, key, fmt.Sprintf("Failed to verify attestation: %v", err))
		}
[...]

func loadPublicKeyVerifier() (signature.Verifier, error) {

       pubKeyBytes, err := os.ReadFile("/etc/cosign/cosign.pub")
	
	if err != nil {
		return nil, fmt.Errorf("error reading public key file: %v", err)
	}

	block, _ := pem.Decode(pubKeyBytes)
	if block == nil || block.Type != "PUBLIC KEY" {
		return nil, fmt.Errorf("failed to decode PEM block containing public key or incorrect type")
	}

	pubKey, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return nil, fmt.Errorf("error parsing PKIX public key: %v", err)
	}

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

	return verifier, nil
}
[...]

The attestation is generated in this way:

trivy image --format cosign-vuln --output vuln.json docker.io/jpolidor/goat-jdk
cosign attest --key $HOME/.cosign/cosign.key --type vuln --predicate vuln.json docker.io/jpolidor/goat-jdk:latest

and then I can verify it without issues by calling:

cosign verify-attestation --key $HOME/.cosign/cosign.key --type vuln docker.io/jpolidor/goat-jdk:latest

that returns a json like this:

{"payloadType":"application/vnd.in-toto+json", "payload":"ey[...]","signatures":[{"keyid":"","sig":"MEQCIAb[...]"}]}

If I run oras manifest fetch docker.io/jpolidor/goat-jdk:sha256-3c0cf95856d49303347b9f8aa352ccad9e97f138384577c3334d80751f3ebfe6.att | jq

I get the detail of the attestation and I can see that the bundle is enclosed in a DSSE Envelope:

{
  "schemaVersion": 2,
  "mediaType": "application/vnd.oci.image.manifest.v1+json",
  "config": {
    "mediaType": "application/vnd.oci.image.config.v1+json",
    "size": 233,
    "digest": "sha256:9c0341148dfda40e4c6e869eb63050d46d3324d0008be876d121c6cc2e6bb778"
  },
  "layers": [
    {
      "mediaType": "application/vnd.dsse.envelope.v1+json",
      "size": 1953032,
      "digest": "sha256:c0434af57cd9592ba271a3ba39618eef16f5369d0c1c4414ce0b5af740eaef45",
      "annotations": {
        "dev.cosignproject.cosign/signature": "",
        "dev.sigstore.cosign/bundle": "{\"SignedEntryTimestamp\":\"MEUCIFcsHduI8cdPyQ0gaTYMsOUxxtIJp20m8uiqFAtS2pchAiEAofj6/j1WRp17vSnKKMslQfK6p2G7ji31Lc3fphsjBpg=\",\"Payload\":{\"body\":\"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiZHNzZSIsInNwZWMiOnsiZW52ZWxvcGVIYXNoIjp7ImFsZ29yaXRobSI6InNoYTI1NiIsInZhbHVlIjoiYzA0MzRhZjU3Y2Q5NTkyYmEyNzFhM2JhMzk2MThlZWYxNmY1MzY5ZDBjMWM0NDE0Y2UwYjVhZjc0MGVhZWY0NSJ9LCJwYXlsb2FkSGFzaCI6eyJhbGdvcml0aG0iOiJzaGEyNTYiLCJ2YWx1ZSI6ImQ1Yjc1MzYyZTQwZjY5Yjk0N2VhNjlkM2IzNzdjODc0ZjcxN2IxMDJlOTNhYjAxNGVhYjJhZDE4YmJlMWJlYWEifSwic2lnbmF0dXJlcyI6W3sic2lnbmF0dXJlIjoiTUVRQ0lBYjd4U254dHVwSkloV3E1VmEyTUpFMzJaNndlQ0hQbXVPTUpOYWZFdGRHQWlBTGhlTHJLNWlhNlhzdmd3dDd6b2Z0QzVEVHEwenRMU0xjaU4zbmZiTWNIZz09IiwidmVyaWZpZXIiOiJMUzB0TFMxQ1JVZEpUaUJRVlVKTVNVTWdTMFZaTFMwdExTMEtUVVpyZDBWM1dVaExiMXBKZW1vd1EwRlJXVWxMYjFwSmVtb3dSRUZSWTBSUlowRkZXVGRKUzBjeWNVOVRaMUV6SzFWTVl6VjJWSE5EZGpoVVprSlBkd3A0WVhwVE5uVktjelJwY21Gc1RtcHhSSFpsTkZWcVJqUjVkVlJ5UVUweVZYaDNlbU41WjFWS2VXSkVlV28yTlhWeFQybGtSak5pZFZCUlBUMEtMUzB0TFMxRlRrUWdVRlZDVEVsRElFdEZXUzB0TFMwdENnPT0ifV19fQ==\",\"integratedTime\":1714076849,\"logIndex\":88725166,\"logID\":\"c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d\"}}",
        "predicateType": "https://cosign.sigstore.dev/attestation/vuln/v1"
      }
    }
  ]
}

Am I missing something here?

Version
Cosign CLI version:

GitVersion:    2.2.4
GitCommit:     fb651b4ddd8176bd81756fca2d988dd8611f514d
GitTreeState:  "clean"
BuildDate:     2024-04-10T21:57:27Z
GoVersion:     go1.22.2
Compiler:      gc
Platform:      darwin/arm64

Go Module version for github.com/sigstore/sigstore: v1.8.3

Found the culprit: I was using

github.com/sigstore/cosign v1.3.8

instead of

github.com/sigstore/cosign/v2 v2.2.4.

The old version were confusing the DSSE envelope and the InToto type.