Skip to content

Instantly share code, notes, and snippets.

@salrashid123
Last active March 7, 2024 12:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save salrashid123/7efde8ebb2c11c34727e9f934bd026fb to your computer and use it in GitHub Desktop.
Save salrashid123/7efde8ebb2c11c34727e9f934bd026fb to your computer and use it in GitHub Desktop.
Cosign sign and verify with annotations

Cosign signature and verification

start with image

export IMAGE_DIGEST=docker.io/salrashid123/myimage@sha256:9ec06569f1c169d4c5b380c64b803d287468d95429dab4e4449842f93a252049

generate keypair

$ cosign generate-key-pair

this sample uses the private key showed at the end

with fingerprint

$ openssl ec  -pubin -inform PEM -in cosign.pub -outform DER | openssl dgst -sha256 | cut -d" " -f2
read EC key
writing EC key
2b20bfe7bb76a7405dfcc75193e7768c41c1fffa28aeabc15e7ad21b0fdc9a89

sign

## get public key to attach to annotation
$ PUB=$(cat cosign.pub | openssl base64)
$ PUB=$(echo $PUB | tr -d '[:space:]' | sed 's/[=]*$//')
$ echo $PUB

$ COSIGN_REPOSITORY=docker.io/salrashid123/myimage

$ cosign sign  --key cosign.key \
  -a dev.cosignproject.cosign/sigalg=ECDSA_P256_SHA256 \
  -a dev.cosignproject.cosign/pub=$PUB --tlog-upload=false  --upload=true $IMAGE_DIGEST 

### (passphrase `123456`)

$ cosign verify --insecure-ignore-tlog=true --key=cosign.pub  $IMAGE_DIGEST | jq '.'

Verification for index.docker.io/salrashid123/myimage@sha256:9ec06569f1c169d4c5b380c64b803d287468d95429dab4e4449842f93a252049 --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - The signatures were verified against the specified public key
[
  {
    "critical": {
      "identity": {
        "docker-reference": "index.docker.io/salrashid123/myimage"
      },
      "image": {
        "docker-manifest-digest": "sha256:9ec06569f1c169d4c5b380c64b803d287468d95429dab4e4449842f93a252049"
      },
      "type": "cosign container image signature"
    },
    "optional": {
      "dev.cosignproject.cosign/pub": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFMXY3UXFmcGlsVzdNMGhQS2g5QnJjd1NjT05OMQo5cm1IaDR5QVJVV2t4V0s0T3NOZ1FHZlErMTVTYnJrMHRsc1I0c2cyNmdhTHVIZ1A4S0ZzWEJIN0R3PT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg",
      "dev.cosignproject.cosign/sigalg": "ECDSA_P256_SHA256"
    }
  }
]

## use skopeo to inspect the signature
$ skopeo inspect --raw docker://$(cosign triangulate --type=signature $IMAGE_DIGEST) | jq -r

{
  "schemaVersion": 2,
  "mediaType": "application/vnd.oci.image.manifest.v1+json",
  "config": {
    "mediaType": "application/vnd.oci.image.config.v1+json",
    "size": 233,
    "digest": "sha256:5da2a409c793152d0c60272c212ba07d3e26b269745035265523bffe15042ad5"
  },
  "layers": [
    {
      "mediaType": "application/vnd.dev.cosign.simplesigning.v1+json",
      "size": 575,
      "digest": "sha256:c4b23792287419c78695c260c7a17f1c8ec5f661b16be14ce8e696398073beac",
      "annotations": {
        "dev.cosignproject.cosign/signature": "MEUCIAoXDplWGo0Tn2K1E/Ny2kiTHhdN1+i06d7Pu/FVN1EkAiEA2ggnIc7AVnPcmM5R/7w1hNshpOfpY0d7GJ3+bJJwcSA="
      }
    }
  ]
}

Attest

use predicates values to set

$ cat predicates.json 
{ "foo":"bar"}

and a rego (to validate with)

$ cat policy.rego 
package signature

import data.signature.verified

default allow = false

