Subject: Reason for V4 signature postscript

From: "Hal Finney" <[email-masked]>
Date: Thu, 22 Jan 2004 14:43:37 -0800

I got some email from Peter Gutmann asking why we do the bizarre
"postscript" in the hashing of V4 signatures.  I didn't remember, but
some digging into the code shed light on it, and gradually the reasons
came back.  Here is the mail I sent to him, which may be useful for
future software archaeologists.

The general concern we had was "aliasing", meaning that a specific set of
bytes which were hashed could mean different things in different contexts.
Specifically, we were worried that a V3 sig could have the same bytes
hashed as a V4.  The problem is that V3 sigs don't hash the sig version.
They hash the body of the data, which could be anything, and then they
hash the sig type and then 4 bytes of sig creation time.

We wanted to make certain that you couldn't conjure up a document and
get someone to put a V3 sig on it, and then turn that into a V4 sig on
something else.  So we wanted to make sure the last 5 hashed bytes for
a V4 sig could never look like the last 5 hashed bytes for a V3 sig.

The oldest version of the code I could find reads like this:

            /* Add hash "postscript", ensure hashed data not alias anything */
            postscript[0] = PGPVERSION_4;  /* Hash-convention version */
            postscript[1] = 0xff;   /* 5th from end, != any sig type value */
            postscript[2] = (PGPByte)(l >> 24);
            postscript[3] = (PGPByte)(l >> 16);
            postscript[4] = (PGPByte)(l >>  8);
            postscript[5] = (PGPByte)(l >>  0);
            PGPContinueHash (temp_hc, postscript, sizeof(postscript));

The 4 is the hash-convention version, which I guess we meant to
distinguish from the signature version.

The FF is there as that is never a value found in the 5th from the end
(or 4th from the end if you count differently) of the data hashed for
a V3 sig.  This assures that no V4 and V3 sigs will ever have the same
bytes hashed.

I remember now why the length was there.  It allows for unambiguous
parsing of the fields of the signature packet, counting from the far
end.  Without that, there may be ambiguity about how to parse it out,
because there is no way, starting from the front, to know where the
signed-document's data ends and the data from the signature begins.
The signed-document's data is hashed with no headers, just the content
of the document, so you don't know where it ends.

As long as the hashed data can be unambiguously parsed from one end or the
other, there is no danger of border-shifting, where data that is supposed
to be part of one field can be interpreted as being part of another.
Without this length field, that is a problem.

So that explains the length, and the FF.  The 4 still seems a little
redundant, but by the end of one of these exercises, you get sort of
paranoid about both making sure no ambiguities are possible, and also
leaving yourself an escape so that the next version of the software
won't suffer from this.  Since we were relying on parsing from the end
to prevent aliasing, it felt a little safer to put a version field right
near that end.  That way if we ever went to a V5 signature we could do
so without worry that it could be aliased with a V4 sig.

Hal Finney