OpenPGP Signatures Incorporating X.509 Certificates
hal@finney.org ("Hal Finney") Tue, 12 April 2005 23:03 UTC
Received: from above.proper.com (above.proper.com [208.184.76.39]) by ietf.org (8.9.1a/8.9.1a) with ESMTP id TAA22063 for <openpgp-archive@lists.ietf.org>; Tue, 12 Apr 2005 19:03:06 -0400 (EDT)
Received: from above.proper.com (localhost.vpnc.org [127.0.0.1]) by above.proper.com (8.12.11/8.12.9) with ESMTP id j3CMliH5062452; Tue, 12 Apr 2005 15:47:44 -0700 (PDT) (envelope-from owner-ietf-openpgp@mail.imc.org)
Received: (from majordom@localhost) by above.proper.com (8.12.11/8.12.9/Submit) id j3CMliJ9062451; Tue, 12 Apr 2005 15:47:44 -0700 (PDT)
X-Authentication-Warning: above.proper.com: majordom set sender to owner-ietf-openpgp@mail.imc.org using -f
Received: from finney.org (226-132.adsl2.netlojix.net [207.71.226.132]) by above.proper.com (8.12.11/8.12.9) with ESMTP id j3CMlgEY062443 for <ietf-openpgp@imc.org>; Tue, 12 Apr 2005 15:47:42 -0700 (PDT) (envelope-from hal@finney.org)
Received: by finney.org (Postfix, from userid 500) id AABE557EE8; Tue, 12 Apr 2005 14:58:27 -0700 (PDT)
To: ietf-openpgp@imc.org
Subject: OpenPGP Signatures Incorporating X.509 Certificates
Message-Id: <20050412215827.AABE557EE8@finney.org>
Date: Tue, 12 Apr 2005 14:58:27 -0700
From: hal@finney.org
Sender: owner-ietf-openpgp@mail.imc.org
Precedence: bulk
List-Archive: <http://www.imc.org/ietf-openpgp/mail-archive/>
List-Unsubscribe: <mailto:ietf-openpgp-request@imc.org?body=unsubscribe>
List-ID: <ietf-openpgp.imc.org>
OpenPGP Signatures Incorporating X.509 Certificates Copyright 2005 by PGP Corporation. All Rights Reserved. Abstract This document is published to document the procedure used by commercial PGP [PGP] products up through version 9 for incorporating X.509 [X.509-00] certificates into OpenPGP [RFC2440] format signatures, and for cryptographically validating such signatures. It describes only the format and methods needed to import X.509 certificates, and to validate key signature packets containing such certificates. It does not deal with storage and implementation questions. 1. Introduction The OpenPGP [RFC2440] specification describes data formats for representing public keys, userids, and key signatures that cryptographically bind keys, userids, and fields from signature packets. It further describes the cryptographic procedures used to sign and verify the signature packets which comply with that specification. An alternative set of standards and formats is widely used in network applications for communicating cryptographic bindings of public keys and associated name data, based on the X.509 [X.509-00] certificate format. X.509 certificates communicate similar information to OpenPGP key, userid and signature packets. However, the details of the data formats are incompatible and it is not possible to transform X.509 certificates into sequences of OpenPGP packets that can be cryptographically validated by the mechanisms described in RFC2440. This document presents an alternative mechanism to allow X.509 certificates to be imported into OpenPGP data formats and cryptographically validated. It describes both the detailed data formats used to import and represent X.509 data in OpenPGP packets, and the procedures necessary to cryptographically validate such X.509 based OpenPGP signatures. These mechanisms allow the cryptographic infrastructure based on X.509 certificates to be imported and used in the context of OpenPGP messages and data. 1.1. Overview of Importing Certificates X.509 certificates are imported into OpenPGP signature packets in three steps, which will be described in more detail in section 2. [Page 1] -2- First, the numeric key material (the RSA modulus and exponent, and corresponding values for other key types) is used to construct an OpenPGP key packet. Second, the name field(s) of the X.509 certificate are used to construct an OpenPGP userid packet. And third, an OpenPGP signature packet is constructed from the certificate. Some fields of the OpenPGP signature packet are set from corresponding fields in the certificate. In addition, the certificate itself is inserted as a whole into the OpenPGP signature packet, in a signature subpacket. During the import process, the keyring is searched for a pre-existing OpenPGP key which matches the numeric key material being imported. If so, the userid and signature are added to the existing key. This also requires checking to see whether there is already a userid on the key matching the userid constructed by the import process; if so, the new signature packet is added to the pre-existing userid. This allows OpenPGP keys to hold a combination of X.509 based signatures and regular OpenPGP signatures. Once the X.509 certificate has been imported, the resulting OpenPGP keys and userids can be used interchangeably with regular OpenPGP keys. The only difference is in the format of the X.509 signatures. 1.2. Validating Certificates Cryptographically validating an X.509 signature packet requires a special process. It is not possible to use the normal OpenPGP signature validation process because no cryptographically valid signature exists over the OpenPGP data. Instead, a two step process is used. First, the X.509 certificate is tested for consistency with the OpenPGP packets. This requires extracting the X.509 certificate from the OpenPGP signature packet. It is then put through a process similar to when it was first imported into the OpenPGP format per this specification, to create temporary OpenPGP key, userid and signature packets from the certificate data. These temporary packets are compared with the OpenPGP key, userid and signature packets from the OpenPGP key holding the X.509 certificate signature. There must be an exact, byte-for-byte match between the two sets of packets for this step of the validation to be considered successful. This guarantees that the material in the OpenPGP packets is consistent with the contents of the X.509 certificate. Second, the X.509 certificate is itself cryptographically validated. This is a straightforward matter of computing the hash over the "to be signed" portion of the certificate and running the cryptographic signature verification algorithm using that hash and using the [Page 2] -3- signature field of the certificate. This step requires that the cryptographic key material of the issuing certificate must be present; for example, it may be available on the keyring as an OpenPGP key if it was previously imported into the OpenPGP format. Together, these two steps assure that the issuing key issued the certificate, and that the resulting OpenPGP key, userid and signature packets faithfully reflect the information put into the certificate by the issuer. On this basis the X.509 certificate signature is considered to be valid. 1.3. Identifying Signing Keys The OpenPGP specification uses keyids to link signatures to the keys which issued them. X.509 uses a different method, based on the issuer name. As a result, X.509 signature packets do not have keyid subpackets. Instead, to find the key which issued an X.509 signature packet it is necessary to extract the X.509 certificate, parse it to extract the issuer field, and then to search the other X.509 signature packets on the keyring for an X.509 certificate whose subject name matches. The key to which that certificate signature is attached is the one which issued the X.509 signature being validated. 2. Importing X.509 Certificates Note that the rules and procedures below for importing an X.509 certificate must be followed precisely by any compatible implementation. This is because checking the cryptographic validity of an X.509 signature requires extracting the certificate from the X.509 signature and repeating the import process, comparing the results byte for byte with the OpenPGP key, userid and signature packets. Any variation between implementations, even seemingly inconsequential ones like changing the order of various subpackets or userid fields, will cause this bytewise comparison to fail and cause the signature to be treated as invalid. 2.1. Creating the Key Packet The first step in importing an X.509 certificate into OpenPGP is to create an OpenPGP key packet which includes the numeric key material from the certificate. X.509 certificates holding RSA, DSS or ElGamal keys may be imported. The data is extracted from the SubjectPublicKeyInfo field of the certificate and converted into OpenPGP public key format. OpenPGP public key packets contain four additional pieces of information. First, they have a version number. Version 3 and 4 packets are presently in use. Second, they have a creation date [Page 3] -4- field. Third, version 3 packets have a field encoding the duration until key expiration. And fourth, they hold an algorithm identifier for the public key algorithm the key represents. In importing the key, the keyring should be searched for an existing key whose numeric key material matches that of the certificate being imported. If a match is found, that key packet is used as the basis for filling in these other fields. This uses the version number, creation date and expiration period fields from the pre-existing key. If no matching key exists, the new OpenPGP packet is created with version 4, and the public key algorithm field is set from the type of public key in the X.509 certificate. V4 keys do not have expiration periods, so that leaves only the creation date. X.509 certificates normally do not specify a key creation date, only a certificate creation date. A somewhat complicated mechanism is available to facilitate setting a reliable key creation date field in the OpenPGP public key packet. This mechanism is intended to facilitate allowing pre-existing OpenPGP keys to acquire X.509 certificates on their key material. These X.509 certificates could then be distributed and imported into other users' OpenPGP compatible software. In order to keep the resulting OpenPGP keys compatible with the ones which were certified, OpenPGP encodes the key creation date into the X.509 certificate request which is sent to be certified. With a cooperative certificate issuing authority (CA), the key creation date is then embedded in the certificate in a special format. This ensures that when other users import the X.509 certificate, they will create the OpenPGP key with the same creation date that the original key had. This is especially important in case the importing user did not previously have a copy of the original OpenPGP key, but acquired it by importing the X.509 certificate; and then he later imports the original OpenPGP key as a conventional-format OpenPGP key, rather than as a certificate. Without the special mechanism for handling creation dates, the creation dates wouldn't match, and the keyids of the two keys would be different, making them appear to be two different keys. Putting the key creation date into the X.509 certificate helps to insure that importing the certificate will correctly reconstruct the OpenPGP key. Two alternative mechanisms are available for encoding this information into the X.509 certificate. The preferred mechanism is a custom extension created for this purpose. The OID for this extension is (1 3 6 1 4 1 3401 8 1 1), encoded as the octet string {0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x9a, 0x49, 0x08, 0x01, [Page 4] -5- 0x01}. The data for the extension is defined as: PGPExtension ::= SEQUENCE { version Version DEFAULT v1, keyCreation Time } The OpenPGP key creation data is stored in X.509 Time format, the same format used for the notBefore and notAfter subfields of the certificate validity field. This is converted to the four byte OpenPGP time format specified in RFC2440 and used as the key creation field in the new OpenPGP key packet. The second method for encoding the OpenPGP creation date into an X.509 certificate is used if the custom extension is not supported by the CA. It stores the OpenPGP creation date in a field in the subject Distinguished Name. It uses either an Organizational Unit or Description field in the subject name. The creation date is stored in one of these field types, with associated data in the format "PGPKeyCreation=0x........" where the dots are replaced by 8 hex digits that encode the creation date in OpenPGP time format. If such a field is found, the hex value after "0x" is converted to binary data and used as the creation date in the OpenPGP key packet. On import, the certificate is searched sequentially for these two possible encodings of creation date. The first match is used, although typically there would not be more than one such encoding present in a certificate. Because subject name comes before extensions, the subject name fields are checked first, then the extensions. If none of these methods work to find an OpenPGP creation date, as will typically be the case on a certificate which was created via X.509 mechanisms and not by certifying an OpenPGP key, the certificate notBefore field is converted to OpenPGP time format and used as the key creation date. 2.2. Creating the UserID Packet Two alternative methods are available to create an OpenPGP UserID packet from an X.509 certificate, the short name format and the long name format. The short name format is used if the conditions described below are met, otherwise the long name format is used. The short name format for the userid is of the form "common_name <email_address>", a widely used format for OpenPGP userids. For this format to be used it must be possible to extract a common name and email address from the certificate. The common name must come from [Page 5] -6- the subject name field. The email address may come from either the subject name, where its OID is (1 2 840 113549 1 9 1), or from a SubjectAlternativeName field in an extension, where the choice type is rfc822Name. As a special case, the short name format is also used if the subject name has only a single field, which is an email address, but there is no common name. In that case the userid is created as "<email_address>". If it is not possible to satisfy these conditions for creating the userid in the short format, a long format is used. This is a slight modification of "Lightweight Directory Access Protocol (v3): UTF-8 String Representation of Distinguished Names" [RFC2253], applied to the subject name field of the certificate. RFC2253 puts the DN fields into reverse order, but this specification modifies that rule somewhat. The common name field (if present) is always output first, before the other fields, to improve readability. Also, any name field corresponding to the special OpenPGP key creation date field described in the section 2.1, if present, is skipped and is not output. The only DN field names which get converted into printable form for the userid are CN, C, L, ST, STREET, O, OU and EMAIL. Other fields in the DN are ignored when converting to an OpenPGP userid. Note that any SubjectAlternativeName extensions are not used when outputting a long format name. Only the fields from the subject name of the certificate are put into the OpenPGP userid packet. If no fields from the list above are found in the DN, the userid packet is created with the text "(Unknown X509 name)". 2.3. Creating the Signature Packet Creating the OpenPGP signature packet from an X.509 certificate involves two steps. The first is to include the certificate itself, in total, into a new subpacket of the OpenPGP signature packet. The second is to set up the various signature packet fields and subpackets which encode the supported semantics of the X.509 certificate. 2.3.1. X.509 Signature Subpacket Format This specification defines a new OpenPGP subpacket type. It uses subpacket type 100, defined in RFC2440 as within the private range of subpackets. The first byte of the subpacket is 1, indicating that the type of the private-range subpacket is an X.509 certificate. The [Page 6] -7- next two bytes are major and minor version numbers. The major version is 1 for all compatible implementations of this specification. The minor version reflects changes in the detailed rules for how X.509 certificates are converted to OpenPGP keys. The current minor version is 4, and this value should be used in newly created certificate subpackets. When verifying an X.509 certificate signature, the minor version number must be parsed and used to guide the conversion process. Since part of the verification involves checking for consistency between the X.509 certificate and the OpenPGP packets, any differences would cause the signature to be treated as invalid. When changes are made for how this conversion is done, the minor version must be upgraded. The only operational difference at this point is between minor version 4 vs. earlier minor version numbers of 3 or less. There is a change to the public key algorithm field used in the signature packet, as described below. No other changes presently exist based on minor version number, for importing signature, userid or key packets. The remaining data in the certificate subpacket is the X.509 certificate itself. Its length is determined implicitly by the subpacket length minus the fields already described. X.509 certificates are self-delimiting, and the certificate must end at the end of the data range in the subpacket allocated to hold it. 2.3.2. Other Signature Fields In addition to inserting the certificate bodily into a new subpacket, other fields of the OpenPGP signature packet are created to be consistent with the data from the certificate. Note that it is necessary to follow the description in this section precisely in order to create X.509 signature packets which will interoperate with other software implementing this specification. No flexibility is possible in the set of signature packets created, the contents of the packet, or the ordering of the packets. This consistency is necessary in order for the byte-for-byte packet comparison to succeed when signatures are verified. OpenPGP signature packets created from X.509 certificates are version 4 packets. The signature type field is 0x10, "generic certification of a user id and public key packet". The next field is the public key algorithm, which guides the signature verification process. As described in the introduction, X.509 signature packets cannot be cryptographically verified by the normal OpenPGP verification rules. To flag this fact and make sure an OpenPGP implementation of this [Page 7] -8- specification does not try to verify the packet, a reserved value is used for the public key algorithm field. This is the one place the minor version number from the certificate subpacket is used. For minor versions 0-3, the reserved value is 0. For minor version 4, the reserved value is 100, which is in the reserved range for RFC2440. In either case, it is meant to indicate that the regular OpenPGP certificate verification process will not work, and to prevent noncompliant OpenPGP implementations from attempting to verify signatures created by this specification. The next field in the V4 signature packet is the hash algorithm ID, which is set to the hash algorithm from the X.509 certificate. If a certificate uses a public key or hash algorithm not recognized by RFC2440, it is not allowed to be imported per this specification. The next part of the signature packet contains the so-called hashed subpackets. Note that these subpackets are not actually hashed, in an X.509 signature packet; rather, their validity is verified based on comparison with the X.509 certificate, which does get cryptographically hashed and verified. Several such subpackets are created, based on X.509 certificate data. The order of these subpackets is significant in that the certificate verification process described in section 1.2 will attempt to re-convert the X.509 certificate into an OpenPGP signature packet and do a byte-for-byte match between the re-converted data and the original signature data. The packets must be identical for the X.509 signature to be considered valid. The first subpacket is signature creation time, subpacket ID 2. This is taken from the notBefore subfield of the validity field in the certificate, and converted to OpenPGP time format. The second subpacket is signature expiration time, subpacket ID 3. This is taken from the notAfter subfield of the validity field in the certificate, and converted to OpenPGP time format. The signature creation time is then subtracted, because OpenPGP actually stores the signature validity duration in seconds in the expiration time subpacket. Next is an optional trust signature subpacket, ID 5. It is used if the imported certificate has a BasicConstraints extension with the boolean cA field being true, representing a CA certificate. The trust signature subpacket holds two bytes. The first is the trust "level", which means the depth to which trust is delegated. This is set based on any PathLenConstraint field of the BasicConstraints extension. If there is no PathLenConstraint, the level value stored in the trust packet is the maximum value of 255. If there is a [Page 8] -9- PathLenConstraint value in the certificate, the trust level stored is equal to that integer value, plus one (then truncated to one byte). The trust packet also has a second byte representing the validity of the trust being extended, which is set to 120, meaning complete validity. Next there is an optional a key flags subpacket, ID 27. It is used if there is a KeyUsage extension in the imported certificate, to encode any key usage restrictions. Not all bits in the KeyUsage extension are recognized and converted by this specification, but the key flags subpacket is created even if none of the bits are recognized, in which case the key flags subpacket will be output with a flag value of zero. The bits which are recognized, and the corresponding OpenPGP key flags values, are as follows: keyCertSign ---> flag 0x01, key can certify other keys cRLSign ---> flag 0x01, key can certify other keys digitalSignature ---> flag 0x02, key can sign data nonRepudiation ---> flag 0x02, key can sign data keyEncipherment ---> flags 0x14, key can encrypt communications and key can encrypt storage dataEncipherment ---> flags 0x14, key can encrypt communications and key can encrypt storage keyAgreement ---> flags 0x14, key can encrypt communications and key can encrypt storage All other key flag bits in the four byte field are output as zero. The last subpacket output is the X.509 certificate subpacket, ID 100, as described in section 2.3.1. above. Following the hashed data subpackets in the signature packet are the unhashed packets. No such packets are used when importing an X.509 signature, so the length of the unhashed region must be zero. Note in particular that X.509 signature packets do not have an issuing keyid field. This is because X.509 certificates refer to their issuer by name, rather than by keyid, as discussed in section 1.3. Next comes a two byte checksum, which is set to two bytes of zero. Finally there is the MPI data for the OpenPGP signature. No MPI data is used for signatures in this specification, so a dummy MPI value of 1 is stored, represented as the three byte sequence 0, 1, 1. That ends the OpenPGP signature packet. [Page 9] -10- 3. References [PGP] PGP Corporation, http://www.pgp.com. [RFC2253] M. Wahl, S. Kille, T. Howes, "Lightweight Directory Access Protocol (v3): UTF-8 String Representation of Distinguished Names", RFC 2253, December, 1997. [RFC2440] J. Callas, L. Donnerhacke, H. Finney, R. Thayer, "OpenPGP Message Format", RFC 2440, November, 1998. [X.509-00] ITU-T. Recommendation X.509: The Directory - Authentication Framework. 2000. [Page 10]
- OpenPGP Signatures Incorporating X.509 Certificat… "Hal Finney"