Binary certificate formats

This document describes two certificate formats that Tor uses for certifying Ed25519 keys, and discusses how those formats is labeled and encoded.

There are:

These are not the only certificate format that Tor uses. For the certificates that authorities use for their signing keys, see “Authority key certificates”.

Additionally, Tor uses TLS, which depends on X.509 certificates.

The certificates in this document were first introduced in proposal 220, and were first supported by Tor in Tor version 0.2.7.2-alpha.

Tor Ed25519 Certificates

A Tor Ed25519 Certificate certifies a key, or a digest of a key, or a digest of some other object, using an Ed25519 key to sign it.

FieldSizeDescription
VERSION1The version of this format
CERT_TYPE1Purpose and meaning of the cert
EXPIRATION_DATE4When the cert becomes invalid
CERT_KEY_TYPE1Type of CERTIFIED_KEY
CERTIFIED_KEY32Certified key, or its digest
N_EXTENSIONS1Number of extensions
N_EXTENSIONS times:
- ExtLen2Length of encoded extension body
- ExtType1Type of extension
- ExtFlags1Control interpretation of extension
- ExtDataExtLenEncoded extension body
SIGNATURE64Signature of all previous fields

The VERSION field holds the value [01].

The CERT_TYPE field holds a value depending on the type of certificate. (See “Certificate types”.)

The CERTIFIED_KEY field is a subject public key, or a digest of a subject public key. The representation depends on the value of CERT_KEY_TYPE. (See “List of certified key types”.)

Note that the Tor Ed25519 Certificate format can only certify objects of length 32. To sign a longer key, we compute its digest. But if we need to make certificates that includes the full value of a longer key, we’ll have to use a new extension, or a new certificate.

The EXPIRATION_DATE is a date, given in hours since the epoch, after which this certificate isn’t valid.

(A four-byte date here will work fine until 10136 A.D.)

The ExtFlags field holds flags. Only one flag is currently defined:

  • 1: AFFECTS_VALIDATION. This flag tells an implementation how to handle an extension whose ExtType it does not recognize. If this flag is set on an extension, then the extension affects whether the certificate is valid; implementations MUST NOT accept the certificate as valid if the do not recognize the extension’s ExtType. If this flag is not set on an extension, implementations MUST ignore that extension if they do not recognize the ExtType.

Ignoring a recognized extension is never valid.

The interpretation of ExtBody depends on the ExtType field. See “Recognized extensions” below.

It is an error for an ExtLen to extend beyond the end of a certificate.

Before acting based on any certificate, parties MUST know which key it is supposed to be signed by, and then check the signature.

It is okay to inspect the certificate’s fields before checking the signature, and reject the certificate if is ill-formed, expired, or so on.

This does not count as “acting based on a certificate.”

The signature is created as an Ed25519 signature, over all the fields in the certificate up until but not including SIGNATURE.

Note that this signature is not personalized with a prefix string. That’s probably an oversight that we should correct if we make another cert format in the future.

Defined Tor Ed25519 certificate extensions

Signed-with-ed25519-key extension [type 04]

In several places, it’s desirable to bundle the signing key along with the certificate. We do so with this extension.

With this extension:

  • ExtLen is 32.
  • `ExtData is a 32-byte Ed25519 public key.

When this extension is present, it MUST match the key used to sign the certificate.

Tor RSA→Ed25519 cross-certificate

A Tor RSA→Ed25519 Cross-certificate signs an Ed25519 key using a legacy 1024-bit RSA key. Its format is:

FieldSizeDescription
ED25519_KEY32The subject key
EXPIRATION_DATE4When the cert becomes invalid
SIGLEN1Length of RSA signature.
SIGNATURESIGLENRSA Signature

Just as with the Ed25519 certificates above, the EXPIRATION_DATE field is a number of hours since the epoch.

As elsewhere, the RSA signature is generated using RSA-PKCSv1 padding, with hash algorithm OIDs omitted.

The signature is computed on the SHA-256 digest of PREFIX | FIELDS, where PREFIX is the string "Tor TLS RSA/Ed25519 cross-certificate" (without any terminating NUL), and FIELDS is all other fields in the certificate (other than the signature itself).

Certificate types (CERT_TYPE field)

This table shows values that can appear in the CertType field used in a CERTS cell during channel negotiation.

Some of these values (those marked with “Ed”) are also used in the CERT_TYPE field in Tor Ed25519 certificates. (X.509 and RSA→Ed25519 cross-certificates don’t have a CERT_TYPE field.)

You might need to scroll this table to view it all.

We’ll try to fix this once we have a better grip on our mdbook CSS.

TypeMnemonicFormatSubjectSigning keyReferenceNotes
[01]TLS_LINK_X509X.509KP_legacy_conn_tlsKS_relayid_rsaLegacy channel negotiationObsolete
[02]RSA_ID_X509X.509KP_relayid_rsaKS_relayid_rsaLegacy channel negotiationObsolete
[03]LINK_AUTH_X509X.509KP_legacy_linkauth_rsaKS_relayid_rsaLegacy channel negotiationObsolete
[04]IDENTITY_V_SIGNINGEdKP_relaysign_edKS_relayid_edOnline signing keys
[05]SIGNING_V_TLS_CERTEdA TLS certificateKS_relaysign_edCERTS cells
[06]SIGNING_V_LINK_AUTHEdKP_link_edKS_relaysign_edCERTS cells
[07]RSA_ID_V_IDENTITYRsaKP_relayid_edKS_relayid_rsaCERTS cells
[08]BLINDED_ID_V_SIGNINGEdKP_hs_desc_signKS_hs_blind_idHsDesc (outer)
[09]HS_IP_V_SIGNINGEdKP_hs_ipt_sidKS_hs_desc_signHsDesc (auth-key)Backwards, see note 1
[0A]NTOR_CC_IDENTITYEdKP_relayid_edEdCvt(KS_ntor)ntor cross-cert
[0B]HS_IP_CC_SIGNINGEdKP_hss_ntorKS_hs_desc_signHsDesc (enc-key-cert)Backwards, see note 1
[[0C]FAMILY_V_IDENTITYEdKP_relayid_edKS_familyid_edfamily-cert

Note 1: The certificate types [09] HS_IP_V_SIGNING and [0B] HS_IP_CC_SIGNING were implemented incorrectly, and now cannot be changed. Their signing keys and subject keys, as implemented, are given in the table. They were originally meant to be the inverse of this order.

List of extension types

List of certified key types (CERT_KEY_TYPE field)

  • [01]: ed25519 key
  • [02]: SHA256(DER(key)) for an RSA key. (Not currently used.)
  • [03]: SHA-256 digest of an X.509 certificate. (Used with certificate type 5.)

(NOTE: Up till 0.4.5.1-alpha, all versions of Tor have incorrectly used [01] for all types of certified key. Implementations SHOULD allow “01” in this position, and infer the actual key type from the CERT_TYPE field.