ietf-openpgp
[Top] [All Lists]

Comments on draft - Long.

1997-12-03 03:53:01
-----BEGIN PGP SIGNED MESSAGE-----

OpenPGP Comments - Bill Stewart, bill(_dot_)stewart(_at_)pobox(_dot_)com, 
12/2/97
Based on 11/97 draft-ietf-openpgp-formats-00.txt ,
plus some mailing list discussion.
===================================================
Structural comment - the draft is a bottom-up document,
rather than a top-down document.  That generally makes the
syntax clearer, in that you never use a FooObject as a component
of a BarObject until you've seen the syntax for the FooObject,
but it's difficult to use for recursive structures,
and it's extremely difficult to do a good job of explaining the
semantics, at least when the context and meaning are as
closely intertwined as they are here.  I say this partly as
a call for careful, clear writing, and partly as an apology for
stuff I get wrong because I don't quite follow it :-)
====================================================

Major missing capability - support for Stealth formats.
I suppose that, since I haven't written up a proposal by now,
I can't complain (:-), but it'd be nice to leave this open
for OpenPGPv2 or something.

=============
Various packed number formats - it's probably cleaner to
describe these up front, or at least before they're used.
=============


3.3 Counted Strings - 
        "A counted string consists of a length and 
        then N octets of string data"
How long is the length field?  What's its format?
I'm guessing it's one of the various variable-length-packed-number
formats used in PGP, but you need to specify which one. 

3.4 Time Fields - Y2038 problem - Also 5.2.2.2, 5.5.2. 5.9
Using Unix-style "seconds since 1970" dates as the only format is 
not a bright thing to do in 1997....   A couple of alternatives:
a) Define a new format, like "yyyymmdd,milliseconds of day" or
        "microseconds since 1AD/01/01/00:00:00" (easy fit in 64bits) or
        "yyyymmddhhmmss.nanosec", that'll be good for all
        reasonable applications (are microseconds enough??)
b) Time values below 10,000,000 are days since 1AD/01/01
        (assumes 1 day granularity is enough, and no PGP in first
        115 days of 1970 :-)  Or hours since 1AD/01/01/00:00:00.
        (Another packed number format - sigh :-)
c) At very minimum, make the times modulo-2**32, with values 
        assumed to be later than ~1990, and validity intervals
        adjusted appropriately.  That still limits you to
        68-year usage, or 34 for safety, which is unfortunately
        a real problem for long-term e-commerce.
d) Use the notation field in signatures if you really care...

There's also the problem that times can't be trusted,
so you shouldn't depend on them too strongly.

3.5.1.3 / 3.5.3.3 Iterated-Salted
What a blazingly ugly design!  Is it really necessary to use
a byte-count in a special one-octet-floating-point format,
rather than using an iteration count?  Probably saves one
multiplication when preparing the argument for a hash,
at the cost of a couple masks and shifts and adds a hunk of code.
Especially with the "Conventionally Encrypted Session Key" 
available, the extra complexity seems unnecessary.

If anybody's really using this option, it probably should be kept,
but as a MAY read, DEPRECATED generate.  Otherwise reserve the
S2K-type indicator 0x03 and drop it.

4.2 Packet Headers - Packet Length.
I'd rather have seen a cleaner format for the length,
but that's a job for OpenPGPv2 to clean up.
(In particular, I'd like to see a format that allows for
padding to multiples of 4 or 8 octets.)

Meanwhile, it appears that the Partial Body Length can
support indefinite-length material, which is critical,
since it allows PGP to be used with streaming input such as
speech that goes on for a long time, (though the particular
encoding is inefficient if the data comes in natural chunk sizes
that aren't powers of 2 (or at least 3*2**n), or compresses
to irregular sizes.)  It's worth noting this kind of application
in the draft, to encourage OpenPGP implementations to be designed
in ways that aren't limited by temp files with maximum lengths.

