tech-invite   World Map     

3GPP     Specs     Glossaries     Architecture     IMS     UICC       IETF     RFCs     Groups     SIP     ABNFs       Search

RFC 4880

 
 
 

OpenPGP Message Format

Part 3 of 5, p. 38 to 59
Prev RFC Part       Next RFC Part

 


prevText      Top      Up      ToC       Page 38 
5.3.  Symmetric-Key Encrypted Session Key Packets (Tag 3)

   The Symmetric-Key Encrypted Session Key packet holds the
   symmetric-key encryption of a session key used to encrypt a message.
   Zero or more Public-Key Encrypted Session Key packets and/or
   Symmetric-Key Encrypted Session Key packets may precede a
   Symmetrically Encrypted Data packet that holds an encrypted message.
   The message is encrypted with a session key, and the session key is
   itself encrypted and stored in the Encrypted Session Key packet or
   the Symmetric-Key Encrypted Session Key packet.

Top      Up      ToC       Page 39 
   If the Symmetrically Encrypted Data packet is preceded by one or
   more Symmetric-Key Encrypted Session Key packets, each specifies a
   passphrase that may be used to decrypt the message.  This allows a
   message to be encrypted to a number of public keys, and also to one
   or more passphrases.  This packet type is new and is not generated
   by PGP 2.x or PGP 5.0.

   The body of this packet consists of:

     - A one-octet version number.  The only currently defined version
       is 4.

     - A one-octet number describing the symmetric algorithm used.

     - A string-to-key (S2K) specifier, length as defined above.

     - Optionally, the encrypted session key itself, which is decrypted
       with the string-to-key object.

   If the encrypted session key is not present (which can be detected
   on the basis of packet length and S2K specifier size), then the S2K
   algorithm applied to the passphrase produces the session key for
   decrypting the file, using the symmetric cipher algorithm from the
   Symmetric-Key Encrypted Session Key packet.

   If the encrypted session key is present, the result of applying the
   S2K algorithm to the passphrase is used to decrypt just that
   encrypted session key field, using CFB mode with an IV of all zeros.
   The decryption result consists of a one-octet algorithm identifier
   that specifies the symmetric-key encryption algorithm used to
   encrypt the following Symmetrically Encrypted Data packet, followed
   by the session key octets themselves.

   Note: because an all-zero IV is used for this decryption, the S2K
   specifier MUST use a salt value, either a Salted S2K or an
   Iterated-Salted S2K.  The salt value will ensure that the decryption
   key is not repeated even if the passphrase is reused.

5.4.  One-Pass Signature Packets (Tag 4)

   The One-Pass Signature packet precedes the signed data and contains
   enough information to allow the receiver to begin calculating any
   hashes needed to verify the signature.  It allows the Signature
   packet to be placed at the end of the message, so that the signer
   can compute the entire signed message in one pass.

   A One-Pass Signature does not interoperate with PGP 2.6.x or
   earlier.

Top      Up      ToC       Page 40 
   The body of this packet consists of:

     - A one-octet version number.  The current version is 3.

     - A one-octet signature type.  Signature types are described in
       Section 5.2.1.

     - A one-octet number describing the hash algorithm used.

     - A one-octet number describing the public-key algorithm used.

     - An eight-octet number holding the Key ID of the signing key.

     - A one-octet number holding a flag showing whether the signature
       is nested.  A zero value indicates that the next packet is
       another One-Pass Signature packet that describes another
       signature to be applied to the same message data.

   Note that if a message contains more than one one-pass signature,
   then the Signature packets bracket the message; that is, the first
   Signature packet after the message corresponds to the last one-pass
   packet and the final Signature packet corresponds to the first
   one-pass packet.

5.5.  Key Material Packet

   A key material packet contains all the information about a public or
   private key.  There are four variants of this packet type, and two
   major versions.  Consequently, this section is complex.

5.5.1.  Key Packet Variants

5.5.1.1.  Public-Key Packet (Tag 6)

   A Public-Key packet starts a series of packets that forms an OpenPGP
   key (sometimes called an OpenPGP certificate).

5.5.1.2.  Public-Subkey Packet (Tag 14)

   A Public-Subkey packet (tag 14) has exactly the same format as a
   Public-Key packet, but denotes a subkey.  One or more subkeys may be
   associated with a top-level key.  By convention, the top-level key
   provides signature services, and the subkeys provide encryption
   services.

   Note: in PGP 2.6.x, tag 14 was intended to indicate a comment
   packet.  This tag was selected for reuse because no previous version
   of PGP ever emitted comment packets but they did properly ignore

Top      Up      ToC       Page 41 
   them.  Public-Subkey packets are ignored by PGP 2.6.x and do not
   cause it to fail, providing a limited degree of backward
   compatibility.

5.5.1.3.  Secret-Key Packet (Tag 5)

   A Secret-Key packet contains all the information that is found in a
   Public-Key packet, including the public-key material, but also
   includes the secret-key material after all the public-key fields.

5.5.1.4.  Secret-Subkey Packet (Tag 7)

   A Secret-Subkey packet (tag 7) is the subkey analog of the Secret
   Key packet and has exactly the same format.

5.5.2.  Public-Key Packet Formats

   There are two versions of key-material packets.  Version 3 packets
   were first generated by PGP 2.6.  Version 4 keys first appeared in
   PGP 5.0 and are the preferred key version for OpenPGP.

   OpenPGP implementations MUST create keys with version 4 format.  V3
   keys are deprecated; an implementation MUST NOT generate a V3 key,
   but MAY accept it.

   A version 3 public key or public-subkey packet contains:

     - A one-octet version number (3).

     - A four-octet number denoting the time that the key was created.

     - A two-octet number denoting the time in days that this key is
       valid.  If this number is zero, then it does not expire.

     - A one-octet number denoting the public-key algorithm of this key.

     - A series of multiprecision integers comprising the key material:

           - a multiprecision integer (MPI) of RSA public modulus n;

           - an MPI of RSA public encryption exponent e.

   V3 keys are deprecated.  They contain three weaknesses.  First, it is
   relatively easy to construct a V3 key that has the same Key ID as any
   other key because the Key ID is simply the low 64 bits of the public
   modulus.  Secondly, because the fingerprint of a V3 key hashes the
   key material, but not its length, there is an increased opportunity
   for fingerprint collisions.  Third, there are weaknesses in the MD5

Top      Up      ToC       Page 42 
   hash algorithm that make developers prefer other algorithms.  See
   below for a fuller discussion of Key IDs and fingerprints.

   V2 keys are identical to the deprecated V3 keys except for the
   version number.  An implementation MUST NOT generate them and MAY
   accept or reject them as it sees fit.

   The version 4 format is similar to the version 3 format except for
   the absence of a validity period.  This has been moved to the
   Signature packet.  In addition, fingerprints of version 4 keys are
   calculated differently from version 3 keys, as described in the
   section "Enhanced Key Formats".

   A version 4 packet contains:

     - A one-octet version number (4).

     - A four-octet number denoting the time that the key was created.

     - A one-octet number denoting the public-key algorithm of this key.

     - A series of multiprecision integers comprising the key material.
       This algorithm-specific portion is:

       Algorithm-Specific Fields for RSA public keys:

         - multiprecision integer (MPI) of RSA public modulus n;

         - MPI of RSA public encryption exponent e.

       Algorithm-Specific Fields for DSA public keys:

         - MPI of DSA prime p;

         - MPI of DSA group order q (q is a prime divisor of p-1);

         - MPI of DSA group generator g;

         - MPI of DSA public-key value y (= g**x mod p where x
           is secret).

       Algorithm-Specific Fields for Elgamal public keys:

         - MPI of Elgamal prime p;

         - MPI of Elgamal group generator g;

Top      Up      ToC       Page 43 
         - MPI of Elgamal public key value y (= g**x mod p where x
           is secret).

5.5.3.  Secret-Key Packet Formats

   The Secret-Key and Secret-Subkey packets contain all the data of the
   Public-Key and Public-Subkey packets, with additional algorithm-
   specific secret-key data appended, usually in encrypted form.

   The packet contains:

     - A Public-Key or Public-Subkey packet, as described above.

     - One octet indicating string-to-key usage conventions.  Zero
       indicates that the secret-key data is not encrypted.  255 or 254
       indicates that a string-to-key specifier is being given.  Any
       other value is a symmetric-key encryption algorithm identifier.

     - [Optional] If string-to-key usage octet was 255 or 254, a one-
       octet symmetric encryption algorithm.

     - [Optional] If string-to-key usage octet was 255 or 254, a
       string-to-key specifier.  The length of the string-to-key
       specifier is implied by its type, as described above.

     - [Optional] If secret data is encrypted (string-to-key usage octet
       not zero), an Initial Vector (IV) of the same length as the
       cipher's block size.

     - Plain or encrypted multiprecision integers comprising the secret
       key data.  These algorithm-specific fields are as described
       below.

     - If the string-to-key usage octet is zero or 255, then a two-octet
       checksum of the plaintext of the algorithm-specific portion (sum
       of all octets, mod 65536).  If the string-to-key usage octet was
       254, then a 20-octet SHA-1 hash of the plaintext of the
       algorithm-specific portion.  This checksum or hash is encrypted
       together with the algorithm-specific fields (if string-to-key
       usage octet is not zero).  Note that for all other values, a
       two-octet checksum is required.

       Algorithm-Specific Fields for RSA secret keys:

       - multiprecision integer (MPI) of RSA secret exponent d.

       - MPI of RSA secret prime value p.

Top      Up      ToC       Page 44 
       - MPI of RSA secret prime value q (p < q).

       - MPI of u, the multiplicative inverse of p, mod q.

       Algorithm-Specific Fields for DSA secret keys:

       - MPI of DSA secret exponent x.

       Algorithm-Specific Fields for Elgamal secret keys:

       - MPI of Elgamal secret exponent x.

   Secret MPI values can be encrypted using a passphrase.  If a string-
   to-key specifier is given, that describes the algorithm for
   converting the passphrase to a key, else a simple MD5 hash of the
   passphrase is used.  Implementations MUST use a string-to-key
   specifier; the simple hash is for backward compatibility and is
   deprecated, though implementations MAY continue to use existing
   private keys in the old format.  The cipher for encrypting the MPIs
   is specified in the Secret-Key packet.

   Encryption/decryption of the secret data is done in CFB mode using
   the key created from the passphrase and the Initial Vector from the
   packet.  A different mode is used with V3 keys (which are only RSA)
   than with other key formats.  With V3 keys, the MPI bit count prefix
   (i.e., the first two octets) is not encrypted.  Only the MPI non-
   prefix data is encrypted.  Furthermore, the CFB state is
   resynchronized at the beginning of each new MPI value, so that the
   CFB block boundary is aligned with the start of the MPI data.

   With V4 keys, a simpler method is used.  All secret MPI values are
   encrypted in CFB mode, including the MPI bitcount prefix.

   The two-octet checksum that follows the algorithm-specific portion is
   the algebraic sum, mod 65536, of the plaintext of all the algorithm-
   specific octets (including MPI prefix and data).  With V3 keys, the
   checksum is stored in the clear.  With V4 keys, the checksum is
   encrypted like the algorithm-specific data.  This value is used to
   check that the passphrase was correct.  However, this checksum is
   deprecated; an implementation SHOULD NOT use it, but should rather
   use the SHA-1 hash denoted with a usage octet of 254.  The reason for
   this is that there are some attacks that involve undetectably
   modifying the secret key.

Top      Up      ToC       Page 45 
5.6.  Compressed Data Packet (Tag 8)

   The Compressed Data packet contains compressed data.  Typically, this
   packet is found as the contents of an encrypted packet, or following
   a Signature or One-Pass Signature packet, and contains a literal data
   packet.

   The body of this packet consists of:

     - One octet that gives the algorithm used to compress the packet.

     - Compressed data, which makes up the remainder of the packet.

   A Compressed Data Packet's body contains an block that compresses
   some set of packets.  See section "Packet Composition" for details on
   how messages are formed.

   ZIP-compressed packets are compressed with raw RFC 1951 [RFC1951]
   DEFLATE blocks.  Note that PGP V2.6 uses 13 bits of compression.  If
   an implementation uses more bits of compression, PGP V2.6 cannot
   decompress it.

   ZLIB-compressed packets are compressed with RFC 1950 [RFC1950] ZLIB-
   style blocks.

   BZip2-compressed packets are compressed using the BZip2 [BZ2]
   algorithm.

5.7.  Symmetrically Encrypted Data Packet (Tag 9)

   The Symmetrically Encrypted Data packet contains data encrypted with
   a symmetric-key algorithm.  When it has been decrypted, it contains
   other packets (usually a literal data packet or compressed data
   packet, but in theory other Symmetrically Encrypted Data packets or
   sequences of packets that form whole OpenPGP messages).

   The body of this packet consists of:

     - Encrypted data, the output of the selected symmetric-key cipher
       operating in OpenPGP's variant of Cipher Feedback (CFB) mode.

   The symmetric cipher used may be specified in a Public-Key or
   Symmetric-Key Encrypted Session Key packet that precedes the
   Symmetrically Encrypted Data packet.  In that case, the cipher
   algorithm octet is prefixed to the session key before it is
   encrypted.  If no packets of these types precede the encrypted data,
   the IDEA algorithm is used with the session key calculated as the MD5
   hash of the passphrase, though this use is deprecated.

Top      Up      ToC       Page 46 
   The data is encrypted in CFB mode, with a CFB shift size equal to the
   cipher's block size.  The Initial Vector (IV) is specified as all
   zeros.  Instead of using an IV, OpenPGP prefixes a string of length
   equal to the block size of the cipher plus two to the data before it
   is encrypted.  The first block-size octets (for example, 8 octets for
   a 64-bit block length) are random, and the following two octets are
   copies of the last two octets of the IV.  For example, in an 8-octet
   block, octet 9 is a repeat of octet 7, and octet 10 is a repeat of
   octet 8.  In a cipher of length 16, octet 17 is a repeat of octet 15
   and octet 18 is a repeat of octet 16.  As a pedantic clarification,
   in both these examples, we consider the first octet to be numbered 1.

   After encrypting the first block-size-plus-two octets, the CFB state
   is resynchronized.  The last block-size octets of ciphertext are
   passed through the cipher and the block boundary is reset.

   The repetition of 16 bits in the random data prefixed to the message
   allows the receiver to immediately check whether the session key is
   incorrect.  See the "Security Considerations" section for hints on
   the proper use of this "quick check".

5.8.  Marker Packet (Obsolete Literal Packet) (Tag 10)

   An experimental version of PGP used this packet as the Literal
   packet, but no released version of PGP generated Literal packets with
   this tag.  With PGP 5.x, this packet has been reassigned and is
   reserved for use as the Marker packet.

   The body of this packet consists of:

     - The three octets 0x50, 0x47, 0x50 (which spell "PGP" in UTF-8).

   Such a packet MUST be ignored when received.  It may be placed at the
   beginning of a message that uses features not available in PGP 2.6.x
   in order to cause that version to report that newer software is
   necessary to process the message.

5.9.  Literal Data Packet (Tag 11)

   A Literal Data packet contains the body of a message; data that is
   not to be further interpreted.

   The body of this packet consists of:

     - A one-octet field that describes how the data is formatted.

Top      Up      ToC       Page 47 
   If it is a 'b' (0x62), then the Literal packet contains binary data.
   If it is a 't' (0x74), then it contains text data, and thus may need
   line ends converted to local form, or other text-mode changes.  The
   tag 'u' (0x75) means the same as 't', but also indicates that
   implementation believes that the literal data contains UTF-8 text.

   Early versions of PGP also defined a value of 'l' as a 'local' mode
   for machine-local conversions.  RFC 1991 [RFC1991] incorrectly stated
   this local mode flag as '1' (ASCII numeral one).  Both of these local
   modes are deprecated.

     - File name as a string (one-octet length, followed by a file
       name).  This may be a zero-length string.  Commonly, if the
       source of the encrypted data is a file, this will be the name of
       the encrypted file.  An implementation MAY consider the file name
       in the Literal packet to be a more authoritative name than the
       actual file name.

   If the special name "_CONSOLE" is used, the message is considered to
   be "for your eyes only".  This advises that the message data is
   unusually sensitive, and the receiving program should process it more
   carefully, perhaps avoiding storing the received data to disk, for
   example.

     - A four-octet number that indicates a date associated with the
       literal data.  Commonly, the date might be the modification date
       of a file, or the time the packet was created, or a zero that
       indicates no specific time.

     - The remainder of the packet is literal data.

       Text data is stored with <CR><LF> text endings (i.e., network-
       normal line endings).  These should be converted to native line
       endings by the receiving software.

5.10.  Trust Packet (Tag 12)

   The Trust packet is used only within keyrings and is not normally
   exported.  Trust packets contain data that record the user's
   specifications of which key holders are trustworthy introducers,
   along with other information that implementing software uses for
   trust information.  The format of Trust packets is defined by a given
   implementation.

   Trust packets SHOULD NOT be emitted to output streams that are
   transferred to other users, and they SHOULD be ignored on any input
   other than local keyring files.

Top      Up      ToC       Page 48 
5.11.  User ID Packet (Tag 13)

   A User ID packet consists of UTF-8 text that is intended to represent
   the name and email address of the key holder.  By convention, it
   includes an RFC 2822 [RFC2822] mail name-addr, but there are no
   restrictions on its content.  The packet length in the header
   specifies the length of the User ID.

5.12.  User Attribute Packet (Tag 17)

   The User Attribute packet is a variation of the User ID packet.  It
   is capable of storing more types of data than the User ID packet,
   which is limited to text.  Like the User ID packet, a User Attribute
   packet may be certified by the key owner ("self-signed") or any other
   key owner who cares to certify it.  Except as noted, a User Attribute
   packet may be used anywhere that a User ID packet may be used.

   While User Attribute packets are not a required part of the OpenPGP
   standard, implementations SHOULD provide at least enough
   compatibility to properly handle a certification signature on the
   User Attribute packet.  A simple way to do this is by treating the
   User Attribute packet as a User ID packet with opaque contents, but
   an implementation may use any method desired.

   The User Attribute packet is made up of one or more attribute
   subpackets.  Each subpacket consists of a subpacket header and a
   body.  The header consists of:

     - the subpacket length (1, 2, or 5 octets)

     - the subpacket type (1 octet)

   and is followed by the subpacket specific data.

   The only currently defined subpacket type is 1, signifying an image.
   An implementation SHOULD ignore any subpacket of a type that it does
   not recognize.  Subpacket types 100 through 110 are reserved for
   private or experimental use.

5.12.1.  The Image Attribute Subpacket

   The Image Attribute subpacket is used to encode an image, presumably
   (but not required to be) that of the key owner.

   The Image Attribute subpacket begins with an image header.  The first
   two octets of the image header contain the length of the image
   header.  Note that unlike other multi-octet numerical values in this
   document, due to a historical accident this value is encoded as a

Top      Up      ToC       Page 49 
   little-endian number.  The image header length is followed by a
   single octet for the image header version.  The only currently
   defined version of the image header is 1, which is a 16-octet image
   header.  The first three octets of a version 1 image header are thus
   0x10, 0x00, 0x01.

   The fourth octet of a version 1 image header designates the encoding
   format of the image.  The only currently defined encoding format is
   the value 1 to indicate JPEG.  Image format types 100 through 110 are
   reserved for private or experimental use.  The rest of the version 1
   image header is made up of 12 reserved octets, all of which MUST be
   set to 0.

   The rest of the image subpacket contains the image itself.  As the
   only currently defined image type is JPEG, the image is encoded in
   the JPEG File Interchange Format (JFIF), a standard file format for
   JPEG images [JFIF].

   An implementation MAY try to determine the type of an image by
   examination of the image data if it is unable to handle a particular
   version of the image header or if a specified encoding format value
   is not recognized.

5.13.  Sym. Encrypted Integrity Protected Data Packet (Tag 18)

   The Symmetrically Encrypted Integrity Protected Data packet is a
   variant of the Symmetrically Encrypted Data packet.  It is a new
   feature created for OpenPGP that addresses the problem of detecting a
   modification to encrypted data.  It is used in combination with a
   Modification Detection Code packet.

   There is a corresponding feature in the features Signature subpacket
   that denotes that an implementation can properly use this packet
   type.  An implementation MUST support decrypting these packets and
   SHOULD prefer generating them to the older Symmetrically Encrypted
   Data packet when possible.  Since this data packet protects against
   modification attacks, this standard encourages its proliferation.
   While blanket adoption of this data packet would create
   interoperability problems, rapid adoption is nevertheless important.
   An implementation SHOULD specifically denote support for this packet,
   but it MAY infer it from other mechanisms.

   For example, an implementation might infer from the use of a cipher
   such as Advanced Encryption Standard (AES) or Twofish that a user
   supports this feature.  It might place in the unhashed portion of
   another user's key signature a Features subpacket.  It might also
   present a user with an opportunity to regenerate their own self-
   signature with a Features subpacket.

Top      Up      ToC       Page 50 
   This packet contains data encrypted with a symmetric-key algorithm
   and protected against modification by the SHA-1 hash algorithm.  When
   it has been decrypted, it will typically contain other packets (often
   a Literal Data packet or Compressed Data packet).  The last decrypted
   packet in this packet's payload MUST be a Modification Detection Code
   packet.

   The body of this packet consists of:

     - A one-octet version number.  The only currently defined value is
       1.

     - Encrypted data, the output of the selected symmetric-key cipher
       operating in Cipher Feedback mode with shift amount equal to the
       block size of the cipher (CFB-n where n is the block size).

   The symmetric cipher used MUST be specified in a Public-Key or
   Symmetric-Key Encrypted Session Key packet that precedes the
   Symmetrically Encrypted Data packet.  In either case, the cipher
   algorithm octet is prefixed to the session key before it is
   encrypted.

   The data is encrypted in CFB mode, with a CFB shift size equal to the
   cipher's block size.  The Initial Vector (IV) is specified as all
   zeros.  Instead of using an IV, OpenPGP prefixes an octet string to
   the data before it is encrypted.  The length of the octet string
   equals the block size of the cipher in octets, plus two.  The first
   octets in the group, of length equal to the block size of the cipher,
   are random; the last two octets are each copies of their 2nd
   preceding octet.  For example, with a cipher whose block size is 128
   bits or 16 octets, the prefix data will contain 16 random octets,
   then two more octets, which are copies of the 15th and 16th octets,
   respectively.  Unlike the Symmetrically Encrypted Data Packet, no
   special CFB resynchronization is done after encrypting this prefix
   data.  See "OpenPGP CFB Mode" below for more details.

   The repetition of 16 bits in the random data prefixed to the message
   allows the receiver to immediately check whether the session key is
   incorrect.

   The plaintext of the data to be encrypted is passed through the SHA-1
   hash function, and the result of the hash is appended to the
   plaintext in a Modification Detection Code packet.  The input to the
   hash function includes the prefix data described above; it includes
   all of the plaintext, and then also includes two octets of values
   0xD3, 0x14.  These represent the encoding of a Modification Detection
   Code packet tag and length field of 20 octets.

Top      Up      ToC       Page 51 
   The resulting hash value is stored in a Modification Detection Code
   (MDC) packet, which MUST use the two octet encoding just given to
   represent its tag and length field.  The body of the MDC packet is
   the 20-octet output of the SHA-1 hash.

   The Modification Detection Code packet is appended to the plaintext
   and encrypted along with the plaintext using the same CFB context.

   During decryption, the plaintext data should be hashed with SHA-1,
   including the prefix data as well as the packet tag and length field
   of the Modification Detection Code packet.  The body of the MDC
   packet, upon decryption, is compared with the result of the SHA-1
   hash.

   Any failure of the MDC indicates that the message has been modified
   and MUST be treated as a security problem.  Failures include a
   difference in the hash values, but also the absence of an MDC packet,
   or an MDC packet in any position other than the end of the plaintext.
   Any failure SHOULD be reported to the user.

   Note: future designs of new versions of this packet should consider
   rollback attacks since it will be possible for an attacker to change
   the version back to 1.

      NON-NORMATIVE EXPLANATION

      The MDC system, as packets 18 and 19 are called, were created to
      provide an integrity mechanism that is less strong than a
      signature, yet stronger than bare CFB encryption.

      It is a limitation of CFB encryption that damage to the ciphertext
      will corrupt the affected cipher blocks and the block following.
      Additionally, if data is removed from the end of a CFB-encrypted
      block, that removal is undetectable.  (Note also that CBC mode has
      a similar limitation, but data removed from the front of the block
      is undetectable.)

      The obvious way to protect or authenticate an encrypted block is
      to digitally sign it.  However, many people do not wish to
      habitually sign data, for a large number of reasons beyond the
      scope of this document.  Suffice it to say that many people
      consider properties such as deniability to be as valuable as
      integrity.

      OpenPGP addresses this desire to have more security than raw
      encryption and yet preserve deniability with the MDC system.  An
      MDC is intentionally not a MAC.  Its name was not selected by
      accident.  It is analogous to a checksum.

Top      Up      ToC       Page 52 
      Despite the fact that it is a relatively modest system, it has
      proved itself in the real world.  It is an effective defense to
      several attacks that have surfaced since it has been created.  It
      has met its modest goals admirably.

      Consequently, because it is a modest security system, it has
      modest requirements on the hash function(s) it employs.  It does
      not rely on a hash function being collision-free, it relies on a
      hash function being one-way.  If a forger, Frank, wishes to send
      Alice a (digitally) unsigned message that says, "I've always
      secretly loved you, signed Bob", it is far easier for him to
      construct a new message than it is to modify anything intercepted
      from Bob.  (Note also that if Bob wishes to communicate secretly
      with Alice, but without authentication or identification and with
      a threat model that includes forgers, he has a problem that
      transcends mere cryptography.)

      Note also that unlike nearly every other OpenPGP subsystem, there
      are no parameters in the MDC system.  It hard-defines SHA-1 as its
      hash function.  This is not an accident.  It is an intentional
      choice to avoid downgrade and cross-grade attacks while making a
      simple, fast system.  (A downgrade attack would be an attack that
      replaced SHA-256 with SHA-1, for example.  A cross-grade attack
      would replace SHA-1 with another 160-bit hash, such as RIPE-
      MD/160, for example.)

      However, given the present state of hash function cryptanalysis
      and cryptography, it may be desirable to upgrade the MDC system to
      a new hash function.  See Section 13.11 in the "IANA
      Considerations" for guidance.

5.14.  Modification Detection Code Packet (Tag 19)

   The Modification Detection Code packet contains a SHA-1 hash of
   plaintext data, which is used to detect message modification.  It is
   only used with a Symmetrically Encrypted Integrity Protected Data
   packet.  The Modification Detection Code packet MUST be the last
   packet in the plaintext data that is encrypted in the Symmetrically
   Encrypted Integrity Protected Data packet, and MUST appear in no
   other place.

   A Modification Detection Code packet MUST have a length of 20 octets.

Top      Up      ToC       Page 53 
   The body of this packet consists of:

     - A 20-octet SHA-1 hash of the preceding plaintext data of the
       Symmetrically Encrypted Integrity Protected Data packet,
       including prefix data, the tag octet, and length octet of the
       Modification Detection Code packet.

   Note that the Modification Detection Code packet MUST always use a
   new format encoding of the packet tag, and a one-octet encoding of
   the packet length.  The reason for this is that the hashing rules for
   modification detection include a one-octet tag and one-octet length
   in the data hash.  While this is a bit restrictive, it reduces
   complexity.

6.  Radix-64 Conversions

   As stated in the introduction, OpenPGP's underlying native
   representation for objects is a stream of arbitrary octets, and some
   systems desire these objects to be immune to damage caused by
   character set translation, data conversions, etc.

   In principle, any printable encoding scheme that met the requirements
   of the unsafe channel would suffice, since it would not change the
   underlying binary bit streams of the native OpenPGP data structures.
   The OpenPGP standard specifies one such printable encoding scheme to
   ensure interoperability.

   OpenPGP's Radix-64 encoding is composed of two parts: a base64
   encoding of the binary data and a checksum.  The base64 encoding is
   identical to the MIME base64 content-transfer-encoding [RFC2045].

   The checksum is a 24-bit Cyclic Redundancy Check (CRC) converted to
   four characters of radix-64 encoding by the same MIME base64
   transformation, preceded by an equal sign (=).  The CRC is computed
   by using the generator 0x864CFB and an initialization of 0xB704CE.
   The accumulation is done on the data before it is converted to
   radix-64, rather than on the converted data.  A sample implementation
   of this algorithm is in the next section.

   The checksum with its leading equal sign MAY appear on the first line
   after the base64 encoded data.

   Rationale for CRC-24: The size of 24 bits fits evenly into printable
   base64.  The nonzero initialization can detect more errors than a
   zero initialization.

Top      Up      ToC       Page 54 
6.1.  An Implementation of the CRC-24 in "C"

      #define CRC24_INIT 0xB704CEL
      #define CRC24_POLY 0x1864CFBL

      typedef long crc24;
      crc24 crc_octets(unsigned char *octets, size_t len)
      {
          crc24 crc = CRC24_INIT;
          int i;
          while (len--) {
              crc ^= (*octets++) << 16;
              for (i = 0; i < 8; i++) {
                  crc <<= 1;
                  if (crc & 0x1000000)
                      crc ^= CRC24_POLY;
              }
          }
          return crc & 0xFFFFFFL;
      }

6.2.  Forming ASCII Armor

   When OpenPGP encodes data into ASCII Armor, it puts specific headers
   around the Radix-64 encoded data, so OpenPGP can reconstruct the data
   later.  An OpenPGP implementation MAY use ASCII armor to protect raw
   binary data.  OpenPGP informs the user what kind of data is encoded
   in the ASCII armor through the use of the headers.

   Concatenating the following data creates ASCII Armor:

     - An Armor Header Line, appropriate for the type of data

     - Armor Headers

     - A blank (zero-length, or containing only whitespace) line

     - The ASCII-Armored data

     - An Armor Checksum

     - The Armor Tail, which depends on the Armor Header Line

   An Armor Header Line consists of the appropriate header line text
   surrounded by five (5) dashes ('-', 0x2D) on either side of the
   header line text.  The header line text is chosen based upon the type
   of data that is being encoded in Armor, and how it is being encoded.
   Header line texts include the following strings:

Top      Up      ToC       Page 55 
   BEGIN PGP MESSAGE
       Used for signed, encrypted, or compressed files.

   BEGIN PGP PUBLIC KEY BLOCK
       Used for armoring public keys.

   BEGIN PGP PRIVATE KEY BLOCK
       Used for armoring private keys.

   BEGIN PGP MESSAGE, PART X/Y
       Used for multi-part messages, where the armor is split amongst Y
       parts, and this is the Xth part out of Y.

   BEGIN PGP MESSAGE, PART X
       Used for multi-part messages, where this is the Xth part of an
       unspecified number of parts.  Requires the MESSAGE-ID Armor
       Header to be used.

   BEGIN PGP SIGNATURE
       Used for detached signatures, OpenPGP/MIME signatures, and
       cleartext signatures.  Note that PGP 2.x uses BEGIN PGP MESSAGE
       for detached signatures.

   Note that all these Armor Header Lines are to consist of a complete
   line.  That is to say, there is always a line ending preceding the
   starting five dashes, and following the ending five dashes.  The
   header lines, therefore, MUST start at the beginning of a line, and
   MUST NOT have text other than whitespace following them on the same
   line.  These line endings are considered a part of the Armor Header
   Line for the purposes of determining the content they delimit.  This
   is particularly important when computing a cleartext signature (see
   below).

   The Armor Headers are pairs of strings that can give the user or the
   receiving OpenPGP implementation some information about how to decode
   or use the message.  The Armor Headers are a part of the armor, not a
   part of the message, and hence are not protected by any signatures
   applied to the message.

   The format of an Armor Header is that of a key-value pair.  A colon
   (':' 0x38) and a single space (0x20) separate the key and value.
   OpenPGP should consider improperly formatted Armor Headers to be
   corruption of the ASCII Armor.  Unknown keys should be reported to
   the user, but OpenPGP should continue to process the message.

   Note that some transport methods are sensitive to line length.  While
   there is a limit of 76 characters for the Radix-64 data (Section
   6.3), there is no limit to the length of Armor Headers.  Care should

Top      Up      ToC       Page 56 
   be taken that the Armor Headers are short enough to survive
   transport.  One way to do this is to repeat an Armor Header key
   multiple times with different values for each so that no one line is
   overly long.

   Currently defined Armor Header Keys are as follows:

     - "Version", which states the OpenPGP implementation and version
       used to encode the message.

     - "Comment", a user-defined comment.  OpenPGP defines all text to
       be in UTF-8.  A comment may be any UTF-8 string.  However, the
       whole point of armoring is to provide seven-bit-clean data.
       Consequently, if a comment has characters that are outside the
       US-ASCII range of UTF, they may very well not survive transport.

     - "MessageID", a 32-character string of printable characters.  The
       string must be the same for all parts of a multi-part message
       that uses the "PART X" Armor Header.  MessageID strings should be
       unique enough that the recipient of the mail can associate all
       the parts of a message with each other.  A good checksum or
       cryptographic hash function is sufficient.

       The MessageID SHOULD NOT appear unless it is in a multi-part
       message.  If it appears at all, it MUST be computed from the
       finished (encrypted, signed, etc.) message in a deterministic
       fashion, rather than contain a purely random value.  This is to
       allow the legitimate recipient to determine that the MessageID
       cannot serve as a covert means of leaking cryptographic key
       information.

     - "Hash", a comma-separated list of hash algorithms used in this
       message.  This is used only in cleartext signed messages.

     - "Charset", a description of the character set that the plaintext
       is in.  Please note that OpenPGP defines text to be in UTF-8.  An
       implementation will get best results by translating into and out
       of UTF-8.  However, there are many instances where this is easier
       said than done.  Also, there are communities of users who have no
       need for UTF-8 because they are all happy with a character set
       like ISO Latin-5 or a Japanese character set.  In such instances,
       an implementation MAY override the UTF-8 default by using this
       header key.  An implementation MAY implement this key and any
       translations it cares to; an implementation MAY ignore it and
       assume all text is UTF-8.

Top      Up      ToC       Page 57 
       The Armor Tail Line is composed in the same manner as the Armor
       Header Line, except the string "BEGIN" is replaced by the string
       "END".

6.3.  Encoding Binary in Radix-64

   The encoding process represents 24-bit groups of input bits as output
   strings of 4 encoded characters.  Proceeding from left to right, a
   24-bit input group is formed by concatenating three 8-bit input
   groups.  These 24 bits are then treated as four concatenated 6-bit
   groups, each of which is translated into a single digit in the
   Radix-64 alphabet.  When encoding a bit stream with the Radix-64
   encoding, the bit stream must be presumed to be ordered with the most
   significant bit first.  That is, the first bit in the stream will be
   the high-order bit in the first 8-bit octet, and the eighth bit will
   be the low-order bit in the first 8-bit octet, and so on.

         +--first octet--+-second octet--+--third octet--+
         |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|
         +-----------+---+-------+-------+---+-----------+
         |5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0|
         +--1.index--+--2.index--+--3.index--+--4.index--+

   Each 6-bit group is used as an index into an array of 64 printable
   characters from the table below.  The character referenced by the
   index is placed in the output string.

     Value Encoding  Value Encoding  Value Encoding  Value Encoding
         0 A            17 R            34 i            51 z
         1 B            18 S            35 j            52 0
         2 C            19 T            36 k            53 1
         3 D            20 U            37 l            54 2
         4 E            21 V            38 m            55 3
         5 F            22 W            39 n            56 4
         6 G            23 X            40 o            57 5
         7 H            24 Y            41 p            58 6
         8 I            25 Z            42 q            59 7
         9 J            26 a            43 r            60 8
        10 K            27 b            44 s            61 9
        11 L            28 c            45 t            62 +
        12 M            29 d            46 u            63 /
        13 N            30 e            47 v
        14 O            31 f            48 w         (pad) =
        15 P            32 g            49 x
        16 Q            33 h            50 y

   The encoded output stream must be represented in lines of no more
   than 76 characters each.

Top      Up      ToC       Page 58 
   Special processing is performed if fewer than 24 bits are available
   at the end of the data being encoded.  There are three possibilities:

   1. The last data group has 24 bits (3 octets).  No special processing
      is needed.

   2. The last data group has 16 bits (2 octets).  The first two 6-bit
      groups are processed as above.  The third (incomplete) data group
      has two zero-value bits added to it, and is processed as above.  A
      pad character (=) is added to the output.

   3. The last data group has 8 bits (1 octet).  The first 6-bit group
      is processed as above.  The second (incomplete) data group has
      four zero-value bits added to it, and is processed as above.  Two
      pad characters (=) are added to the output.

6.4.  Decoding Radix-64

   In Radix-64 data, characters other than those in the table, line
   breaks, and other white space probably indicate a transmission error,
   about which a warning message or even a message rejection might be
   appropriate under some circumstances.  Decoding software must ignore
   all white space.

   Because it is used only for padding at the end of the data, the
   occurrence of any "=" characters may be taken as evidence that the
   end of the data has been reached (without truncation in transit).  No
   such assurance is possible, however, when the number of octets
   transmitted was a multiple of three and no "=" characters are
   present.

Top      Up      ToC       Page 59 
6.5.  Examples of Radix-64

   Input data:  0x14FB9C03D97E
   Hex:     1   4    F   B    9   C     | 0   3    D   9    7   E
   8-bit:   00010100 11111011 10011100  | 00000011 11011001 11111110
   6-bit:   000101 001111 101110 011100 | 000000 111101 100111 111110
   Decimal: 5      15     46     28       0      61     37     62
   Output:  F      P      u      c        A      9      l      +
   Input data:  0x14FB9C03D9
   Hex:     1   4    F   B    9   C     | 0   3    D   9
   8-bit:   00010100 11111011 10011100  | 00000011 11011001
                                                   pad with 00
   6-bit:   000101 001111 101110 011100 | 000000 111101 100100
   Decimal: 5      15     46     28       0      61     36
                                                      pad with =
   Output:  F      P      u      c        A      9      k      =
   Input data:  0x14FB9C03
   Hex:     1   4    F   B    9   C     | 0   3
   8-bit:   00010100 11111011 10011100  | 00000011
                                          pad with 0000
   6-bit:   000101 001111 101110 011100 | 000000 110000
   Decimal: 5      15     46     28       0      48
                                               pad with =      =
   Output:  F      P      u      c        A      w      =      =

6.6.  Example of an ASCII Armored Message

   -----BEGIN PGP MESSAGE-----
   Version: OpenPrivacy 0.99

   yDgBO22WxBHv7O8X7O/jygAEzol56iUKiXmV+XmpCtmpqQUKiQrFqclFqUDBovzS
   vBSFjNSiVHsuAA==
   =njUN
   -----END PGP MESSAGE-----

   Note that this example has extra indenting; an actual armored message
   would have no leading whitespace.



(page 59 continued on part 4)

Next RFC Part