Nexus Handbook handbook · verified
Handbook/Signing practice

What a signature proves, and what it does not

Verification gets recommended constantly and explained rarely. People end up running the command as a ritual without a clear sense of what a GOOD result establishes. That gap is worth closing, because the difference between what signing proves and what people assume it proves is where the remaining risk lives.

#The claim a signature makes

A signature over a block of text establishes exactly two things. Whoever produced it held the private key matching a specific public key. And the text has not changed by a single character since they produced it.

That is the entire claim. It is narrow and it is absolute. There is no partial credit and no probabilistic element. Either the maths works out, in which case both statements hold, or it does not, in which case neither does.

Everything useful follows from chaining that claim to something you already trust. If you know the key belongs to the market, and the market signed a statement listing its current addresses, then a valid signature over that statement tells you the list is genuine and unmodified. The signature does not carry that trust on its own. It transfers trust you already had in the key.

The dependencyVerification is only as good as your confidence that the key is the right key. A signature checked against a key you obtained from the page you are trying to verify proves nothing at all. It is a page vouching for itself.

#Which means the key comes first

This is the step people skip. Getting the key right is the part that requires care, and once it is done correctly it stays done. The fingerprint is the thing to pin, not the key file, because a fingerprint is short enough to compare by eye and long enough that nobody can produce a second key matching it.

Get the fingerprint from more than one place that would have to be compromised independently. Check it once, carefully, character by character rather than glancing at the first and last few. Then store it where you will find it later. After that, every future verification is mechanical and you never repeat this step. The getting started chapter walks through the commands.

The failure mode worth naming explicitly is accepting a key because it arrived alongside the thing it was meant to verify. A phishing page will happily serve you a key, a signed message, and instructions for checking one against the other, and all three will be internally consistent because the same person produced all three. Internal consistency is not evidence.

#The four ways it fails

GnuPG tells you which of these you are looking at, though the output is not always easy to read. They mean very different things.

BAD signatureThe maths does not work. The text was altered after signing, or the signature was fabricated. This is unambiguous and the only correct response is to leave.
No public keyThe message was signed by a key you do not have. This is not a failure of the message, it is a gap in your keyring. Import the correct key, after checking its fingerprint, and try again. Do not import whatever key the page offers you.
GOOD signature, wrong keyThe maths works, but against a key that is not the one you pinned. This is the dangerous one, because the word GOOD appears in the output. Always read which key ID signed, not just whether the word GOOD is present.
GOOD signature, stale contentEverything checks out but the signed statement is old. A signed message stays valid forever, so an attacker can replay a genuine old one. This is why signed statements carry a timestamp and why you have to actually look at it.

The last two are the ones that catch experienced users, and both are defeated by the same habit. Read the output rather than pattern matching on the word GOOD. Two extra seconds.

#Replay, and why timestamps are in there

A signature has no expiry built into it. A statement signed two years ago verifies exactly as cleanly today as it did then, because nothing about it has changed. That property is what makes signatures useful for archives and what makes them awkward for anything about the present.

The fix is to put the time inside the signed text. Once the timestamp is part of what was signed, it cannot be adjusted without breaking the signature, so an attacker replaying an old statement is stuck presenting an old date. Then the question becomes whether you look at it. A signed statement dated eleven months ago verifying perfectly is telling you something was true eleven months ago, which is not the question you were asking.

This matters most around address rotation. A genuine, correctly signed roster from before a rotation lists an address that has since been retired. Everything about it verifies. It is simply out of date, and out of date rosters are precisely what gets replayed.

#Where verification stops helping

Being honest about the limits is more useful than overselling the tool.

None of that argues against verifying. It argues for treating verification as one control among several rather than the whole of your defence. It reliably answers one question, which is whether you are where you think you are, and it answers that question better than anything else available. The security chapter covers the controls that sit around it.