4.3 Packet Tags / 5.1 Encrypted Session Key Packet - (nitpick)
should "Encrypted Session Key Packet" be renamed 
"Public Key Encrypted Session Key Packet" now that 
there's also a "Conventionally Encrypted Session Key Packet"?

Also, the "Name Packet" (Tag 13) is yet another packet that's
later called a "UserID Packet".  My personal preference is to
call it a "User Data Packet" - see 5.11 for discussion.

5.1 Encrypted Session Key Packet - Traffic Analysis Risk -
The KeyID field, as defined, leads to a major traffic analysis risk,
but the format doesn't depend critically on the value in the field.
At a previous Bay Area Cypherpunks meeting, somebody from PGP 
mentioned a request from some freedom fighter users that KeyIDs
be shorter, because the current tyrannical government was
using them to identify who to torture into decrypting messages -
having PGP was incriminating enough, but with short KeyIDs, 
e.g. 0-3 or 0-16, it's possible to reduce decryption workload
without indentifying the user of the message.

Some obvious alternative implementations are to keep the field
for compatibility, while specifying that the 
- - the receiver of a message MAY attempt decryption regardless
        of the value in the field, regardless of whether
        it's intended for him or not.
- - the sender must output a value in the field that 
- -- SHOULD be the KeyID, but 
- -- MAY be all-0, for which the receiver SHOULD/MAY decrypt
- -- MAY be Z=1-63 bits of leading 0 followed by the low-order
        64-Z bits of the intended recipient's KeyID, which the 
        receiver SHOULD/MAY decrypt if it matches his KeyID's low bits.
- -- MAY be some other prearranged value, e.g. a multicast code,
        which the receiver MAY decide to attempt to decrypt.

Since this just requires permission in the spec, rather than
needing specific implementation, and since the main negative impact
on non-implementing users is attempting to decrypt
an occasional message that wasn't intended for them that they
happened to receive, I'd like to ask that it be included.

5.2 Signature Packet
===== documentation comments
This section deals with some of the most complex parts of PGP.
It needs to address where the signature packets fall in the
grand scheme of things, e.g. needs enough BNF here or elsewhere to say

    Signed_Thing::=     Signed_Key | Signed_Doc | One_Pass_Signed_Doc
    Signed_Key  ::=     one Public Key Packet (Tag 6) FOLLOWED BY
                        one or more Signature_Packet(Tag 2)
    Signed_Doc  ::=     one Signature_Packet(Tag 2) FOLLOWED BY
                        one Data_Packet
    Data_Packet ::=     Compressed_Data_Packet(Tag 8) |
                        Literal Data Packet
    One_Pass_Signed_Doc::= one One_Pass_Signature_Packet(Tag4) FOLLOWED BY
                        one Data_Packet FOLLOWED BY
                        one Signature Packet

(Correcting this as needed.)

It also would be nice to put some of the semantic issues in the
front section here - at very least, the definition of
"self-signature".

Also, while PGP 2.6.2 uses Version 3 Signature Packets,
either section 5.2 or 5.2.1 should indicate that it only supports
RSA and not also the DSA signatures.

=== proposed semantic issues for 5.2:
Implementations SHOULD support generation of V3 signatures,
and PROBABLY (??) SHOULD generate them when encrypting to RSA keys,
or at least RSA keys received from a Public Key Packet Version 3.
Implementations SHOULD NOT generate V3 signatures for non-RSA keys?

5.2.2 Version 4 Signature Packet Format

The format does not contain a KeyID field, and does not
document how to find the KeyID from the various Public Key types --
there needs to be at least a reference to the section
currently numbered 8.2.

The subpacket stuff is confusing (no surprise, it's new.)
The descriptions of the Hashed and Unhashed subpacket data should be
- - one or more hashed subpackets
- - zero or more unhashed subpackets
or else these two lines and their preceding lines should be replaced by
- - hashed_subpacket block
- - unhashed_subpacket block
and the definitions of the subpacket blocks (here or in 5.2.2.1) should be
- - Two-octet octet count for following subpacket data.
- - zero or more (un)hashed subpackets

5.2.2.1 - Signature Subpacket Specification
I'm assuming the "Two-octet octet count" in this section is the
same field as in 5.2.2?  (Should be anyway.)  Only should appear once.

The description up front needs to say something like
- -------------
Some subpacket types are mandatory, others are optional.
Some subpacket types only apply to self-signatures.
Some subpacket types can appear multiple times, others just once.
Some subpacket types are always hashed, some are always unhashed.
        (Are any of them optionally hashed?)
A hashed subpacket MUST be in the hashed_subpacket block, and 
an unhashed subpacket MUST/MAY appear in the unhashed_subpacket block.
- -------------

The header format description is clumsy, and should be restructured.
Replace the 
        - subpacket type (1 octet):
          If bit 7 is set, subpacket understanding is critical,
with
        - subpacket_type_and_criticality_flag (1 octet)
        bit 7    - Criticality Flag
        bits 6-0 - subpacket type.

I'd recommend that the table of subpacket types indicate
which of these attributes apply to it, e.g.:
- --------------
         2 = signature creation time,   (hashed,mandatory,once)
         3 = signature expiration time, (hashed,optional,once)
         4 = exportable,                (hashed,optional,once)
         5 = trust signature,           (hashed,????,????)
         6 = regular expression,        (hashed,optional,once)
         7 = revocable,                 (hashed,optional,once)
         9 = key expiration time,       (hashed,optional,once,self)
        10 = reserved for PGP use       (hashed,optional,multiple,self)
        11 = preferred symmetric algorithms,    (hashed,optional,once)
        12 = revocation key,            (hashed,optional,????,self)
        16 = issuer key ID,             (unhashed,mandatory,once)
        20 = notation data,             (unhashed,optional,multiple)
        21 = preferred hash algorithms, (hashed,optional,once)
        22 = preferred compression algorithms,  (hashed,optional,once)
        23 = key server preferences,    (hashed,optional,once,self)
        24 = preferred key server       hashed,optional,once,self)
- ------------

Semantics Question - is support for optional subpacket types MUST?
        or only SHOULD or MAY?  
        Is support for types not defined here MAY or MUST NOT?

It would be nice to reserve some of this space for
user-defined functions, though it's a tossup whether the best mechanism
is to define additional numbers (e.g. reserve 64-127 or 96-127)
or to use the notation data with user-specified values (better?).

The Criticality Flag stuff is confusing.  I think I understand it better
now than I did before, so here's what I think it means (and if
I'm wrong, I hope somebody will rewrite it so it sinks in next time:-)
        The Criticality Flag is a request from the signer to the
        recipient's OpenPGP implementation for strict semantic support
        for optional and undefined subpacket types.  
        If the recipient's implementation does not recognize or 
        recognizes but does not implement a subpacket type
        for which the signer has set the Criticality Flag
        - For a Signed_Doc or One_Pass_Signed_Doc, the implementation
                ? SHOULD ignore the Criticality Flag
                ? SHOULD use the implementation-defined bad-signature
                        handling response.
        - For a Signed_Public_Key, 
                Define a Valid Self-Signature as
                The packet contains an Issuer KeyID subpacket, 
                The implementation must calculate the Key's KeyID
                The Issuer KeyID matches the Key's KeyID
                The implementation must calculate the signature
                        for the public key packet, using the public key,
                        as described in Section #.##
                The calculated signature matches.

                Depending on whether the signature is a self-signature,
                - If the Signature Packet is not a Self-Signature,
                  --- the implementation SHOULD discard the Signature Packet
                  --- the implementation SHOULD invoke error-handling
                - If the Signature Packet is a Valid Self-Signature,
                  --- the implementation MUST? discard the Signature Packet
                  --- the implementation SHOULD? invalidate the 
                        entire key that the Signature signs,
                        at least if it's a brand-new key
                  --- the implementation SHOULD NOT? continue to use
                        the key, at least if it's new.
                  --- the implementation SHOULD invoke error-handling
                - If the Signature Packet is an INVALID Self-Signature,
                        the implementation MUST discard the signature
                        but PROBABLY SHOULD NOT? invalidate the key,
                        unless it's a brand-new key. 

                  
