Skip to content

Instantly share code, notes, and snippets.

@bobcallaway
Created February 23, 2022 14:51
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bobcallaway/e669534a9591c802b64c84603323c2c0 to your computer and use it in GitHub Desktop.
Save bobcallaway/e669534a9591c802b64c84603323c2c0 to your computer and use it in GitHub Desktop.
# used in DevConf 22 presentation: https://www.youtube.com/watch?v=vh26wcpA1-M
#!/bin/sh
#set -X
#doitlive commentecho: true
#
# Start with a clean slate
make clean
#
# Edit the source
cd hello-ko
vim main.go
#
# Make the binary
go build . && sha256sum hello-ko
#
# Let's commit and push this to github
git commit -sam "commit from live demo - $(date)" && git push origin main
#
# Sign the binary (blob)
COSIGN_EXPERIMENTAL=1 cosign sign-blob hello-ko --output-certificate hello-ko.cert
#
# Let's look at the cert
cat hello-ko.cert | base64 -d | openssl x509 -text -noout
#
# Let's search the transparency log for the entry
rekor-cli search --sha $(sha256sum hello-ko | cut -d ' ' -f 1)
#
# Let's look at the specific entry
rekor-cli get --uuid $(rekor-cli search --sha $(sha256sum hello-ko | cut -d ' ' -f 1) 2>/dev/null | head -1)
#
#
# but containers are all the hotness these days, let's go look at the github action
#
#
COSIGN_EXPERIMENTAL=1 cosign verify ghcr.io/bobcallaway/hello-ko | jq
# let's look at the code signing certificate from github actions
rekor-cli get --log-index $(COSIGN_EXPERIMENTAL=1 cosign verify ghcr.io/bobcallaway/hello-ko 2>/dev/null | jq -r .[0].optional.Bundle.Payload.logIndex) --format=json | jq -r .Body.HashedRekordObj.signature.publicKey.content | base64 -d | openssl x509 -text -noout
### end first demo
### start second demo
#!/bin/sh
#set -x
#doitlive commentecho: true
# Requires openssl, step (https://github.com/smallstep/cli), jq
## COSIGN or SWISS-ARMY-KNIFE TOOL
# use openssl to generate keypair
openssl ecparam -genkey -name secp384r1 > ec_private.pem && openssl ec -in ec_private.pem -pubout > ec_public.pem
# show public key
cat ec_public.pem
## FULCIO
# use step to get ID token from Fulcio OIDC IdP (note this token only lasts 60 sec - TYPE QUICKLY!)
step oauth --provider=https://oauth2.sigstore.dev/auth --client-id=sigstore --listen localhost:0 --oidc --bare 2>/dev/null > id_token
# extract email from ID token
step crypto jwt inspect --insecure < id_token |jq -r .payload.email | tr -d '\n' > email
# sign email address string with private key
openssl dgst -sha256 -sign ec_private.pem email > email.sig
# verify signature locally
openssl dgst -sha256 -verify ec_public.pem -signature email.sig email
# submit to fulcio via curl (need to sign email address with private key)
curl -s https://fulcio.sigstore.dev/api/v1/signingCert -H "Authorization: Bearer $(cat id_token)" -H "Accept: application/pem-certificate-chain" -H "Content-Type: application/json" -o signingCertChain.pem --data-binary "{ \"publicKey\": { \"algorithm\": \"ecdsa\", \"content\": \"$(step crypto key format ec_public.pem|base64 -w0)\" }, \"signedEmailAddress\": \"$(base64 -w0 email.sig)\" }"
# inspect OIDC ID token
step crypto jwt inspect --insecure < id_token | egrep -v "sub|user_id"
# inspect signing cert chain
openssl crl2pkcs7 -nocrl -certfile signingCertChain.pem | openssl pkcs7 -print_certs -text -noout
# verify signed email address using pub key in signing cert
openssl x509 -pubkey -noout -in signingCertChain.pem > signingPubKey.pem
openssl dgst -sha256 -verify signingPubKey.pem -signature email.sig email
diff signingPubKey.pem ec_public.pem || echo "pub key from signing cert does not match generated one"
## COSIGN or SWISS-ARMY-KNIFE TOOL
# generate & sign artifact and generate detached signature
head -c 128 < /dev/urandom > artifact
openssl dgst -sha256 -sign ec_private.pem artifact > artifact.sig
openssl dgst -sha256 -verify signingPubKey.pem -signature artifact.sig artifact
# generate timestamp request
openssl ts -query -data artifact.sig -cert -sha256 -no_nonce -out request.tsq
# send to Rekor Timestamping authority to make entry into log for this signature
# -- note that the index for the timestamp entry in the log is returned as a response HTTP header
curl -sSH "Content-Type: application/timestamp-query" --data-binary @request.tsq https://rekor.sigstore.dev/api/v1/timestamp -o response.tsr
# fetch timestamping certificate chain for verification
curl -sSo ts_chain.pem https://rekor.sigstore.dev/api/v1/timestamp/certchain
# verify timestamp response
openssl ts -verify -in response.tsr -queryfile request.tsq -CAfile ts_chain.pem
# ensure timestamp is during validity period of code signing certificate
openssl ts -reply -in response.tsr -text | grep "Time stamp"; openssl crl2pkcs7 -nocrl -certfile signingCertChain.pem | openssl pkcs7 -print_certs -text -noout|grep -A2 -m1 Validity
## REKOR
# submit signature for & signing cert to rekor
curl -s https://rekor.sigstore.dev/api/v1/log/entries -H "Accept: application/json" -H "Content-Type: application/json" -o rekor_output --data-binary " { \"apiVersion\": \"0.0.1\", \"kind\": \"rekord\", \"spec\": { \"signature\": { \"format\": \"x509\", \"content\": \"$(base64 -w0 artifact.sig)\", \"publicKey\": { \"content\": \"$(base64 -w0 signingCertChain.pem)\" } }, \"data\": { \"content\": \"$(base64 -w0 artifact)\" } } }"
jq '.[keys[0]].body |= (@base64d|fromjson)' rekor_output
# print inclusion proof for entry
# curl -s -H "Accept: application/json" https://rekor.sigstore.dev/api/v1/log/entries/$(jq -r -c 'keys[0]' rekor_output) | jq .
rekor-cli verify --artifact artifact --signature artifact.sig --public-key signingCertChain.pem --pki-format x509
# delete private key - since all we need to verify signature is stored in Rekor
rm -rf ec_private.pem
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment