<?xml version="1.0" encoding="utf-8"?>
<?xml-model href="rfc7991bis.rnc"?>
<!-- <?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?> -->
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<rfc
  xmlns:xi="http://www.w3.org/2001/XInclude"
  category="info"
  docName="draft-miller-ssh-cert-01"
  ipr="trust200902"
  obsoletes=""
  updates=""
  submissionType="IETF"
  xml:lang="en"
  version="3">
<!--
    * docName should be the name of your draft
    * category should be one of std, bcp, info, exp, historic
    * ipr should be one of trust200902, noModificationTrust200902, noDerivativesTrust200902, pre5378Trust200902
    * updates can be an RFC number as NNNN.
    * obsoletes can be an RFC number as NNNN
-->

<front>
	<title>SSH Certificate Format</title>
	<seriesInfo name="Internet-Draft" value="draft-miller-ssh-cert-01"/>
	<author fullname="Damien Miller" initials="D." surname="Miller">
		<organization>OpenSSH</organization>
		<address>
			<email>djm@openssh.com</email>
			<uri>https://www.openssh.com/</uri>
		</address>
	</author>
	<date year="2025" month="04" day="23" />
	<area>General</area>
	<workgroup>Internet Engineering Task Force</workgroup>
	<keyword>ssh</keyword>
	<keyword>certificate</keyword>
	<abstract>
		<t>
		This document presents a simple certificate format that may
		be used in the context of the Secure Shell (SSH) protocol for
		user and host authentication.
		</t>
	</abstract>
</front>

<middle>
<section><name>Introduction</name>
	<t>
	Secure Shell (SSH) is a protocol for secure remote
	connections and login over untrusted networks.
	SSH uses public key signatures for host authentication and
	commonly uses them for user authentication.
	This document describes a lightweight certificate format for use in
	these contexts. It may be used for server authentication as part
	of key exchange (<xref target="RFC4253" section="7" />) and for
	user public key authentication (<xref target="RFC4252" section="7" />).
	</t>

	<section anchor="requirements"><name>Requirements Language</name>
		<t>
		The key words "MUST", "MUST NOT", "REQUIRED", "SHALL",
	        "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT
	        RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
	        interpreted as described in BCP 14 <xref target="RFC2119"/>
	        <xref target="RFC8174"/> when, and only when, they appear in
	        all capitals, as shown here.
		</t>
	</section>
</section>

<!--
<section><name>Format Overview</name>
	<t>
	XXX
	</t>
</section>
-->

<section><name>Certificate Format</name>
	<t>
	All values in a certificate are encoded using the SSH wire
	representations specified by <xref target="RFC4251" />.
	</t>
	<section anchor="fmt"><name>Public certificate format</name>
		<section><name>General structure and common fields</name>
			<t>
			Certificates have the following general structure:
			</t>
			<sourcecode>
    string              key type
    string              nonce
    byte[]              public key fields
    uint64              serial number
    uint32              certificate role
    string              identifier
    string              principals
    uint64              valid after
    uint64              valid before
    string              critical options
    string              extensions
    string              reserved
    string              signature key
    string              signature
			</sourcecode>
			<t>
			The "key type" string identifies the certificate type,
			e.g. "ssh-ed25519-cert" identifies an ED25519
			certificate. The valid certificate types are listed
			below.
			</t>
			<t>
			The "nonce" field contains a random nonce. This value
			MUST be at least 16 bytes in length. 32 bytes is
			typical.
			</t>
			<t>
			The "public key fields" section contains the actual
			public key material. These are specified below for
			each certificate type.
			</t>
			<t>
			The "certificate role" field indicates the role of the
			certificate, either SSH2_CERT_TYPE_USER for user
			authentication certificates or SSH2_CERT_TYPE_HOST
			authentication certificates.
			</t>
			<t>
			The "identifier" field contains a UTF-8 encoded,
			human-readable identifier for the certificate,
			suitable for display to the user, recording in logs,
			etc.
			</t>
			<t>
			The "principals" field contains one or more UTF-8
			encoded names, themselves encoded as strings, for
			example:
			</t>
			<sourcecode>
    string              principal[0]
    string              principal[1]
    ...
    string              principal[N]
			</sourcecode>
			<t>
			These names identify the principals the certificate is
			intended to authenticate. In the case of user
			certificates, these will typically be user names,
			whereas for host certificates they will be host names
			and/or numerical addresses.
			</t>
			<t>
			The "valid after" and "valid before" field represent
			a validity interval for the certificate with each
			field being interpreted as a number of seconds since
			the Unix epoch (00:00:00 UTC on 1 January 1970) except
			for two special values. A zero value in the
			"valid after" field indicates that the certificate
			is valid from any time to the "valid after" date.
			A all-1s (i.e. 0xFFFFFFFFFFFFFFFF) value in the
			"valid after" field indicates that the certificate has
			no end expiry date.
			</t>
			<t>
			The "critical options" field contains zero or more
			of the certificate options described in
			<xref target="critopts" /> and encoded as described in
			<xref target="optionenc" />. If an implementation
			does not recognise or support a particular option
			contained in a certificate, then it MUST refuse to
			accept the certificate for authentication.
			</t>
			<t>
			The "extensions" field similarly contains zero or more
			of the certificate extensions described in
			<xref target="exts" /> and encoded as described in
			<xref target="optionenc" />.
			An implementation that does not recognise or support
			an extension present in a certificate extension section
			MUST ignore the extension.
			</t>
			<t>
			The "reserved" field is reserved for future use.
			Implementations MUST ignore the contents of this field
			if it is not empty.
			</t>
			<t>
			The "signature key" field contains the CA key used to
			sign the certificate, encoded as a SSH public key blob.
			Implementations MUST NOT accept certificate keys
			as CA keys.
			</t>
			<t>
			The "signature" field contains a signature, made using
			the CA signature key over the entire certificate
			excluding the "signature" field itself (i.e. everything
			from the "key type" up to and including the
			"signature key").
			The signature is encoded using the standard SSH
			signature encoding for the CA key type in question,
			e.g. <xref target="RFC5656" section="3.1.2"/>
			for ECDSA CA keys.
			</t>
		</section>
		<section anchor="dsacert"><name>DSA certificates</name>
			<t>
			DSA certificates have key type "ssh-dss-cert" and
			certify DSA keys as
			defined in <xref target="RFC4253" section="6.6" />.
			This format is equivalent to the vendor extension
			"ssh-dss-cert-v01@openssh.com".
			</t>
			<sourcecode>
    string              "ssh-dss-cert"
    string              nonce
    mpint               p
    mpint               q
    mpint               g
    mpint               y
    byte[]              public key fields
    uint64              serial number
    uint32              certificate role
    string              identifier
    string              principals
    uint64              valid after
    uint64              valid before
    string              critical options
    string              extensions
    string              reserved
    string              signature key
    string              signature
			</sourcecode>
			<t>
			The "p", "q", "g" values are the DSA domain
			parameters. "y" is the public key value.
			These values are as defined by Section 4.1 of
			<xref target="FIPS.186-4"/>.
			</t>
		</section>
		<section anchor="ecdsacert"><name>ECDSA certificates</name>
			<t>
			ECDSA certificates are represented by the key types
			"ecdsa-sha2-nistp256-cert",
			"ecdsa-sha2-nistp384-cert" and
			"ecdsa-sha2-nistp521-cert".
			They respectively certify "ecdsa-sha2-nistp256",
			"ecdsa-sha2-nistp384" and "ecdsa-sha2-nistp521"
			respectively, as defined by
			<xref target="RFC5656" section="3.1" />.
			This format is equivalent to the vendor extensions
			"ecdsa-sha2-nistp256-cert-v01@openssh.com",
			"ecdsa-sha2-nistp384-cert-v01@openssh.com" and
			"ecdsa-sha2-nistp521-cert-v01@openssh.com".
			</t>
			<sourcecode>
    string              "ecdsa-sha2-nistp256-cert" |
                        "ecdsa-sha2-nistp384-cert" |
                        "ecdsa-sha2-nistp521-cert"
    string              nonce
    string              ecdsa_curve_name
    string              Q
    byte[]              public key fields
    uint64              serial number
    uint32              certificate role
    string              identifier
    string              principals
    uint64              valid after
    uint64              valid before
    string              critical options
    string              extensions
    string              reserved
    string              signature key
    string              signature
			</sourcecode>
			<t>
			The value "Q" is the ECDSA public
			value as defined by Section 6.2 of
			<xref target="FIPS.186-5"/>.
			</t>
		</section>
		<section anchor="eddsacert"><name>EDDSA certificates</name>
			<t>
			EDDSA certificates have key type "ssh-ed25519-cert" or
			"ssh-ed448-cert" and certify Ed25519 and Ed448 keys
			(respectively) as defined by
			<xref target="RFC8709" />.
			This format is equivalent to the vendor extension
			"ssh-ed25519-cert-v01@openssh.com".
			</t>
			<sourcecode>
    string              "ssh-ed25519-cert" | "ssh-ed448-cert"
    string              nonce
    string              ENC(A)
    byte[]              public key fields
    uint64              serial number
    uint32              certificate role
    string              identifier
    string              principals
    uint64              valid after
    uint64              valid before
    string              critical options
    string              extensions
    string              reserved
    string              signature key
    string              signature
			</sourcecode>
			<t>
			The value ENC(A) is the EDDSA public key,
			the contents and interpretation of which are
			defined by <xref target="RFC8032" section="3.2"/>.
			</t>
		</section>
		<section anchor="rsacert"><name>RSA certificates</name>
			<t>
			RSA certificates have type "ssh-rsa-cert".
			These certify RSA, as defined in
			<xref target="RFC4253" section="6.6"/>.
			This format is equivalent to the vendor extension
			"ssh-rsa-cert-v01@openssh.com".
			</t>
			<sourcecode>
    string              "ssh-rsa-cert"
    string              nonce
    mpint               e
    mpint               n
    byte[]              public key fields
    uint64              serial number
    uint32              certificate role
    string              identifier
    string              principals
    uint64              valid after
    uint64              valid before
    string              critical options
    string              extensions
    string              reserved
    string              signature key
    string              signature
			</sourcecode>
			<t>
			"n" is the public composite modulus and
			"e" is the public exponent.
			These values are defined by Section 5.1 of
			<xref target="FIPS.186-4" />.
			</t>
		</section>
		<section><name>Other certificate formats</name>
			<t>
			SSH clients and server clients MAY support additional
			key types not documented here. Vendor-specific key types
			should use the domain-qualified naming convention
			defined in <xref target="RFC4251" section="4.2" />.
			</t>
		</section>
	</section>
	<section anchor="optionenc"><name>Option / extension encoding</name>
		<t>
		The "critical options" and "extensions" certificate sections
		use the same format for encoding, though they differ in how
		unsupported options are handled.
		</t>
		<t>
		Both sections consist of zero or more key/value pairs, encoded
		as a pair of strings:
		</t>
		<sourcecode>
    string              key
    string              value
		</sourcecode>
		<t>
		"key" should be a UTF-8 encoded string that identifies the
		option being encoded. Available keys for extensions and for
		critical options sections are listed below, but implementations
		may add their own options using the domain-qualified naming
		convention defined in <xref target="RFC4251" section="4.2" />.
		</t>
		<t>
		The contents and format of "value" are specific to each option
		or extension. Key/value pairs MUST be ordered lexically by key
		name.
		</t>
		<t>
		A common patten for flag-type options is for the
		value to be the empty string. For example, this is a complete
		extensions section that encodes a single flag value
		"permit-user-rc".
		</t>
		<sourcecode>
  00000016                           # Extensions section len=22
    0000000e                         # 1st key string len=14
      7065726d69742d757365722d7263   #   "permit-user-rc"
    00000000                         # 1st value string len=0
		</sourcecode>
		<t>
		For options whose values encode textual values, it is common
		for the value to contain a nested string. For example, the
		following is a complete criticial options section that sets
		a string-values option "force-command" to the value "sftp".
		</t>
		<sourcecode>
  0000001d                           # Criticial options len=29
    0000000d                         # 1st key string len=13
      666f7263652d636f6d6d616e64     #   "force-command"
    00000008                         # 1st value string len=8
      00000004                       #   value body string len=4
        73667470                     #     "sftp"
		</sourcecode>
		<t>
		Finally, the following is an example of a critical options
		section that contains a flag option "foo@example.com" and
		a string-valued option "force-command" with a the value "sftp".
		</t>
		<sourcecode>
  00000038                           # Criticial options len=56
    0000000f                         # 1st key string len=15
      666f6f406578616d706c652e636f6d #   "foo@example.com"
    00000000                         # 1st value string len=0
    0000000d                         # 2nd key string len=13
      666f7263652d636f6d6d616e64     #   "force-command"
    00000008                         # 2nd value string len=8
      00000004                       #   value body string len=4
        73667470                     #     "sftp"
		</sourcecode>
	</section>
	<section anchor="exts"><name>Certificate extensions</name>
		<t>
		Certificate extensions are encoded using the rules in
		<xref target="optionenc" />. When an implementation encounters
		an extension it does not recognise or support, it MUST ignore
		it and continue processing the certificate without error.
		</t>
		<t>
		There are no defined certificate extensions for host
		certificates.
		</t>
		<t>
		The initially defined certificate extensions for user
		certificates are:
		</t>
		<dl>
			<dt>no-touch-required</dt>
			<dd>
			<t>
			Valid for key types that support user-presence
			assertions in their signatures (such as FIDO-backed
			keys). This option indicates that signatures made
			with this certificate that
			do not assert user-presence should be accepted,
			reversing the default behaviour of refusing such
			signatures. Note that no such key types are currently
			standardised, but some SSH implementation support them
			as vendor extensions.
			</t>
			<t>
			This is a flag-type option. Its value is the
			empty string.
			</t>
			</dd>

			<dt>permit-agent-forwarding</dt>
			<dd>
			<t>
			Indicates that sessions authenticated with this
			certificate may request authentication agent forwarding
			<xref target="I-D.ietf-sshm-ssh-agent" />. Certificates
			that lack this extension MUST not permit this protocol
			feature be enabled on SSH server implementations that
			support it.
			</t>
			<t>
			This is a flag-type option. Its value is the
			empty string.
			</t>
			</dd>

			<dt>permit-port-forwarding</dt>
			<dd>
			<t>
			Indicates that sessions authenticated with this
			certificate may request authentication TCP forwarding
			using the "tcpip-forward" and/or "direct-tcpip"
			SSH channel requests defined in
			<xref target="RFC4254" section="7" />.
			Certificates
			that lack this extension MUST not permit these protocol
			features be enabled on SSH server implementations that
			support them.
			</t>
			<t>
			This is a flag-type option. Its value is the
			empty string.
			</t>
			</dd>

			<dt>permit-pty</dt>
			<dd>
			<t>
			Indicates that sessions authenticated with this
			certificate may request pseudo-terminal allocation
			using the "pty-req" SSH channel request defined in
			<xref target="RFC4254" section="6.2" />.
			Certificates
			that lack this extension MUST not permit this protocol
			feature be enabled on SSH server implementations that
			support it.
			</t>
			<t>
			This is a flag-type option. Its value is the
			empty string.
			</t>
			</dd>

			<dt>permit-user-rc</dt>
			<dd>
			<t>
			Indicates that sessions authenticated with this
			certificate may execute optional SSH-specific user
			initialisation scripts (e.g. "~/.ssh/rc").
			Certificates that lack this extension MUST not
			process these scripts on SSH server implementations
			that support them.
			</t>
			<t>
			This is a flag-type option. Its value is the
			empty string.
			</t>
			</dd>

			<dt>permit-X11-forwarding</dt>
			<dd>
			<t>
			Indicates that sessions authenticated with this
			certificate may request X11 protocol forwarding
			using the "x11-req" SSH channel request defined in
			<xref target="RFC4254" section="6.3" />.
			Certificates
			that lack this extension MUST not permit this protocol
			feature be enabled on SSH server implementations that
			support it.
			</t>
			<t>
			This is a flag-type option. Its value is the
			empty string.
			</t>
			</dd>

		</dl>
		<t>
		SSH implementations may define additional vendor extensions
		using the domain-qualified naming convention defined in
		<xref target="RFC4251" section="4.2" />.
		</t>
	</section>
	<section anchor="critopts"><name>Critical options</name>
		<t>
		Certificate critical options are encoded using the rules in
		<xref target="optionenc" />. When an implementation encounters
		an option it does not recognise or support, it MUST refuse
		to accept the certificate for authorisation decisions.
		</t>
		<t>
		There are no defined critical options for host
		certificates.
		</t>
		<t>
		The initially defined critical options for user
		certificates are:
		</t>
		<dl>
			<dt>force-command</dt>
			<dd>
			<t>
			Forces the execution of the specified command for
			any session (<xref target="RFC4254" section="6.5" />)
			of type "exec" or "shell" and overrides the
			subsystem name for sessions of type "subsystem".
			</t>
			<t>
			This is a string-type option. Its value contains a
			nested string which holds the command string.
			</t>
			</dd>

			<dt>source-address</dt>
			<dd>
			<t>
			Provides an allow-list of source addresses from which
			the certificate is valid. The address list consists of
			zero or more CIDR ranges (e.g. "192.0.2.0/29") or
			wildcard addresses (e.g. "192.0.2.*") separated by
			commas. If this option is present, servers MUST
			refuse connections from sources that are not listed.
			</t>
			<t>
			This is a string-type option. Its value contains a
			nested string which holds the allow-list.
			</t>
			</dd>

			<dt>verify-required</dt>
			<dd>
			<t>
			Valid for key types that support user verification
			assertions in their signatures (such as FIDO-backed
			keys). This option indicates that signatures made
			with this certificate that must require this assertion
			to be present in the signature and that servers
			MUST refuse authentication if it is absent.
			Note that no such key types are currently
			standardised, but some SSH implementation support them
			as vendor extensions.
			</t>
			<t>
			This is a flag-type option. Its value is the
			empty string.
			</t>
			</dd>

		</dl>
		<t>
		SSH implementations may define additional vendor extensions
		using the domain-qualified naming convention defined in
		<xref target="RFC4251" section="4.2" />.
		</t>
	</section>
	<section><name>Private certificate format</name>
		<t>
		For cases where a certificate and its associated private key
		must be serialised, such as adding one to a SSH authentication
		agent <xref target="I-D.ietf-sshm-ssh-agent" />, the following
		format is used;
		</t>
		<sourcecode>
    string              key type
    string              certificate blob
    byte[]              private key fields
		</sourcecode>
		<t>
		Where "key type" is the type of the certificate being encoded
		(e.g. "ssh-rsa-cert"), "certificate blob" is the entire encoded
		certificate as described in <xref target="fmt" /> and
		"private key fields" contain the encoded private key values
		as described in the following sections.
		</t>
		<section><name>DSA certificates</name>
			<t>
			DSA certificates with private keys use the following
			encoding format.
			</t>
			<sourcecode>
    string              "ssh-dss-cert"
    string              certificate blob
    byte[]              private key fields
    mpint               x
			</sourcecode>
			<t>
			The "y" parameters is defined as per
			Section 4.1 of <xref target="FIPS.186-4"/>.
			</t>
		</section>
		<section><name>ECDSA certificates</name>
			<t>
			ECDSA certificates with private keys use the following
			encoding format.
			</t>
			<sourcecode>
    string              "ecdsa-sha2-nistp256-cert" |
                        "ecdsa-sha2-nistp384-cert" |
                        "ecdsa-sha2-nistp521-cert"
    string              certificate blob
    byte[]              private key fields
    mpint               d
			</sourcecode>
			<t>
			The "d" value is defined
			by Section 6.2 of <xref target="FIPS.186-5"/>.
			</t>
		</section>
		<section><name>EDDSA certificates</name>
			<t>
			EDDSA certificates with private keys use the following
			encoding format.
			</t>
			<sourcecode>
    string              "ssh-ed25519-cert" | "ssh-ed448-cert"
    string              certificate blob
    byte[]              private key fields
    string              k || ENC(A)
			</sourcecode>
			<t>
			The encoded value is a concatenation of
			the private key k and the public ENC(A) key.
			The contents and interpretation of the
			ENC(A) and k values are
			defined by <xref target="RFC8032" section="3.2"/>.
			</t>
		</section>
		<section><name>RSA certificates</name>
			<t>
			EDDSA certificates with private keys use the following
			encoding format.
			</t>
			<sourcecode>
    string              "ssh-dss-cert"
    string              certificate blob
    byte[]              private key fields
    mpint               d
    mpint               iqmp
    mpint               p
    mpint               q
			</sourcecode>
			<t>
			"p" and "q" are its constituent private
			prime factors.
			"iqmp" is the inverse of "q" modulo
			"p". All these values except "iqmp"
			(which can be calculated from the others)
			are defined by Section 5.1 of
			<xref target="FIPS.186-4" />.
			</t>
		</section>
	</section>
</section>

<section><name>Using certificates</name>
	<t>
	Certificates may be appear and be used any place in the SSH protocol
	where plain keys are used.
	In particular, they may be used for server authentication or for
	user public-key authentication.
	For each of these cases, the certificate, encoded as per
	<xref target="fmt" /> appears in place of the encoded key.
	</t>
	<section title="Accepting certificates">
		<t>
		Implementations that accept a certificate MUST verify the CA
		signature over the certificate contents prior to making
		any authentication or authorisation decisions.
		Implementations MAY elect to verify the certificate signature
		as soon as the certificate is received.
		</t>
		<t>
		When making authentication or authorisation decisions with a
		certificate, implementations:
		</t>
		<ul>
			<li><t>MUST check that the certificate is well-formed</t></li>
			<li><t>MUST ensure that no unsupported critical options are present</t></li>
			<li><t>MUST check that the "certificate role" matches the intended decision type (user or host authentication)</t></li>
			<li><t>MUST check the time against the certificate validity interval</t></li>
			<li><t>MUST verify that at least one of the listed certificate principals is accepted</t></li>
			<li><t>MUST perform any additional authorisation operations required by critical options.</t></li>
		</ul>
	</section>
	<section title="Certificate signatures">
		<t>
		When signatures are required, they are made and formatted using
		the same rules for the underlying plain key type. For example, a
		"ssh-rsa-cert" could produce signatures of types "ssh-rsa" using
		the rules from <xref target="RFC4253" section="6.6" />, or
		"rsa-sha2-256" or "rsa-sha2-512" using the rules from
		<xref target="RFC8332" section="3" />.
		</t>
	</section>
	<section title="Use in host authentication">
		<t>
		Certificate host keys may be used for server authentication
		as part of the initial key exchange or for subsequent
		re-exchange. To use a certificate host key, its key type name
		(e.g. "ssh-ed25519-cert") must appear in the
		server_host_key_algorithms of the SSH_MSG_KEXINIT
		(<xref target="RFC5656" section="7.1" />).
		If negotiated by both the server and the client, then
		a certificate of the agreed type may take the place
		of the plain host key in the final reply message. For example
		in ECDH host authentication
		(<xref target="RFC5656" section="4" />),
		host authentication occurs in the
		final SSH_MSG_KEX_ECDH_REPLY message:
		</t>
		<sourcecode>
    byte                SSH_MSG_KEX_ECDH_REPLY
    string              K_S, server's certificate
    string              Q_S, server's ephemeral ECDH public key
    string              the signature on the exchange hash
		</sourcecode>
		<t>
		Certificates used for host authentication MUST have
		"certificate role" of SSH2_CERT_TYPE_HOST. Other certificate
		types MUST not be accepted.
		</t>
		<t>
		Certificate host keys list hostnames and/or IP addresses for
		the host in their "principals" section. Clients MUST match
		the hostname or address thay are using for the host against
		the principals in this list and refuse to authorise the
		certificate if it is absent.
		</t>
		<t>
		Clients that accept certified host keys MAY downgrade the
		certificate to a plain public key and process it accordingly,
		if they are unable to verify the certificate. This allows
		recovery from the situation where the endpoints negotiate
		use of a cerificate host key but the client is not able to
		authorise the certificate contents, perhaps because the CA
		is not trusted or because the host name the client is using
		does not match any in the certificate.
		</t>
	</section>
	<section title="Use in user authentication">
		<t>
		For user public key authentication
		No prior negotiation is needed to send a user
		authentication attempt that contains a certificate, though
		clients may wish to filter the ones they send against the
		server's list of accepted publickey authentication signature
		algorithms if one was provided via the
		<xref target="RFC8308" />SSH_MSG_EXT_INFO mechanism.
		</t>
		<t>
		Certificates used for user authentication MUST have
		"certificate role" of SSH2_CERT_TYPE_USER. Other certificate
		types MUST not be accepted.
		</t>
		<t>
		Certificate keys for user authentication list one or more
		user principal names in their "principals" section.
		Interpretation and authorisation of principal names for a
		given target user name is fully determined by the server.
		In the trivial case, a certificate may list user names directly
		and the server merely matches the user name in the
		SSH_MSG_USERAUTH_REQUEST
		(<xref target="RFC4252" section="7" />)
		to one of the principals in the certificate.
		</t>
		<t>
		To make a user authentication attempt using a certificate
		host key, the certificate takes the place of the plain
		public key in a SSH_MSG_USERAUTH_REQUEST message.
		For example:
		</t>
		<sourcecode>
    byte                SSH_MSG_USERAUTH_REQUEST
    string              user name
    string              service name
    string              "publickey"
    boolean             TRUE
    string              certificate key algorithm name
    string              encoded certificate
    string              signature
		</sourcecode>
	</section>
</section>

<section><name>Protocol numbers</name>
	<section anchor="certtypes" title="Certificate types">
		<t>
		The following numbers are used for certificate types:
		</t>
		<sourcecode>
    SSH2_CERT_TYPE_USER                1
    SSH2_CERT_TYPE_HOST                2
		</sourcecode>
	</section>
</section>

<section anchor="IANA"><name>IANA Considerations</name>
	<t>
	This format requires creation of one new registry and additions to an
	existing registry.
	</t>
	<section title="Additions to SSH key type registry">
		<t>
		IANA is requested to insert the following entries into the
		table Public Key Algorithm Names
		<xref target="IANA-SSH-KEYTYPES" /> under
		Secure Shell (SSH) Protocol Parameters
		<xref target="RFC4250" />.
		</t>
		<table>
		<thead>
		<tr><th>Key type name</th><th>Reference</th></tr>
		</thead>
		<tbody>
		<tr><td>ssh-dss-cert</td><td><xref target="dsacert" /></td></tr>
		<tr><td>ecdsa-sha2-nistp256-cert</td><td><xref target="ecdsacert" /></td></tr>
		<tr><td>ecdsa-sha2-nistp384-cert</td><td><xref target="ecdsacert" /></td></tr>
		<tr><td>ecdsa-sha2-nistp521-cert</td><td><xref target="ecdsacert" /></td></tr>
		<tr><td>ssh-ed25519-cert</td><td><xref target="eddsacert" /></td></tr>
		<tr><td>ssh-ed448-cert</td><td><xref target="eddsacert" /></td></tr>
		<tr><td>ssh-rsa-cert</td><td><xref target="rsacert" /></td></tr>
		</tbody>
		</table>
	</section>
	<section title="New registry: Certificate Extension Identifiers">
		<t>
		This registry, titled "Certificate Extension Identifiers"
		records identifiers for certificate extensions.
		Its initial state should consist of the
		following names.
		Future name allocations shall occur via
		EXPERT REVIEW as per <xref target="RFC8126" />.
		</t>
		<table>
		<thead>
		<tr><th>Extension name</th><th>Reference</th></tr>
		</thead>
		<tbody>
		<tr><td>no-touch-required</td><td><xref target="exts" /></td></tr>
		<tr><td>permit-agent-forwarding</td><td><xref target="exts" /></td></tr>
		<tr><td>permit-port-forwarding</td><td><xref target="exts" /></td></tr>
		<tr><td>permit-pty</td><td><xref target="exts" /></td></tr>
		<tr><td>permit-user-rc</td><td><xref target="exts" /></td></tr>
		<tr><td>permit-X11-forwarding</td><td><xref target="exts" /></td></tr>
		</tbody>
		</table>
	</section>
	<section title="New registry: Certificate Criticial Option Identifiers">
		<t>
		This registry, titled "Certificate Critical Option Identifiers"
		records identifiers for certificate criticial options.
		Its initial state should consist of the
		following names.
		Future names allocations shall occur via
		EXPERT REVIEW as per <xref target="RFC8126" />.
		</t>
		<table>
		<thead>
		<tr><th>Option name</th><th>Reference</th></tr>
		</thead>
		<tbody>
		<tr><td>force-command</td><td><xref target="critopts" /></td></tr>
		<tr><td>source-address</td><td><xref target="critopts" /></td></tr>
		<tr><td>verify-required</td><td><xref target="critopts" /></td></tr>
		</tbody>
		</table>
	</section>
	<section title="New registry: Certificate Type Numbers">
		<t>
		This registry, titled "Certificate Type Numbers"
		records the numbers used to indicate the types of certificates.
		Its initial state should consist of the
		following numbers.
		Future message number allocations shall occur via
		EXPERT REVIEW as per <xref target="RFC8126" />.
		</t>
<table>
<thead>
<tr><th>Number</th><th>Identifier</th><th>Reference</th></tr>
</thead>
<tbody>
<tr><td>1</td><td>SSH2_CERT_TYPE_USER</td><td><xref target="certtypes" /></td></tr>
<tr><td>2</td><td>SSH2_CERT_TYPE_HOST</td><td><xref target="certtypes" /></td></tr>
</tbody>
</table>
	</section>
</section>

<section anchor="Security"><name>Security Considerations</name>
	<t>
	XXX TODO XXX
	</t>
</section>

<section anchor="implstatus"><name>Implementation Status</name>
	<t>
	This section records the status of known implementations of the
	protocol defined by this specification at the time of posting of
	this Internet-Draft, and is based on a proposal described in
	<xref target="RFC7942" />. The description of implementations in
	this section is intended to assist the IETF in its decision processes
	in progressing drafts to RFCs. Please note that the listing of any
	individual implementation here does not imply endorsement by the
	IETF. Furthermore, no effort has been spent to verify the
	information presented here that was supplied by IETF contributors.
	This is not intended as, and must not be construed to be, a
	catalog of available implementations or their features. Readers
	are advised to note that other implementations may exist.
	</t>
	<t>
	According to <xref target="RFC7942" />, "this will allow reviewers
	and working groups to assign due consideration to documents that
	have the benefit of running code, which may serve as evidence of
	valuable experimentation and feedback that have made the implemented
	protocols more mature. It is up to the individual working groups
	to use this information as they see fit".
	</t>
	<t>
	The following example projects maintain implementations of SSH
	certificates. All have implemented them in the vendor extension
	namespace, e.g. "ssh-rsa-cert-v01@openssh.com".
	</t>
	<dl>
		<dt>OpenSSH</dt>
		<dd>
		<t>
		OpenSSH is the originating implementation of this protocol and
		has supported it since 2010.
		</t>
		<t>
		Website: https://www.openssh.com/
		</t>
		</dd>

		<dt>libssh</dt>
		<dd>
		<t>
		libssh has supported this format since 2011.
		</t>
		<t>
		Website: https://www.libssh.org/
		</t>
		</dd>

		<dt>Golang x/crypto/ssh</dt>
		<dd>
		<t>
		The Go programming language project has supported an
		implementation of this format in its external "x" repository
		since 2012.
		</t>
		<t>
		Website: https://pkg.go.dev/golang.org/x/crypto/ssh
		</t>
		</dd>

		<dt>Net::SSH</dt>
		<dd>
		<t>
		The Net::SSH library has supported this format since 2014.
		</t>
		<t>
		Website: https://net-ssh.github.io/net-ssh/
		</t>
		</dd>

		<dt>AsyncSSH</dt>
		<dd>
		<t>
		The AsyncSSH library has supported this format since 2015.
		</t>
		<t>
		Website: https://github.com/ronf/asyncssh
		</t>
		</dd>

		<dt>Paramiko</dt>
		<dd>
		<t>
		The Paramiko library has supported this format since 2017
		</t>
		<t>
		Website: https://www.paramiko.org/
		</t>
		</dd>

		<dt>Apache MINA SSHD</dt>
		<dd>
		<t>
		The Apache MINA SSHD server library has supported this format
		since 2020.
		</t>
		<t>
		Website: https://mina.apache.org/sshd-project/
		</t>
		</dd>

		<dt>PuTTY</dt>
		<dd>
		<t>
		The PuTTY SSH client has supported this format since 2022.
		</t>
		<t>
		Website: https://www.chiark.greenend.org.uk/~sgtatham/putty/
		</t>
		</dd>

		<dt>russh</dt>
		<dd>
		<t>
		The russh library has supported this format since 2024.
		</t>
		<t>
		Website: https://github.com/Eugeny/russh
		</t>
		</dd>

	</dl>
	<t>
		Additionally, Google's HIBA system <xref target="HIBA" /> builds
		on top of the OpenSSH certificate format to perform
		centralised authorisation for pool of target hosts.
	</t>
</section>
</middle>

<back>
<references>
	<name>References</name>
	<references><name>Normative References</name>
		<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml" />
		<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.4250.xml" />
		<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.4251.xml" />
		<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.4252.xml" />
		<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.4253.xml" />
		<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.4254.xml" />
		<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.5656.xml" />
		<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7942.xml" />
		<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8032.xml" />
		<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8126.xml" />
		<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml" />
		<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8332.xml" />
		<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8308.xml" />
		<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8709.xml" />
		<xi:include href="https://datatracker.ietf.org/doc/bibxml3/draft-ietf-sshm-ssh-agent-02.xml" />
		<reference anchor="FIPS.186-4">
			<front>
				<title>Digital Signature Standard (DSS)</title>
				<author>
					<organization>
						National Institute of
						Standards and Technology
					</organization>
				</author>
				<date month="July" year="2013" />
			</front>
			<refcontent>FIPS PUB 186-4</refcontent>
			<seriesInfo name="DOI" value="10.6028/NIST.FIPS.186-4"/>
		</reference>
		<reference anchor="FIPS.186-5">
			<front>
				<title>Digital Signature Standard (DSS)</title>
				<author>
					<organization>
						National Institute of
						Standards and Technology
					</organization>
				</author>
				<date month="February" year="2023" />
			</front>
			<refcontent>FIPS PUB 186-5</refcontent>
			<seriesInfo name="DOI" value="10.6028/NIST.FIPS.186-5"/>
		</reference>
	</references>

	<references><name>Informative References</name>
			<reference anchor="IANA-SSH-KEYTYPES" target="https://www.iana.org/assignments/ssh-parameters/"><front>
			<title>Public Key Algorithm Names</title>
			<author>
				<organization>IANA</organization>
			</author>
		</front></reference>
			<reference anchor="HIBA" target="https://github.com/google/hiba"><front>
			<title>HIBA: Host Identity Based Authorization</title>
			<author>
				<organization>Google</organization>
			</author>
		</front></reference>
	</references>
</references>


<section anchor="Acknowledgements" numbered="false"><name>Acknowledgements</name>
	<t>
	XXX YOUR NAME HERE XXX
	</t>
</section>

<section anchor="appendix_example" numbered="false"><name>Example certificates</name>
	<t>
	This is an example of a hex-encoded certificate for an
	ecdsa-sha2-nistp256-cert public key, signed by a ssh-ed25519
	certificate authority.
	</t>
	<sourcecode>
    0000: 0000 0018 6563 6473 612d 7368 6132 2d6e  ....ecdsa-sha2-n
    0010: 6973 7470 3235 362d 6365 7274 0000 0020  istp256-cert...
    0020: 7ee0 cb87 8240 788b 087e 0a23 f505 1828  ~....@x..~.#...(
    0030: 98e1 510f b3a2 fcf6 4086 30f6 25b1 aa19  ..Q.....@.0.%...
    0040: 0000 0008 6e69 7374 7032 3536 0000 0041  ....nistp256...A
    0050: 04a5 7c7c 0829 b7ee 3473 1383 52b8 afc1  ..||.)..4s..R...
    0060: 673c 7145 29de 5f0f a699 4f08 6f58 8f96  g&lt;qE)._...O.oX..
    0070: c9ad 70d3 0b20 a4e9 3558 ffd3 f85d ddfa  ..p.. ..5X...]..
    0080: 313d 294b 2b9f 2862 dd2b 5831 3688 065c  1=)K+.(b.+X16..\
    0090: 52ab 54a9 8ceb 1f0a d200 0000 0100 0000  R.T.............
    00a0: 136a 6f73 6566 2e6b 4065 7861 6d70 6c65  .josef.k@example
    00b0: 2e6f 7267 0000 001e 0000 0007 6a6f 7365  .org........jose
    00c0: 662e 6b00 0000 0f45 5841 4d50 4c45 5c6a  f.k....EXAMPLE\j
    00d0: 6f73 6566 2e6b 0000 0000 4d4a 2972 0000  osef.k....MJ)r..
    00e0: 0000 82e9 0790 0000 0020 0000 000d 666f  ......... ....fo
    00f0: 7263 652d 636f 6d6d 616e 6400 0000 0b00  rce-command.....
    0100: 0000 0765 7865 6375 7465 0000 0082 0000  ...execute......
    0110: 0015 7065 726d 6974 2d58 3131 2d66 6f72  ..permit-X11-for
    0120: 7761 7264 696e 6700 0000 0000 0000 1770  warding........p
    0130: 6572 6d69 742d 6167 656e 742d 666f 7277  ermit-agent-forw
    0140: 6172 6469 6e67 0000 0000 0000 0016 7065  arding........pe
    0150: 726d 6974 2d70 6f72 742d 666f 7277 6172  rmit-port-forwar
    0160: 6469 6e67 0000 0000 0000 000a 7065 726d  ding........perm
    0170: 6974 2d70 7479 0000 0000 0000 000e 7065  it-pty........pe
    0180: 726d 6974 2d75 7365 722d 7263 0000 0000  rmit-user-rc....
    0190: 0000 0000 0000 0033 0000 000b 7373 682d  .......3....ssh-
    01a0: 6564 3235 3531 3900 0000 20d5 258d f8cb  ed25519... .%...
    01b0: 1bda 81d7 9a2f 6b4d 1304 d497 0add 67eb  ...../kM......g.
    01c0: 04b9 d5de 47d9 cc0c d5ff 5000 0000 5300  ....G.....P...S.
    01d0: 0000 0b73 7368 2d65 6432 3535 3139 0000  ...ssh-ed25519..
    01e0: 0040 5864 29cc 18fd 8b1d 19f3 210e c11e  .@Xd).......!...
    01f0: 43a9 bde1 90e6 0505 8733 d333 e806 5381  C........3.3..S.
    0200: 81b4 d847 6efa 3889 6706 30ea 8117 f2e5  ...Gn.8.g.0.....
    0210: 25c4 6e6e 2378 5e27 1c25 7653 3af5 ca9f  %.nn#x^'.%vS:...
    0220: 0b05 0a
	</sourcecode>
	<t>
	This is an annotated version of the above certificate. Note that
	all offsets are inclusive, e.g. "0010-0013" refers to a four-byte
	sequence.
	</t>
	<sourcecode>
    # 0000-001b: 0018 6563 6473 ... 7274
    string              key type name "ecdsa-sha2-nistp256-cert"
    # 001c-003f: 0020 7ee0 cb87 ... aa19
    string              nonce
    # 0040-004b: 0008 6e69 7374 7032 3536
    string              ECDSA curve name "nistp256"
    # 004c-0090: 0000 0041 04a5 7c7c ... 5c52
    string              ECDSA Q point
    # 0091-0098: ab54 a98c eb1f 0ad2 (12345678901234567890)
    uint64              serial number
    # 0099-009c: 0000 0001 (SSH2_CERT_TYPE_USER)
    uint32              certificate role
    # 009d-00b3: 0000 0013 6a6f ... 7267
    string              identifier "josef.k@example.org"
    # 00b4-00d5: 0000 001e 0000 0007 ... 0790
    string              principals
        # 00b8-00c2: 0000 0007 6a6f 7365 662e 6b
        string          principal[0] = "josef.k"
        # 00c3-00d5: 000f 4558 414d 504c 455c 6a6f 7365 662e 6b
        string          principal[1] = "EXAMPLE\josef.k"
    # 00d6-00dd: 0000 0000 4d4a 2972
    uint64              valid after = 2011/02/03T04:05:06 UTC
    # 00de-00e5: 0000 0000 82e9 0790
    uint64              valid before = 2039/08/07T06:05:04 UTC
    # 00e6-0109: 0020 0000 000d ... 7465
    string              critical options
        # 00ea-00fa: 0000 000d 666f 7263 652d 636f 6d6d 616e 64
        string          key[0] = "force-command"
        # 00fb-0109: 0000 000b 0000 0007 6578 6563 7574 65
        string          value[0]
            # 00ff-0109: 0000 0007 6578 6563 7574 65
            string      "execute"
    # 010a-0190: 0000 0082 0000 0015 ... 7263
    string              extensions
        # 010e-0126: 0000 0015 7065 ... 6e67
        string          key[0] = "permit-X11-forwarding"
        # 0127-012a: 0000 0000
        string          value[0] = (empty)
        # 012b-0145: 0000 0017 7065 726d ... 6e67
        string          key[1] = "permit-agent-forwarding"
        # 0146-0149: 0000 0000
        string          value[1] = (empty)
        # 014a-0163 0000 0016 7065 ... 6e67
        string          key[2] = "permit-port-forwarding"
        # 0164-0167: 0000 0000
        string          value[2] = (empty)
        # 0168-0175: 0000 000a 7065 726d 6974 2d70 7479
        string          key[3] = "permit-pty"
        # 0176-0179: 0000 0000
        string          value[3] = (empty)
        # 017a-018b: 0000 000e 7065 726d 6974 2d75 7365 722d 7263
        string          key[4] = "permit-user-rc"
        # 018c-018f: 0000 0000
        string          value[4] = (empty)
    # 0190-0193: 0000 0000
    string              reserved = (empty)
    # 0194-01ca: 0000 0033 0000 000b ... ff50
    string              signature key (ssh-ed25519)
    # 01cb-0222: 0000 0053 0000 000b ... 050a
    string              signature (ssh-ed25519)
	</sourcecode>
</section>

</back>
</rfc>