5.2.2.2 Signature Subpacket Types
(it'd be nice to number these, especially since you've got numbers :-)
I've already discussed Y2038 problems above, so assume they apply
here as well.

- - Signature Creation Time - MANDATORY?  
        Or MAY this be optional, at least for environments like
        smartcards that may really not know what time it is.

- - Preferred {sym,hash,comp} - array of one-octet values
        The syntax for an array needs to be specified!
        Is it "Some counter field and COUNT octets"?
        Or "Null-terminated bunch of octets"?

- - Exportability - needs a definition of export/import.

- - Trust Signature - this invokes a bunch of complex semantics,
        which aren't explained very deeply in the one paragraph.
        If they're defined stably enough to really belong in this
        document, they should either be described here,
        or (better) in an appendix, or There should be a pointer 
        to some document elsewhere that explains what all this
        "meta-introducer" stuff is about and why it's different
        from simply being one signature higher up the food chain.

- - Additional Recipient Request - the community seems to have
        stabilized on the view that this should be
        Reserved For <Somebody's> Use.

- - Notation Data - I'm unclear on the flag syntax.  Is it
        -       First Octet - ALWAYS 0x80 or RESERVED
                2nd-4th Octets - 0x00, Reserved, MUST ignore
        - or -  First Octet - 0x00 or 0x80 or implementation-defined
                2nd-4th Octets - implementation-defined
        I'd prefer the latter.  Also, since this is an obvious
        extension mechanism for software, we ought to define
        some way to specify that the Notation is intended for
        implementation-defined software use.  Perhaps
                0x00 - Something special
                0x80 - Human-readable, non-software
                0x01-0x7f - Reserved for future OpenPGP use
                0x81-0xff - user-defined

- - Preferred Key Server - Currently self-signature only -
        I suggest we also permit this for non-self-signatures,
        so signers can indicate where they serve their keys
        and maybe even where they store revocation certificates.

- - Key Server Preferences - I'm guessing a more functional definition
        would be something like
        - No-Modify - Key Server SHOULD NOT change any data
                in the key server records for a key that
                sets this field.

- - [Unclear context:] Implementations SHOULD implement a "preference"
        and MAY implement a "request."
        ? It's not clear to me what this statement is referring to.
        The "preferences" indicated above were the hash/symmetric/public
        algorithms and the key servers; the only "request" I saw
        was the "Additional Recipient Request".
        It's also not clear what it means - does it mean that
        implementations SHOULD implement the ability to accept input 
        packets containing preferences (perhaps obeying them),
        and MAY implement the ability to generate output packets
        containing the preferences?

- - JDCC Note - specifying negative preferences - Is specifying
        only Triple-DES good enough?  Or should we do something hokey
        like making algorithm numbers 128-255 (or -1 - -128)
        indicate that you really don't want alg&0x80 (or -alg)?
        I lean towards the former, especially since there are
        MUST defaults available, though it would be nice to say
        CAST5,IDEA,-3DES so that the sender whose preferences are
        3DES,Blowfish,DSASubliminal,CAST5 will know to pick CAST5
        even though she likes 3DES better.  That's too subtle, though.
        Perhaps the negotiation rule should be
                Sender SHOULD pick the algorithm supported by both
                        sender and receiver that the receiver prefers,
                but MAY selfishly pick any algorithm supported by
                        both sender and receiver.

- - JDCC Note - revoking user name / user data - there isn't enough context
        at this point in the document to indicate that - we've only
        had hints and allegations that there really are user data packets
        that are signed :-)  So it needs to be later in the document.

