The reason for the trailer in V4 sigs is to address a security weakness
in V3 sigs and their relation with V4. The problem is that V3 key sigs
do not hash the length of the userid field, and neither version hashes
the length of the data when signing a document. This would mean that,
if we did not have a V4 trailer, it might be possible to get someone to
V3 sign a properly constructed userid or document, and then turn that
into a V4 signature on something else.
To prevent that, we want the sequence of bytes hashed in a V4 signature to
be (a) uniquely parseable; and (b) unable to match the same sequence of
bytes hashed in any other signature version. Uniquely parseable means
that given the sequence of bytes that were hashed, and with no other
information, you can determine with 100% reliability what the parsing
is of the data into signature packets and other packets.
V3 document signatures hash n random bytes, where n is not hashed,
and then 1 byte of signature type and 4 bytes of signature creation time.
V3 key signatures hash bytes starting with the key packet, which is
uniquely parseable because it includes the length; then the user id,
which does not include the length; then 1 byte of signature type and 4
bytes of signature creation time.
We want to make sure that no V4 signature could hash a sequence of bytes
that matches the same sequence of bytes in a V3 signature.
This is why we force the 4th byte from the end in the V4 sequence of
hashed bytes to be 0xff. The 4th byte from the end in a V3 sequence
of hashed bytes will always be signature type, and 0xff is not a legal
signature type. So that will ensure that V3 signatures cannot be
re-packaged as V4 signatures.
The reason we include the version number and length of hashed packets
is to ensure unique parseability. Without the length of hashed packets
at the end, you could create a document whose V4 signature could be
applied to a different document with different subpackets in a modified
V4 signature. By including the length of hashed packets we make it
unambiguous where the document ends and the V4 signature packet begins.
And the reason we include the version there is in case we change this
for future versions, we will have an unambiguous place where the version
number can be found, 6 bytes from the end. The other location of version
number might not be uniquely parseable once we create new versions.
This will give us more flexibility in the future and we won't have to
worry about repackaging attacks as we did with the V3 to V4 transition.