The organisation delivers the evidence, the auditor performs the verification. That needs no access to the product, no server and no software written by us. The tools that ship with Windows, or openssl, are enough.
Three separate packages exist because they answer three separate questions and are delivered at different times. Their wrapper is identical, so the auditor learns one procedure.
| Package | The question it answers | Its data file |
|---|---|---|
| Evidence dossier SQLChangeGuard-Evidence |
The end to end story of the single request you sampled. Who asked for it, under which rule it was approved, who ran it, what the script was that day. | Dossier.json Dossier.pdf |
| Anchor package SQLChangeGuard-Anchors |
The daily anchors for a date range. Each anchor carries, under signature, the digest of the last record at the moment it was taken. It is delivered regularly, ahead of the audit. | Anchors.json |
| Audit records package SQLChangeGuard-AuditRecords |
The raw audit rows for the record number range you choose. This is the only delivery that lets the claim inside an anchor be compared against today's records. | Package.json |
Why not a single file. The anchor has to have been delivered before the audit; its value comes from being early. An anchor that arrives together with the records is just two files produced at the same moment by the same party, and proves nothing. Merging all three into one file would destroy the only evidential value the anchor has.
| File | What it is for |
|---|---|
| The data file | Dossier.json, Anchors.json or Package.json. The evidence itself. Plain text JSON, readable by eye. |
| Manifest.json | The package identity block: installation id, product version, range, and the SHA-256 digest of every file in the package. Removing a file from the package is caught by this list. |
| Manifest.sig | The RSA signature over the bytes of Manifest.json, in Base64. The signature is over the bytes that were delivered, not over a recomputed copy. |
| PublicKey.pem | The public half of the key that signed the manifest. When an anchor package spans a key change, the older keys ship separately as PublicKey-<id>.pem, because openssl reads only the first key out of a concatenated PEM file. |
| Verify.ps1 | A script that runs the checks above for you. Its own digest is listed in the manifest, so a modified copy is caught. It is a convenience, not the evidence. |
The signature parameters are fixed and stated in the evidence format specification: RSA (3072 bit minimum), SHA-256, PKCS#1 v1.5, PEM key, Base64 signature. When timestamping is on, the evidence dossier also carries Manifest.tsr; the stamp on an anchor travels inside the anchor envelope itself.
The steps do not substitute for each other. One passing does not make another pass.
You read the list in Manifest.json and recompute the SHA-256 digest of every file. A row that does not match means that file changed after the package was produced.
The question it answers: is the file in front of me the one that came out of the package?
Manifest.sig is checked against PublicKey.pem. If it passes, the manifest came from the installation that holds the matching private key and has not changed by a single byte since.
The question it answers: was this list really sealed with the organisation's own key?
You compute the fingerprint of the public key and compare it with the value the organisation published outside this package. Skip this step and step 2 proves nothing: anyone who ships a package with a key of their own also passes the signature check.
The question it answers: is the key that sealed this package the key the organisation declared?
The first three steps check the wrapper. The fourth looks at the records themselves and needs no key: chain linkage, the anchor comparison, and recomputing the content. All three are set out below.
The question it answers: could the records have been rewritten after the fact?
The signing key of the audit chain stays inside the organisation and never leaves it. None of these three checks needs that key, so the auditor can run them alone.
Every row in the records package carries the digest of the row before it. You take two consecutive rows and check whether the previousHash of the later one equals the hash of the earlier one. This can be done entirely by hand, with nothing but the rows in the package.
Knowing the limit of this check matters. It compares digest values only; it does not compute whether a digest really belongs to the content beside it, because that needs the secret key. So it catches an inserted row and a deleted row, but on its own it cannot catch a content edit.
You hold an anchor package from last month, received at the time. One anchor in it says: "on that day my last record was number 41,207 and its digest is this." That sentence is signed and it was delivered on that day.
Today you ask for a records package covering record 41,207 and compare the hash of that row against the value in the anchor. If they match, that record has not changed since the day the anchor was delivered.
The strength of this check rests entirely on the anchor having been delivered to you earlier. An anchor that arrives on the same day as the records proves nothing; both files were produced at the same moment. That is why anchor delivery is not left until audit time but happens on a schedule. Each export is itself an audit event and is recorded, so a regular delivery habit can be shown from those records afterwards. If no range is given, the package starts where the previous delivery ended, leaving no gap between two deliveries.
The two checks above share one gap: both look only at digest values. Someone who changes the content of a record and leaves its digest field untouched would pass both. The link holds, the anchor holds, nothing shows.
So the records carry a second chain, and that one is keyless. The auditor recomputes the value from the content of the record on their own machine and compares it with what the row says. A mismatch means that record's content changed.
The objection that a keyless value can be computed by an attacker too is correct and beside the point. This chain draws its strength not from secrecy but from its end value sitting in an anchor already delivered to you. An attacker can recompute the chain but cannot change the old value in your drawer. Git commit digests and certificate transparency logs work the same way.
The exact definition of the calculation is in the evidence format specification, together with a test vector: a given input with its expected output, so you can write your own verifier and check that it works.
Unzip the package and run these inside the folder. Nothing connects to the product and nothing goes over the network.
The script is not part of the evidence. Verify.ps1 ships inside the package it checks. An auditor who wants independence should run the commands by hand at least once. The authoritative procedure is not in the script but in the evidence format specification, which is available on request and which the delivered packages follow.
With these four items in hand the whole verification can be done. The order matters.
You can ask for a fifth item: the evidence format specification. The authoritative description of the verification is in that document rather than in the script inside the package; it is available on request and the delivered packages follow it.
This is the difference between tamper evident and tamper proof. We do not promise a record that cannot be altered; we produce one where alteration shows. The second can be verified, the first can only be asserted.
A signature shows where a package came from, not when. The date is written from the organisation's own server clock, and that clock can be changed.
RFC 3161 timestamping closes that gap. When it is switched on, the digest of the package is sent to an external timestamp authority and the response is placed in the package as Manifest.tsr. The date is then stated by a third party rather than by the organisation.
The only thing that leaves the network is the digest. The record itself never goes to the timestamp authority under any circumstances. The feature is governed by a single master switch; when it is turned off no network call is made at all and the product keeps working without internet access.
The configuration that ships with the product has the feature on and points at a free public authority, so an installation can be seen working end to end on day one. In production that address should be replaced with the organisation's own contracted or internal authority: a public service makes no commitment and ties the evidence chain to something outside the organisation.
If the authority cannot be reached the work does not stop, the package is produced without a stamp, and the gap is not hidden: the file is omitted, the stamp field in the anchor envelope stays empty and a warning is written to the log. On such a package the auditor can see that the date is the organisation's own assertion.