- - JDCC Note - PGP3 other subpacket types - did it go as far as
        specifying the subpacket numbers or subpacket names?
        Should we reserve those numbers now?
        e.g. 42 - answer subpacket - reserved for later

- - 5.2.3 Signature Types -
- - JDCC Note - What should we do about defined-but-not-implemented types?
        These types 0x11-0x13 follow the "UserID Identifies A Body" model,
        rather than the more general "Key Asserts Some Attribute" model
        that folks like Carl Ellison have advocated (which I prefer.)
        (See comments on 5.11 suggesting calling it "User Data".)
        I'd recommend that we do one of two things:
        1) Junk them now, stick to generic certifications,
        and use either notations subpackets or other as-yet undefined
        subpacket types to indicate special attributes of signatures.
        We've got enough syntactical hooks already.
        2) Define more syntactical hooks :-)  
        Keep them, and also reserve 0x14-0x1f for signature types:
        implementations SHOULD/MAY accept Signature types 0x10-0x1f
        as signatures on keys, MAY handle them specially, and
        MAY output them (if there's a good reason.)
        Alternatively (now that I've ranted against the critical bit :-),
        SHOULD accept 0x10-0x17, SHOULD reject unrecognized 0x18-0x1f,
        or maybe keep 0x10-0x1f for signatures you SHOULD accept and 
        0x80-0xff for user-defined signature types which should
        be rejected if unrecognized.

- - JDCC Note - Timestamp Signatures? - Reserve for future use?
        I'm not sure how a timestamp signature is different from any
        other document signature, since there's already a timestamp
        in the signature field.  Sounds like a better job for a notation?
        But somebody may make a good argument to the contrary.
        Also, it's a bit odd that compressed data fields don't have
        timestamps in them but literal data fields do.

- - JDCC Note - Key-only signature that doesn't cover user name -
        I'm not sure what the semantics of this are,
        except perhaps they're useful for self-signatures
        or binding notation-based attributes to the key.
        You could just as well sign a key with the user name
        and ignore the user name when using the key?
        On the other hand, if you want the feature,
        it probably needs to be a separate signature type
        so you know not to include the hash of the user name.

- - 5.3 Conventionally Encrypted Session Key (Tag 3)
        It's a bit disappointing that this uses an all-zero IV,
        but it's presumably already implemented.
        The problem is that it gives an octet of relatively-well-known
        plaintext in the encrypted session key - the algorithm ID.
        It's not much use for a Bad Guy, but it's there.

- - 5.5 Key Material Packet
        Some good BNF descriptions would really help here.

- - 5.5.2 - Public Key Packet Formats
        Implementations SHOULD accept V3 public key packets and
        MUST accept V4 public key packets?

        Another minor weakness with V3 keys is that the validity period
        is limited to 64k days (assuming unsigned short?),
        and some applications may find 200 years a bit limiting :-)
        More importantly, it doesn't allow defining keys with
        very short expiration times, e.g. 1 hour or 30 seconds.

        V4 keys 
        - The Y2038 problem is here too...
        - Is this a good place to specify that implementations
        MUST support DSA and El-Gamal, and SHOULD support RSA?

- - 5.5.3 - Secret Key Packet Formats 
        - Does this belong in the standard?  Is the Secret Key Packet 
        ever transmitted outside the implementation?
        Or is it really an implementation detail that doesn't need 
        to be part of a standard?  I agree that it's convenient to 
        read your PGP Version N secret keyring with PGP Version N+1,
        but to me that only rates a SHOULD and not a MUST.  
        In particular, there may be environments in which the 
        applications don't store their secret keys in files, 
        and don't transmit them to anyone, especially for 
        transient communications applications,
        and there are applications that want more security than the 
        standard PGP implementation uses for storing its secret keys
        (e.g. the UserName is visible in the secret key ring.)
        Also, there may be applications that only need to 
        verify signatures, or only need to public-key encrypt data, 
        or maybe even only need to symmetric-key encrypt data, 
        but don't need to public-key decrypt or sign data, 
        and it would be nice for them to say they're OpenPGP compliant.

        - Does "CFB" refer to standard CFB, or PGP-hacked CFB-variant?

- - 5.6 - Compressed Data Packet (Tag 8)
        According to section 7.2, a Compressed Data Packet
        should be decompressible into a valid OpenPGP message,
        while this section only specifies that it contain
        an RFC1951 DEFLATE block containing "some set of packets".
        The spec should state at this point that the contents
        of the DEFLATE block must be a valid OpenPGP message,
        or more precisely, that 
        an OpenPGP program writing a Compressed Data Packet 
        MUST use a valid OpenPGP message as the contents, and that 
        an OpenPGP program reading a Compressed Data Packet 
        SHOULD assume that the decompressed contents are valid
        and attempt to interpret them.

- - 5.7 - Symmetrically Encrypted Data Packet (Tag 9)
        Will this packet _always_ contain either a literal or compressed?
        Or will it at least always contain some PGP packets?
        (For instance, you might use it to encrypt secret keys....)
        Should OP be _required_ to always interpret any PGP packets in it?

- - 5.8 - Should this now say "NA" or "OP" or "McAfee" :-)

