TT Lab
Get started
Learn Learning paths Courses

Air-Gapped Sites — Defence and Government

Verification Has Two Layers, and Checking One Always Lets Something Through

Continue in TT Lab

In one line

The case where the hash matches but the signature breaks and the case where the signature matches but the hash is off have completely different causes and responses, and telling them apart requires looking at both layers.

Why this was needed

"It passed verification" is vaguer than it sounds. Ask what it passed, and people usually answer only one of two things: they checked the hashes, or they checked the signature. But these two protect different things.

What the file hash protects: is this the file the manifest talked about? It catches whether the file was damaged while being moved off the media, or whether someone changed the file along the way.

What the signature protects: was that manifest made by someone we know? It catches whether the list itself was changed.

What happens if you look at only one layer is the point of this piece.

If you look at only the file hashes. Suppose someone changes a file and, to avoid being caught, also rewrites the corresponding line in the manifest with the new hash. The file hash check passes entirely — because it compared against the rewritten list. Verification catches nothing.

If you look at only the signature. Leave the manifest and signature untouched and change just one payload file. Signature verification passes — because the manifest is unchanged. The changed file gets installed as is.

So you have to look at both layers, and the order is fixed too.

How it works

The receiving side's order is this.

1) 번들 전체 해시   매체에서 옮기다 깨졌는가.        틀리면 그 자리에서 끝.
2) 서명 검증        이 목록을 아는 사람이 만들었는가.  틀리면 파일은 볼 것도 없다.
3) 파일별 해시      목록이 말한 그 파일들이 맞는가.

Why step 2 comes before step 3. If you do step 3 first, you end up comparing against a manifest whose authenticity has not yet been confirmed. Compared against a rewritten list, everything naturally matches. Changing the order alone makes verification powerless. This is the point most often gotten wrong in this module.

And there is one more thing. If the public key is inside the bundle, signature verification protects nothing. If the person holding the bundle makes their own key pair and swaps in the payload, manifest, signature, and public key all at once, the receiving side verifies the signature in that bundle with the public key in that bundle and lets it through. For a signature to mean anything, one root of trust has to arrive by a different route. Deliver the public key by a path separate from the bundle, and have the receiving side use it only after checking it against a fingerprint it already knows.

What it looks like in the field

The two failures differ in weight. If the signature is correct but one file hash is off, it is likely damage in transit. Downloading it again usually fixes it. Conversely, if all the file hashes match but the signature is broken, the list itself was swapped wholesale, so it is not a problem that ends with downloading again. The reporting line changes. That is why the import record says not "verification failed" but at which layer it broke.

The location of the private key often causes accidents. There was an accident where the signing working directory was compressed wholesale and handed over, and the private key went out with it. Keep the private key at permission 600, and always check with your own eyes what went into the bundle using tar -tzf. Thinking you did not include it and it not being on the list are different facts.

The hash file and the bundle go stale together. If you repackage the bundle, the hash changes. The value written in the document, the hash file, and the actual bundle must always be the same, but the moment you repackage, the three diverge. If packaging, computing the hash, and updating the document are not tied into a single procedure, they will surely drift apart.

What you will do in the next lab

You unpack the same bundle twice and apply a different tampering to each. In one, you change just one byte of a binary; in the other, you make the same change and also rewrite the corresponding line of the manifest with the new hash. Then you run signature verification and file hash comparison on both, and confirm by the numbers which one breaks where. Seeing the two results come out as opposites with your own eyes is the core of this lab.