Sign a release, distribute it, and detect a tampered copy

capstone · 120 min · Objective 1.3

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

  1. Before anything else, copy root.crt from 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.
  2. On the publisher, create the release: printf 'lab release v1\n' > release.txt, and publish its digest with sha256sum release.txt > release.sha256 (that format is what sha256sum -c reads back).
  3. Sign the digest with the server key from the PKI lab -- openssl dgst -sha256 -sign server.key -out release.sig release.sha256 -- and place server.crt and intermediate.crt alongside. Do NOT serve root.crt.
  4. 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.
  5. 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 YOUR root.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 ships openssl and sha256sum.
  6. Now tamper. Modify release.txt on the publisher WITHOUT updating anything else, fetch again, and repeat the recipient's checks. Record which one failed.
  7. Tamper the second way: modify release.txt AND regenerate release.sha256 to match, leaving the signature alone. Repeat the checks and record which one failed this time.
  8. Tamper the third way: generate a new key, sign the new digest with it, and replace server.crt on the publisher with that key's self-signed certificate. Repeat the checks -- the Verify block takes pub.pem afresh from whatever certificate was served, as a real client would -- and record which one failed.
  9. Write /tmp/release-report.md mapping 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.