Sign a release, distribute it, and detect a tampered copy
Task
Pull Domain 1 together into one exercise: publish a signed artefact with a certificate chain you built, verify it as a recipient would, then tamper with it and show precisely which check catches the tampering and which does not.
Steps
- Before anything else, copy
root.crtfrom the PKI lab to the recipient by hand, out of band. That copy is the recipient's trust anchor. A root the recipient downloads from the same server as the release proves nothing: whoever controls the server chooses it. - On the publisher, create the release:
printf 'lab release v1\n' > release.txt, and publish its digest withsha256sum release.txt > release.sha256(that format is whatsha256sum -creads back). - Sign the digest with the server key from the PKI lab --
openssl dgst -sha256 -sign server.key -out release.sig release.sha256-- and placeserver.crtandintermediate.crtalongside. Do NOT serveroot.crt. - Serve the five files (
release.txt,release.sha256,release.sig,server.crt,intermediate.crt) on the lab network only:python3 -m http.server 8080 --bind 10.99.0.10. - On the recipient, retrieve all five from
http://10.99.0.10:8080/and run the Verify block below, which checks in the right order: first the certificate chain against YOURroot.crt, then the signature over the digest using the public key taken from the certificate you just checked, then the digest against the file. On the Windows VM run it in Git Bash, which shipsopensslandsha256sum. - Now tamper. Modify
release.txton the publisher WITHOUT updating anything else, fetch again, and repeat the recipient's checks. Record which one failed. - Tamper the second way: modify
release.txtAND regeneraterelease.sha256to match, leaving the signature alone. Repeat the checks and record which one failed this time. - Tamper the third way: generate a new key, sign the new digest with it, and replace
server.crton the publisher with that key's self-signed certificate. Repeat the checks -- the Verify block takespub.pemafresh from whatever certificate was served, as a real client would -- and record which one failed. - Write
/tmp/release-report.mdmapping each of the three tampering methods to the check that caught it, and state which check would have been the only defence if the other two were skipped.
Verify
openssl verify -CAfile root.crt -untrusted intermediate.crt server.crt
openssl x509 -in server.crt -pubkey -noout > pub.pem
openssl dgst -sha256 -verify pub.pem -signature release.sig release.sha256
sha256sum -c release.sha256
grep -ciE "chain|signature|digest" /tmp/release-report.md
Run all three checks after each tampering round and record the outcomes. The first round must fail at sha256sum -c; the second must pass the digest check and fail the signature check; the third must pass both and fail the chain verification. The grep must be at least three — the report maps every method to its check.
Notes
The third round is the one that matters, and it is the supply chain problem from Domain 2 in miniature: the attacker produced a perfectly valid digest and a perfectly valid signature. Only the certificate chain — the question of WHOSE key signed it — caught them. An organisation that checks digests and signatures but never validates the signer has a verification process that a self-signed key defeats.
And the chain caught them only because of step 1. Had the recipient downloaded root.crt from the release server, the attacker would have served their own self-signed certificate as the root, and all three checks would have passed. A trust anchor that arrives with the thing it vouches for is not an anchor.
This is an independent study companion for CompTIA Security+ SY0-801 and is not produced by or endorsed by CompTIA.