Skip to content

Instantly share code, notes, and snippets.

@bobcallaway
Created September 3, 2022 14:12
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 bobcallaway/dbb9b13ce71dc92ecdebde36c41f6505 to your computer and use it in GitHub Desktop.
Save bobcallaway/dbb9b13ce71dc92ecdebde36c41f6505 to your computer and use it in GitHub Desktop.
# used in OpenSSF EU 22 presentation:
#!/bin/sh
#set -X
#doitlive commentecho: true
### start second demo
#!/bin/sh
#set -x
#doitlive commentecho: true
# Requires yubico-piv-tool, step (https://github.com/smallstep/cli), jq, curl
## SETUP
# reset yubikey to factory defaults
ykman piv reset
ykman piv keys generate --algorithm ECCP256 9c pubkey.pem
# generate a sBOM* (silly bill of materials)
echo "insert dad joke here" > /tmp/sBOM
# let's sign the sBOM
yubico-piv-tool -a verify-pin --sign -s 9c -H SHA256 -A ECCP256 -i /tmp/sBOM -o /tmp/sBOM.sig
# let's upload the information to rekor
~/go/bin/rekor-cli upload --pki-format=x509 --artifact /tmp/sBOM --public-key pubkey.pem --signature /tmp/sBOM.sig
## FULCIO
# use step to get ID token from Fulcio OIDC IdP (note this token only lasts 60 sec - TYPE QUICKLY!)
~/go/bin/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
~/go/bin/step crypto jwt inspect --insecure < id_token |jq -r .payload.email | tr -d '\n' > /tmp/email
# sign email address from inside OIDC token with yubikey
yubico-piv-tool -a verify-pin --sign -s 9c -H SHA256 -A ECCP256 -i /tmp/email -o /tmp/email.sig
base64 /tmp/email.sig |tr -d '\n' > /tmp/email.sigb64
# 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\": \"$(base64 pubkey.pem | tr -d '\n')\" }, \"signedEmailAddress\": \"$(base64 /tmp/email.sig|tr -d '\n')\" }"
# 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