- - 5.9 - Literal Data Packet (Tag 11)
        - Is it "__CONSOLE" or "_CONSOLE" (I assume one _, but it's
        easy for underscores to get kerned together.)
        - Perhaps the example should mention displaying on a CRT
        as well as not saving it on a disk?
        - Y2038 time problems again.
        - The semantics are arbitrary and the syntax doesn't
        indicate which choice was the sender made here - if anyone cares.
        - Implements SHOULD NOT believe what they read :-)

- - 5.10 - Trust Packet (Tag 12)
        Since these packets aren't exported and shouldn't be imported,
        it's not clear this belongs in the standard.
        The trust packet and the trust signature subpacket in 5.2.2.2
        both have complex semantics that aren't very well documented.
        At least these are internal-use only, though, so who cares?
        I agree that they should be implementation-dependent.
        
        I also agree that the trust packet should be signed by the user -
        but the standards document has not yet told us where the
        trust packet is syntactically - is it attached to one key,
        in which case there's a key to self-sign with?
        Is it free-floating in the public key file (more likely)?
        (In which case there's no "self" to self-sign them...).
        It's even worse than it appears - other people's public keys
        are used in a context where you're either encrypting to them,
        or checking the validity of their signatures, so there's
        no need to use anybody's private keys to be able to check against,
        and the instance of PGP may not even have any private key at all.
        An implementation might require a private key to unlock a 
        secret key ring without too much annoyance, but doing so to
        unlock the pubkey file seems a bit paranoid.

- - 5.11 - UserID / UserName / User Data
        I'd suggest the term "User Data".  Unlike "User ID" or "User Name",
        it doesn't imply the "True Name" or "One Key, One Body" model
        of how public keys are used - but it does imply that the data is 
        picked by the user, which is not only a less authoritarian model,
        but more reflective of reality than some of the other terms.
        It also makes it potentially less clear what the certifier
        is certifying, but that also reflects reality.

        Requiring UTF-8 is probably not bad - we need to be sure the field
        always gets protected if it's being transmitted across
        non-8-bit-safe media, which gets back to the armor-vs-mime wars.
        We should at least require that a conforming implementation
        MUST NOT munge the string except in automatically reversible ways
        (such as MIME-Quoted-Printable or armoring the whole thing),
        and should do any key-related transactions in full-8-bit.

        There is one security-related problem of permitting
        arbitrary characters - users can put newlines in their key strings,
        or backspaces, or ANSI terminal-control escape sequences,
        or other things that can encourage the user interface to lie
        to the unsuspecting recipient.  Banning those might be good.

- - 6.1 - Public-Key Algorithm Constants
        Elliptic Curve - Yeah, they probably deserve some numbers.
        Perhaps reserve 20-29 for future Elliptic Curve.
        Leaving ElGamal signatures unmentioned is probably good,
        but if you want to use them, anybody seeing the "16" for
        ElGamal in a signature context ought to get the idea.
        ElGamal signatures and DSA signatures both have subliminal
        channel problems; perhaps we should allocate some symmetric-key
        algorithm identifiers for those :-)

- - 6.2 - Symmetric-Key Algorithm Identifiers
        By the way, how DOES PGP generate 3-key 3DES keys, since
        168 bits of key is just bigger than a 160-bit hash?
        Or does it use 2-key only?  S2K is limited to the hash length.

- - 7 - Packet Composition 
        My preference is to have this section up front.

- - 7.1 - Transferable Public Keys 
        The BNF needs to be beefed up.  In particular,
        if each Subkey can be followed by one or more revocation sigs
        as well as one or more normal signatures.
        Also, are the signatures on the Subkeys required?
        Are they required to be self-signed by the preceding public key?
        
        Again, my recommendation of the term "User Data" for "UserID".

        JDCC's note near the end of section 5.2.2.2 on 
        revocable User Data is in scope at this point.
        The syntax looks very clearly like a revocation signature
        immediately following the user data would apply to that data,
        rather than to the whole key, and it calls for zero or more packets
        so there's clearly room.  The catch is making sure the
        implementation doesn't choke when seeing a revocation instead
        of either a signature or a subkey.  I would definitely recommend
        that if a implementation sees a revocation sig immediately following
        a User Data field, that it MAY/SHOULD revoke that User Data,
        though the meaning of "revoke" may not be precisely defined. :-)
        On the other hand, it's probably too early to generate such
        (certainly needs testing with popular implementations first.)

        On the other hand, there's the operational queston of what
        revoking a User Data means.  It probably means that 
        PGP should notify the user before trying to use that key
        with that name.  But signatures are signed by keys,
        not by names, so rejecting signatures by that key when
        there are other User Data fields active is a mistake.
        And PGP 5.0 doesn't always tell you who signed some key anyway.
        If a Key/UserData pair is signed by a certifier's key,
        and you receive a revocation for that UserData signed by 
        the certifier's key, you SHOULD discard or ignore the certification.

- - 7.2 - BNF should go a layer or two deeper.

- - 8 Key Formats -
        This appears to overlap substantially with 7.1.  Why both?
        Also, 7.1 permits zero or more subkeys, while 8 V4 requires one.
        Can the number be zero?  Or more than one?

- - 8.2 KeyIDs and Fingerprints
        Probably should also repeat the V3 fingerprint format here.
        It's also worth noting that the KeyID and fingerprint 
        are both calculated rather than stored in the data;
        implementations may choose to cache this information for
        internal use, though there's no mechanism for export/import,
        and keyservers would definitely want to.

- - 9 - Security Considerations
        Traffic analysis should be mentioned here, since PGP does
        little to stop it and doesn't have stealth built in.

        Talking about the fingerprint hacks may be useful here.

===============================================================================
=
-----BEGIN PGP SIGNATURE-----
Version: PGP for Personal Privacy 5.0
Charset: noconv

iQBVAwUBNIU6H/thU5e7emAFAQGOVAH7BWXLYorrBwaXohonVC1cg0R53nMgOrX1
PfvQ0EcmEIhjqf3GJ8Z7cL5z98oT3Gl5BN8+rR7+iN3/S+EfZezf2w==
=fzBe
-----END PGP SIGNATURE-----

                                Thanks! 
                                        Bill
Bill Stewart, stewarts(_at_)ix(_dot_)netcom(_dot_)com
Regular Key PGP Fingerprint D454 E202 CBC8 40BF  3C85 B884 0ABE 4639