<?xml version="1.0"?>
<?rfc toc="yes"?>
<?rfc symrefs="yes"?>
<?rfc sortrefs="yes"?>
<?rfc compact="yes"?>
<?rfc subcompact="no"?>
<!DOCTYPE rfc SYSTEM "rfc2629.dtd">
<rfc ipr="trust200902" docName="draft-mccain-keylist-05" category="std">
	<!-- TODO: We should verify that 'trust200902' is the intellectual property
	designation we want. ~MM -->
	<!-- TODO: figure out which category this goes in. ~MM -->
	<front>
		<!-- Working title. We'll want something that more accurately frames the
		system before we submit. It never also hurts to have a more catchy
		title... -->
		<title abbrev="OpenPGP Keylist Subscriptions">
			Distributing OpenPGP Key Fingerprints with Signed Keylist Subscriptions
		</title>
		<author initials="M.M." surname="McCain" fullname="R. Miles McCain">
			<organization abbrev="FLM">
				First Look Media
			</organization>
			<address>
				<email>
					ietf@sendmiles.email
				</email>
				<uri>
					https://rmrm.io
				</uri>
			</address>
		</author>
		<author initials="M.L." surname="Lee" fullname="Micah Lee">
			<organization abbrev="TI">
				The Intercept
			</organization>
			<address>
				<email>
					micah.lee@theintercept.com
				</email>
				<uri>
					https://micahflee.com/
				</uri>
			</address>
		</author>
		<author initials="N.D.W." surname="Welch" fullname="Nat Welch">
			<organization abbrev="Google">
				Google
			</organization>
			<address>
				<email>
					nat@natwelch.com
				</email>
				<uri>
					https://natwelch.com
				</uri>
			</address>
		</author>
		<date month="September" year="2019" day="2" />
		<area>
			Security
		</area>
		<keyword>
			OpenPGP
		</keyword>
		<keyword>
			GPGSync
		</keyword>
		<keyword>
			GPG
		</keyword>
		<keyword>
			Keylist
		</keyword>
		<abstract>
			<t>
				This document specifies a system by which an OpenPGP client may subscribe
				to an organization's public keylist to keep its keystore up-to-date with
				correct keys from the correct keyserver(s), even in cases where the keys correspond to multiple
				(potentially uncontrolled) domains. Ensuring that all members or followers
				of an organization have their colleagues' most recent PGP public keys is
				critical to maintaining operational security. Without the most recent
				keys' fingerprints and a source of trust for those keys (as this document
				specifies), users must manually update and sign each others' keys -- a
				system that is untenable in larger organizations. This document proposes a
				experimental format for the keylist file as well as requirements for
				clients who wish to implement this experimental keylist subscription
				functionality.
			</t>
			<!-- We'll want to tighten this abstract up a bit... ~MM -->
			<!-- ^ I did what I could. ~MM -->
		</abstract>
	</front>
	<middle>
		<section anchor="intro" title="Introduction">
			<t>
				 This document specifies a system by which clients may subscribe to
				 cryptographically signed 'keylists' of public key fingerprints. The public
				 keys do not necesssarily all correspond to a single domain. This system
				 enhances operational security by allowing seamless key rotation across
				 entire organizations without centralized public key hosting. To enable
				 cross-client compatibility, this document provides a experimental format
				 for the keylist, its cryptographic verification, and the method by which it
				 is retreived by the client. The user interface by which a client provides
				 this functionality to the user is out of scope, as is the process by which
				 the client retrieves public keys. Other non-security-related implementation
				 details are also out of scope.
			</t>
			<section anchor="notation" title="Requirements Notation">
				<t>
					The key words "MUST", "MUST NOT", "REQUIRED", "SHALL",
					"SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY",
					and "OPTIONAL" in this document are to be interpreted as
					described in
					<xref target="RFC2119" />
					.
				</t>
			</section>
			<section anchor="terminology" title="Terminology">
				<t>
					This document uses the terms "OpenPGP", "public key",
					"private key", "signature", and "fingerprint" as defined by
					OpenPGP Message Format
					<xref target="RFC4880" />
					(the fingerprint type SHOULD be V4).
					<!-- TODO: clarify the _type_ of fingerprints we use (ideally V4/SHA-160) -->
				</t>
				<!-- TODO: add unicode definitions. ~MM -->
				<!-- TODO: verify that all the previous terms are actually
				defined in RFC4880. ~MM -->
				<!-- TODO: does 'URI' and 'Internet' need a citation? Probably
				not, but we should check. ~MM -->
				<t>
					 The term "keylist" is defined as a list of OpenPGP public key fingerprints
					 accessible via a URI in the format specified in
					 <xref target="formats" />. Keylists SHOULD be treated as public
					 documents, however a system administrator MAY choose, for example, to
					 restrict access to a keylist to a specific subnet or private network.
				</t>
				<!-- TODO: I avoid using the word 'file' here as it has a
				nuanced meaning and really we're just talking about data
				accessible via a URI. Is there a term other than 'data' that is
				appropriate here? ~MM -->
				<!-- I think this is fine. ~NDW -->
				<t>
					An "authority key" is defined as the OpenPGP secret key used
					to sign a particular keylist. Every keylist has a
					corresponding authority key, and every authority key has at
					least one corresponding keylist. A single authority key
					SHOULD NOT be used to sign multiple keylists.
				</t>
				<!-- I'm not opposed to it, but why shouldn't the same authority
				key be used to sign multiple keylists? I think it'd be confusing
				in the UI in GPG Sync if you do this, because they keylist is
				displayed by the authority key's UID. But from a security
				standpoint, it should be probably be just as secure. ~ML -->
				<!-- I removed the reference to security. One potential
				consideration, though, is that this sentence is less about the
				spec and more about the end user. Perhaps we should just remove
				the reference all together because it doesn't fit into the
				implementation but rather the end user's habits? Could be a
				point of criticism. ~MM -->
				<t>
					To be "subscribed" to a keylist means that a program will
					retreive that keylist on a regular interval. After
					retrieval, that program will perform an update to an
					internal OpenPGP keystore.
				</t>
				<!-- TODO: This needs to be cleaned/tightened. ~MM -->
				<t>
					A "client" is a program that allows the user to subscribe to
					keylists. A client may be an OpenPGP client itself or a
					separate program that interfaces with an OpenPGP client to
					update its keystore.
				</t>
			</section>
			<section anchor="note-to-readers" title="Note to Readers">
				<t>RFC Editor: please remove this section prior to
				publication.</t>
				<t>Development of this Internet draft takes place on GitHub at
				<eref
				target="https://github.com/firstlookmedia/keylist-rfc">firstlookmedia/Keylist-RFC</eref>.
				</t>
				<t>We are still considering whether this Draft is better for the Experimental or
				Informational track. All feedback is appreciated.</t>
			</section>
		</section>
		<section anchor="functions" title="Functions and Procedures">
			<t>
				As new keys are created and other keys are revoked, it is
				critical that all members of an organization have the most
				recent set of keys available on their computers. Keylists enable
				organizations to publish a directory of OpenPGP keys that
				clients can use to keep their internal keystores up-to-date.
			</t>
			<section anchor="keylist-subscribe" title="Subscribing to Keylists">
				<t>
					A single client may subscribe to any number of keylists.
					When a client first subscribes to a keylist, it SHOULD
					update or import every key present in the keylist into its
					local keystore. Keylist subscriptions SHOULD be persistent
					-- that is, they should be permanently stored by the client
					to enable future automatic updates.
				</t>
				<t>
					To subscribe to a keylist, the client must be aware of the
					keylist URI (see <xref target="RFC3986" />), and the
					fingerprint of the authority key used to sign the
					keylist. The protocol used to retrieve the keylist and its
					signature SHOULD be HTTPS (see <xref target="RFC2818" />),
					however other implementation MAY be supported. A client
					implementing keylist functionality MUST support the
					retrieval of keylists and signatures over HTTPS. All other
					protocols are OPTIONAL.
				</t>
				<t>
					A client MUST NOT employ a trust-on-first-use (TOFU) model for
					determining the fingerprint of the authority public key; the
					authority public key fingerprint must be explicitly provided
					by the user.
				</t>
				<t>
					The process by which the client stores its keylist
					subscriptions is out of scope, as is the means by which
					subscription functionality is exposed to the end-user.
				</t>
				<t>
					The client MAY provide the option to perform all its network
					activity over a SOCKS5 proxy (see <xref target="RFC1928" />).
				</t>
			</section>
			<section anchor="keylist-update" title="Automatic Updates">
				<t>
					The primary purpose of keylists is to enable periodic
					updates of OpenPGP clients' internal keystores. We RECOMMEND
					that clients provide automatic 'background' update functionality;
					we also regonize that automatic background updates are not possible
					in every application (specifically cross-platform CLI tools).
				</t>
				<t>When automatic background updates are provided, we RECOMMEND
					that clients provide a default refresh interval of less than
					one day, however we also RECOMMEND that clients allow the
					user to select this interval. The exact time at which
					updates are performed is not critical.
				</t>
				<t>
					To perform an update, the client MUST perform the following
					steps on each keylist to which it is subscribed. The steps
					SHOULD be performed in the given order.
				</t>
				<t>
					<list style="numbers">
						<t>
							Obtain a current copy of the keylist from its URI. If a
							current copy (i.e. not from local cache) cannot be obtained,
							the client SHOULD abort the update for this keylist and notify
							the user. The client SHOULD continue the update for other keylists
							to which it is subscribed, notwithstanding also failing the criteria
							described in this section.
						</t>
						<t>
							Obtain a current copy of the keylist's signature
							data from its URI, which is included in the keylist data
							format specified in <xref target="formats" />. If a current copy
							cannot be obtained, the client SHOULD abort the update and notify
							the user. The client SHOULD continue the update for other keylists
							to which it is subscribed, notwithstanding also failing the criteria
							described in this section.
						</t>
						<!-- I say 'obtain' rather than retrieve because I want
						to leave open the possibility of a client checking to
						see if the hash of the file, for example, has changed,
						and only re-requesting if it has. 'Obtain' is also very
						ambiguous, though, so it may be to our advantage to use
						something more specific or explain this rationale
						outright. ~MM -->
						<!-- we should be verifying a checksum, and be explicit
						about it in this description. ~NDW -->
						<t>
							Using the keylist and the keylist's signature,
							cryptographically verify that the keylist was signed
							using the authority key. If the signature does not
							verify, the client MUST abort the update of this
							keylist and SHOULD alert the user. The client SHOULD
							NOT abort the update of other keylists to which it
							is subscribed, unless they too fail signature
							verification.
						</t>
						<t>
							Validate the format of the keylist according to
							<xref target="formats" />
							. If the keylist is in an invalid format, the client
							MUST abort the update this keylist and SHOULD alert
							the user. The client SHOULD continue the update for
							other keylists to which it is subscribed, notwithstanding
							also failing the criteria described in this section.
						</t>
						<t>
							For each fingerprint listed in the keyfile, if a
							copy of the associated public key is not present in
							the client's local keystore, retrieve it from the
							keyserver specified by either the key entry, the keylist (see
							<xref target="formats" />) or, if the keylist specifies
							no keyserver, from the user's default keyserver. If the public
							key cannot be found for a particular fingerprint, the client
							MUST NOT abort the entire update process; instead, it SHOULD
							notify the user that the key retrieval failed but otherwise
							merely skip updating the key and continue.
							If the key is already present and not revoked,
							refresh it from the keyserver determined in the same 
							manner as above. If it is present and revoked, do nothing
							for that particular key.
						</t>
						<!-- TODO: Is it overkill to establish some concept of a
						'linked keystore' as the keystore that the client
						interacts with and keeps updated? This is a potential
						ambiguity for machines with multiple keystores. ~MM -->
						<!-- That could be useful, but I'd leave that up to the
						client. Maybe add a recommendation that says something
						around letting users specify which keystore they want to
						sync to? It seems slightly out of scope as you are
						saying retrival and update is out of scope. ~NDW -->
						<!-- TODO: Should anything else be in this list? ~MM -->
					</list>
				</t>
			</section>
			<section anchor="keylist-crypto" title="Cryptographic Verification of Keylists">
				<t>
					To ensure authenticity of a keylist during an update, the
					client MUST verify that the keylist's data matches its
					cryptographic signature, and that the public key used to
					verify the signature matches the authority key fingerprint
					given by the user.
				</t>
				<t>
					For enhanced security, it is RECOMMENDED that keylist
					operators sign each public key listed in their keylist with
					the authority private key. This way, an organization can
					have an internal trust relationship without requiring
					members of the organization to certify each other's public
					keys.
				</t>
			</section>
		</section>
		<section anchor="formats" title="Data Element Formats">
			<t>
				The following are format specifications for the keylist file and
				its signature file.
			</t>
			<section anchor="keylist-format" title="Keylist">
				<t>
					The keylist MUST be a valid JavaScript Object Notation
					(JSON) Data Interchange Format
					<xref target="RFC8259" /> object with specific keys
					and values, as defined below. Note that unless otherwise specified,
					'key' in this section refers to JSON keys -- not OpenPGP keys.
				</t>
				<t>
					To encode metadata, the keylist MUST have a "metadata" root key
					with an object as the value ("metadata object").
					The metadata object MUST contain a "signature_uri" key whose value
					is the URI string of the keylist's signature file. All metadata keys
					apart from "signature_uri" are OPTIONAL.
				</t>
				<t>
					The metadata object MAY contain a "keyserver" key with the value of the
					URI string of a HKP keyserver from which the OpenPGP keys in the keylist
					should be retrieved. Each PGP key listed in the keylist MAY have a
					"keyserver" JSON key; if a PGP key in the keylist specifies a HKP keyserver that is
					different from the one described in the metadata object, the PGP key-specific
					keyserver should be used to retrieve that particular key (and not the key listed
					in the metadata object).
				</t>
				<t>
					The metadata object MAY contain a "comment" key with the
					value of any string. The metadata object MAY also contain other arbitrary
					key-value pairs.
				</t>
				<!-- TODO: Should we specify in more detail what a keyserver URI
				is, or even what a keyserver is? More details here:
				https://github.com/firstlookmedia/keylist-rfc/issues/8#issuecomment-427133308
				~ML -->
				<t>
					The keylist MUST have a "keys" key with an array as the value.
					This array contains a list of OpenPGP key fingerprints and
					metadata about them. Each item in the array MUST be an object.
					Each of these objects MUST have a "fingerprint" key with the
					value of a string that contains the full 40-character
					hexadecimal public key fingerprint, as defined in OpenPGP
					Message Format
					<xref target="RFC4880" />
					. Any number of space characters (' ', U+0020) MAY be included
					at any location in the fingerprint string. These objects MAY
					contain "name" (the name of the PGP key's owner), "email" 
					(an email of the PGP key's owner), "keyserver" (a HKP keyserver 
					from which the key should be retrieved), and "comment" key-value pairs,
					as well as any other key-value pairs.
					<!-- Maybe the edit here was a bit _too_ reductive. Let me know if you
					think I cut too much. The thinking is really that "name", "email", and
					"comment" keys are really just optional, so it makes sense to merge them
					into a single sentence, but I'm also completely open to reverting this
					change if you prefer the old phrasing! -->
				</t>
				<t>
					The following is an example of a valid keylist.
				</t>
				<figure>
					<artwork>
{
  "metadata": {
    "signature_uri": "https://www.example.com/keylist.json.asc",
    "comment": "This is an example of a keylist file"
  },
  "keys": [
    {
      "fingerprint": "927F419D7EC82C2F149C1BD1403C2657CD994F73",
      "name": "Micah Lee",
      "email": "micah.lee@theintercept.com",
      "comment": "Each key can have a comment"
    },
    {
      "fingerprint": "1326CB162C6921BF085F8459F3C78280DDBF52A1",
      "name": "R. Miles McCain",
      "email": "0@rmrm.io",
	  "keyserver": "https://keys.openpgp.org/"
    },
    {
      "fingerprint": "E0BE0804CF04A65C1FC64CC4CAD802E066046C02",
      "name": "Nat Welch",
      "email": "nat.welch@firstlook.org"
    }
  ]
}
					</artwork>
				</figure>
			</section>
			<section anchor="sigfile" title="Signature">
				<t>
					The signature file MUST be an ASCII-armored 'detached
					signature' of the keylist file, as defined in OpenPGP
					Message Format
					<xref target="RFC4880" />
					.
				</t>
			</section>
			<section anchor="wellknown" title="Well-Known URL">
				<t>
					Keylists SHOULD NOT be well-known resources <xref target="RFC4880" />.
					To subscribe to a keylist, the client must be aware not only of the keylist's
					location, but also of the fingerprint of the authority public key used to sign the keylist.
					Furthermore, because keylists can reference public keys from several different domains,
					the expected host of the well-known location for a keylist may not always be self-evident.
				</t>
			</section>
		</section>
		<section anchor="implementation" title="Implementation Status">
			<t>
				GPG Sync, an open source program created by one of the authors,
				implements this experimental standard. GPG Sync is used by First
				Look Media and the Freedom of the Press Foundation to keep
				OpenPGP keys in sync across their organizations, as well as to
				publish their employee's OpenPGP keys to the world. These
				organizations collectively employ more than 200 people and have
				used the system described in this document successfully for
				multiple years.
			</t>
			<t>
				GPG Sync's existing code can be found at
				&lt;https://github.com/firstlookmedia/gpgsync&gt;
			</t>
			<t>
				First Look Media's keylist file can be found at
				&lt;https://github.com/firstlookmedia/gpgsync-firstlook-fingerprints&gt;
			</t>
			<!-- TODO: clunky. We could clean this. ~MM -->
		</section>
		<section anchor="securitybenefits" title="Security Benefits">
			<t>
				The keylist subscription functionality defined in this
				document provides a number of security benefits, including:
			</t>
			<t>
				<list style="symbols">
					<t>
						The ability for new keys to be quickly distributed
						across an organization.
					</t>
					<t>
						Removing the complexity of key distribution from
						end users, allowing them to focus on the content of
						their communications rather than on key management.
					</t>
					<t>
						The ability for an organization to prevent the
						spread of falsely attributed keys by centralizing
						the public key discovery process within their
						organization without centralized public key hosting.
					</t>
					<!-- TODO: others? ~MM -->
				</list>
			</t>
		</section>
		<section anchor="comparison" title="Relation to Other Technologies">
			<section anchor="wkd" title="Web Key Directories">
				<t>
					Unlike Web Key Directories, keylists are not domain specific. A keylist
					might contain public key fingerprints for email addresses across several
					different domains. Moreover, keylists only provide references to public
					keys by way of fingerprints; Web Key Directories provide the public keys
					themselves.
				</t>
			</section>
			<section anchor="dns" title="OPENPGPKEY DNS Records">
				<t>
					 A keylist MAY reference public keys corresponding to email addresses
					 across several different domains. Because managing OPENPGPKEY DNS Records
					 <xref target="RFC7929" /> for a particular domain requires control of that
					 domain, the OPENPGPKEY DNS Record system is not suitable for cases in
					 which keys are strewn about several different domains, including ones
					 outside of the control of an organization's system adminitrators.
				</t>
			</section>
			<!-- We'll want to clean this up, but the messaging we'd like to convey is there. -->
		</section>
		<section anchor="securityconsiderations" title="Security Considerations">
				<t>
					There is a situation in which keylist subscriptions could
					pose a potential security threat. If both the authority
					key and the keylist distribution system were to be
					compromised, it would be possible for an attacker to
					distribute any key of their choosing to the subscribers of the
					keylist. The potential consequences of this attack are limited,
					however, because the attacker cannot remove or modify the keys
					already present on subscribers' systems.
				</t>
				<t>
					Some organizations may wish to keep their keylists private. While
					this may be achievable by serving keylists at URIs only accessible from
					specific subnets, keylists are designed to be public
					documents. As such, clients may leak the contents of keylists to
					keyservers -- this specification ensures to the best of its ability
					the integrity of keylists, but not the privacy of keylists.
				</t>
			<!-- TODO, see https://tools.ietf.org/html/bcp72 ~MM -->
		</section>
		<section anchor="ianaconsiderations" title="IANA Considerations">
			<t>
				This document has no actions for IANA.
			</t>
		</section>
	</middle>
	<back>
		<references title="Normative References">
			<?rfc include="reference.RFC.7929.xml"?>
			<?rfc include="reference.RFC.4880.xml"?>
			<?rfc include="reference.RFC.3986.xml"?>
			<?rfc include="reference.RFC.2119.xml"?>
			<?rfc include="reference.RFC.8259.xml"?>
			<?rfc include="reference.RFC.2818.xml"?>
			<?rfc include="reference.RFC.1928.xml"?>
		</references>
		<!--
		<references title="Informative References"> </references>
		-->
	</back>
</rfc>