allow {
    input.predicateType == "https://cosign.sigstore.dev/attestation/v1"

    predicates := json.unmarshal(input.predicate.Data)
    predicates.foo == "bar"

Now attest

$ cosign attest  --tlog-upload=false --key cosign.key --predicate=predicates.json $IMAGE_DIGEST

## use skopeo to inspect the attestation
$ skopeo inspect --raw docker://$(cosign triangulate --type=attestation $IMAGE_DIGEST) | jq -r

{
  "schemaVersion": 2,
  "mediaType": "application/vnd.oci.image.manifest.v1+json",
  "config": {
    "mediaType": "application/vnd.oci.image.config.v1+json",
    "size": 233,
    "digest": "sha256:dda6106d75509a5296c3c1e89e49c5b6c5f94322be4d8336e8ed8813bd0ca8a8"
  },
  "layers": [
    {
      "mediaType": "application/vnd.dsse.envelope.v1+json",
      "size": 632,
      "digest": "sha256:d98b12f07edd80f40eb67be2235b42d94bc759f1ed98023d19595031dc6c1543",
      "annotations": {
        "dev.cosignproject.cosign/signature": "",
        "predicateType": "https://cosign.sigstore.dev/attestation/v1"
      }
    }
  ]
}


## now verify the attestation using policy.rego

$ cosign verify-attestation --insecure-ignore-tlog=true --key cosign.pub --policy policy.rego  $IMAGE_DIGEST

Verification for docker.io/salrashid123/myimage@sha256:9ec06569f1c169d4c5b380c64b803d287468d95429dab4e4449842f93a252049 --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - The signatures were verified against the specified public key
{
  "payloadType": "application/vnd.in-toto+json",
  "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInByZWRpY2F0ZVR5cGUiOiJodHRwczovL2Nvc2lnbi5zaWdzdG9yZS5kZXYvYXR0ZXN0YXRpb24vdjEiLCJzdWJqZWN0IjpbeyJuYW1lIjoiaW5kZXguZG9ja2VyLmlvL3NhbHJhc2hpZDEyMy9teWltYWdlIiwiZGlnZXN0Ijp7InNoYTI1NiI6IjllYzA2NTY5ZjFjMTY5ZDRjNWIzODBjNjRiODAzZDI4NzQ2OGQ5NTQyOWRhYjRlNDQ0OTg0MmY5M2EyNTIwNDkifX1dLCJwcmVkaWNhdGUiOnsiRGF0YSI6InsgXCJmb29cIjpcImJhclwifSIsIlRpbWVzdGFtcCI6IjIwMjMtMTAtMTBUMTM6MzA6NTFaIn19",
  "signatures": [
    {
      "keyid": "",
      "sig": "MEQCIGy+iCUUBTYJOMD54G0fuxnObrE7vbmxKOOLzbd4YVUVAiBWZvCO3sa5jOlu1c6wxNOFYqkkWo2ASbZl42LSWYIshg=="
    }
  ]
}

finally, expanding the payload shows the predicates are included

{
  "_type": "https://in-toto.io/Statement/v0.1",
  "predicateType": "https://cosign.sigstore.dev/attestation/v1",
  "subject": [
    {
      "name": "index.docker.io/salrashid123/myimage",
      "digest": {
        "sha256": "9ec06569f1c169d4c5b380c64b803d287468d95429dab4e4449842f93a252049"
      }
    }
  ],
  "predicate": {
    "Data": "{ \"foo\":\"bar\"}",
    "Timestamp": "2023-10-10T13:30:51Z"
  }
}

sign without upload

cosign sign --key cosign.key \
  -a dev.cosignproject.cosign/sigalg=ECDSA_P256_SHA256 \
  -a dev.cosignproject.cosign/pub=$PUB --tlog-upload=false \
    --upload=false --output-signature=signature.dat --output-payload=payload.dat  --upload=false $IMAGE_DIGEST 



$ cat signature.dat 
MEUCIQCyv9LMBeJEg636DLIL3cc23WRFOClmYH3ykxSCz4UjDAIgZto0uV0Jy55ZTIFoGcKf3YRqgjhWsORvjo6AeLK17ZE

$ cat payload.dat | jq '.'
{
  "critical": {
    "identity": {
      "docker-reference": "index.docker.io/salrashid123/myimage"
    },
    "image": {
      "docker-manifest-digest": "sha256:9ec06569f1c169d4c5b380c64b803d287468d95429dab4e4449842f93a252049"
    },
    "type": "cosign container image signature"
  },
  "optional": {
    "dev.cosignproject.cosign/pub": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFMXY3UXFmcGlsVzdNMGhQS2g5QnJjd1NjT05OMQo5cm1IaDR5QVJVV2t4V0s0T3NOZ1FHZlErMTVTYnJrMHRsc1I0c2cyNmdhTHVIZ1A4S0ZzWEJIN0R3PT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg",
    "dev.cosignproject.cosign/sigalg": "ECDSA_P256_SHA256"
  }
}

  • cosign.pub
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1v7QqfpilW7M0hPKh9BrcwScONN1
9rmHh4yARUWkxWK4OsNgQGfQ+15Sbrk0tlsR4sg26gaLuHgP8KFsXBH7Dw==
-----END PUBLIC KEY-----
  • cosign.key (passphrase 123456)
-----BEGIN ENCRYPTED SIGSTORE PRIVATE KEY-----
eyJrZGYiOnsibmFtZSI6InNjcnlwdCIsInBhcmFtcyI6eyJOIjo2NTUzNiwiciI6
OCwicCI6MX0sInNhbHQiOiIyL2tOZlAxSXFVMEszNndTZEg4b2hnUHBkUWV0YllD
c0hxT0VoaGd5SmhZPSJ9LCJjaXBoZXIiOnsibmFtZSI6Im5hY2wvc2VjcmV0Ym94
Iiwibm9uY2UiOiJYZEpQdEZPYytrMDE5MDcvTEVQZmJ1U0t2ZkR0TG4rTyJ9LCJj
aXBoZXJ0ZXh0IjoiODMrYXlIRHozcDNQTldyTG5aTFRXRnNnZFowa2gzVE9HY0RG
V0FXUU1HbWZ0WmMzaEtjejlHMlViTjB3Ry90OXVWUlNOL0VTMkhDcm9MTWdTd3A4
Tk5QZnRGWmlBZGhLZWVOWlM0MjBMa3VSSzdVZ0N1U010NUtiVDU2cnpFTkhVcnNJ
eFd2MjV2eVJpUEpYN3NVVEdyQUl0aGRuUkdpcEgwaGdPQmpaUGZKN01MSnFBUjFk
LzhqK0ErN2ExSGdsdnpGY3FDWTgwY0FHcVE9PSJ9
-----END ENCRYPTED SIGSTORE PRIVATE KEY-----
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment