On Wed, 21 Apr 1999 hal(_at_)rain(_dot_)org wrote:
I have experimentally implemented the integrated message integrity
check within the encryption/decryption layer. It is not difficult to
handle the 20-byte trailing hash during decryption. I use a circular
buffer in which I put the trailing part of each chunk of decrypted data.
It always has the last 20 decrypted bytes in it. The data is passed
through the hash as we output it from this decryption layer; once we
hit EOF we take the 20 bytes in the buffer and we know those should be
matched against the calculated hash.
I can't speak for other implementations, but I found doing it this way to
be fairly straightforward. I don't see implementation difficulty as being
a barrier to this approach, or a reason to put the integrity checking
in a pseudo-signature packet.
Implementation difficulty of one thing is not a reason, but I could
probably come up with hundreds of tiny little things to make it better
which would add some value but bloat the code greatly after all were
implemented. And we should also fix existing implementation/functional
problems such as the lack of a checksum on the new sym-encrypted-sym-key
packets so you have to try each key on the ciphertext.
You could also create a new packet type, so the EOF would simply signal
that you should look for a(n encrypted) new packet type X with 20 bytes of
contents which is the hash result.
Otherwise, why bother with all this packet nonsense and the CTBs and
whatever in the first place? You could theoretically not have any of this
and simply search backwards (or include a 2 byte tag) to the beginning of
the first signature packet.
There is a packet infrastructure. This should be used in one capacity or
another. I make an exception for header bytes because these are either of
fixed or well defined short lengths. Tacking things on the end can be
made to work, but it is not a clean way to do things.
We have packets with undefined types which we can add one for this
function. We also have a predefined packet which is (symmetrically)
encrypted as part of the existing infrastructure which in normal usage
contains the same data, except in signed form so we call it a signature
packet, but only because it has to this point only contained signatures.
To repeat: The reason to put integrity checking in a pseudo-signature
packet is because all the necessary code is ALREADY THERE, so instead of
adding a 20 byte delay line you only need a new algorithm ID to identify
this and an IF() test to bypass the signature validation routine. If
something is already there and easily adapted it is silly to create a new
Sort of like an old comedy sketch when satellites were first being used
to transmit TV where Mr. Smith was in the kitchen, but they flew him
across the country so he could appear in Mrs. Smith's living room "live
via satellite. You want to duplicate 70% of the existing signature packet
infrastructure and add a delay line layer because the MDC function is not
a "signature"? I want to make a 2% change to the existing signature
routines that would accomplish the same function.
How many lines of code did it take for your change? How much slower?
Remember to add in the hash computation. And the second hash computation
if there is one if the same packet is going to be signed anyway.
Care to take a stab at adding that function to my opgp and count the lines
as a percentage?
And try my technique and count the impact on the code. Or find some
reason the function fails to be accomplished by my method. If you could
argue that it wouldn't work (or work well, or have security problems) I
would say do it your way (except in a unique packet).
The problem with doing it in a signature packet is that it is a
fundamentally different function than signatures. The hash only provides
integrity in the context of an encryption envelope. Logically the
integrity protection is a property of the encryption layer. Doing the
hash without encryption provides no integrity protection. The signature
packet is functionally the wrong place to put it.
As I pointed out, the "signature packet" can be called something
different, e.g. "verification packet" or "validation packet". Had I known
that a MDC feature might be added I would have raised a big stink about
using the word "validation" or "verification" instead of "signature" for
the packet type in the RFC "just in case we want to do something other
than full signatures with it". What is being asked for is merely a proper
subset of what happens to create the existing packets.
It may be a fundamentally different function, but it happens at exactly
the same point in the implmementation and merely omits one step - the
actual crypto function to validate the signature. And if you are
encrypting, these packets are encrypted along with the message.
Normal messages are just the encrypted literal packet. Or encryption
applied to a 1-pass validation (was signature) header, the literal packet,
and the validation packet. You just have your hash over the V4 hashed
material value in addition to the literal packet.
Your point about requiring encryption is correct, but you can more easily
have implementations reject unencrypted non-signature validation packets
as providing no information, i.e. only worry about the validation if the
whole came from the encryption.
And are you sure that no one is going to want to add the validation or
other information provided by the subpackets? (e.g. Date info - you could
also add file permissions, length, etc. to the validation packet
infrastructure, but not to a fixed 20 byte MAC).