# Certificates in Tor

This document describes a certificate formats that Tor uses for
its Ed25519 internal certificates,
and discusses how that format is labeled and encoded.

This format is not the only certificate format that Tor uses.
For the certificates that authorities use
for their signing keys,
see ["Creating key certificates"](dir-spec/creating-key-certificates.md).

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.

<a id="cert-spec.txt-1.1"></a>

## Signing

All signatures here, unless otherwise specified,
are computed using an Ed25519 key.

In order to future-proof the format,
before signing anything,
the signed document is prefixed with a personalization string,
which will be different in each case.

<a id="cert-spec.txt-2"></a>

## Document formats

### X.509 certificates {#x509}

Describing this format is out of scope
for the Tor specifications.

<a id="cert-spec.txt-2.1"></a>

### Ed25519 Certificates {#ed-certs}

When generating a signing key,
we also generate a certificate for it.
These representation for this certificate is:

| Field            | Size | Description                         |
| ---------------- | ---- | ----------------------------------- |
| `VERSION`        | 1    | The version of this format          |
| `CERT_TYPE`      | 1    | [Purpose and meaning of the cert](#list-cert-types) |
| `EXPIRATION_DATE`| 4    | When the cert becomes invalid       |
| `CERT_KEY_TYPE`  | 1    | [Type of `CERTIFIED_KEY`](#list-key-types) |
| `CERTIFIED_KEY`  | 32   | Certified key, or its digest        |
| `N_EXTENSIONS`   | 1    | Number of extensions                |
| `N_EXTENSIONS` times: | |                                     |
| - `ExtLen`       | 2    | Length of encoded extension body    |
| - `ExtType`      | 1    | [Type of extension](#list-ext-types)|
| - `ExtFlags`     | 1    | Control interpretation of extension |
| - `ExtData`      | `ExtLen` | Encoded extension body          |
| `SIGNATURE`      | 64   | Signature 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"](#list-cert-types).)

The `CERTIFIED_KEY` field is an Ed25519 public key
if CERT_KEY_TYPE is `[01]`, or a digest of some other key type
depending on the value of CERT_KEY_TYPE.
(See ["List of certified key types"](#list-key-types).)

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`.
  If this flag is present,
  then the extension affects whether the certificate is valid;
  implementations MUST NOT accept the certificate as valid
  unless they recognize the `ExtType`
  and accept the extension as valid.

The interpretation of `ExtBody` depends on the `ExtType` field.
See ["Recognized extensions"](#extensions) below.

It is an error for an extension to be truncated;
such a certificate is invalid.

Before processing any certificate,
parties SHOULD know which key it is supposed to be signed by,
and then check the signature.

The signature is created by signing all the fields in the certificate
up until but not including `SIGNATURE`.


<a id="cert-spec.txt-2.2"></a>

### Recognized extensions {#extensions}

<a id="cert-spec.txt-2.2.1"></a>

#### Signed-with-ed25519-key extension \[type 04\] { #signed-with-ed25519 }

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.

<a id="cert-spec.txt-2.3"></a>

### RSA→Ed25519 cross-certificate { #rsa-cross-cert }

In one place,
we have a binary certificate that signs an Ed25519 key
using a legacy 1024-bit RSA key.
Its format is:

| Field             | Size | Description |
| ----------------- | ---- | ----------- |
| `ED25519_KEY`     | 32   | The subject key
| `EXPIRATION_DATE` | 4    | When the cert becomes invalid |
| `SIGLEN`          | 1    | Length of RSA signature. |
| `SIGNATURE`       | `SIGLEN` | RSA Signature |

Just as with the
[Ed25519 certificates above](#ed-certs),
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 SHA256 hash 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).

<a id="cert-spec.txt-A.1"></a>

## Certificate types (CERT_TYPE field) { #list-cert-types }

This table shows values of the `CERT_TYPE` field in Ed,
as well as values of the `CertType` field
used in a [`CERTS` cell](./tor-spec/negotiating-channels.md#CERTS-cells)
during channel negotiation.

> You might ned to scroll this table to view it all.
>
> We'll try to fix this once we have a better grip on our mdbook CSS.

| Type | Mnemonic         | Format | Subject                 | Signing key         | Reference | Notes |
|------| -------------    | ------ | ----------------------- | ------------        | --------- | ----- |
|`[01]`| `TLS_LINK_X509`  | [X.509]| [`KP_legacy_conn_tls`]  | [`KS_relayid_rsa`]  | [Legacy channel negotiation] | Obsolete |
|`[02]`| `RSA_ID_X509`    | [X.509]| [`KP_relayid_rsa`]      | [`KS_relayid_rsa`]  | [Legacy channel negotiation] | Obsolete |
|`[03]`| `LINK_AUTH_X509` | [X.509]| [`KP_legacy_linkauth_rsa`]|[`KS_relayid_rsa`]    | [Legacy channel negotiation] | Obsolete |
|`[04]`| `IDENTITY_V_SIGNING` |[Ed]| [`KP_relaysign_ed`]     | [`KS_relayid_ed`]   | [Online signing keys] | |
|`[05]`| `SIGNING_V_TLS_CERT` |[Ed]| A TLS certificate       | [`KS_relaysign_ed`] | [CERTS cells] | |
|`[06]`| `SIGNING_V_LINK_AUTH`|[Ed]| [`KP_link_ed`]          | [`KS_relaysign_ed`] | [CERTS cells] | |
|`[07]`| `RSA_ID_V_IDENTITY`  |[Rsa]|[`KP_relayid_ed`]       | [`KS_relayid_rsa`]  | [CERTS cells] | |
|`[08]`| `BLINDED_ID_V_SIGNING`|[Ed]|[`KP_hs_desc_sign`]     | [`KS_hs_blind_id`]  | [HsDesc (outer)] | |
|`[09]`| `HS_IP_V_SIGNING`    |[Ed]| [`KP_hs_ipt_sid`]       | [`KS_hs_desc_sign`] | [HsDesc (`auth-key`)] | Backwards, see [note 1](#note-1) |
|`[0A]`| `NTOR_CC_IDENTITY`   |[Ed]| [`KP_relayid_ed`]       | [`EdCvt`]`(`[`KS_ntor`]`)` | [ntor cross-cert] | |
|`[0B]`| `HS_IP_CC_SIGNING`   |[Ed]| [`KP_hss_ntor`]         | [`KS_hs_desc_sign`]  | [HsDesc (`enc-key-cert`)] | Backwards, see [note 1](#note-1) |

[X.509]: #x509
[Rsa]: #rsa-cross-cert
[Ed]: #ed-certs
[`KP_legacy_conn_tls`]: ./tor-spec/relay-keys.md#legacy_conn_tls
[`KP_legacy_linkauth_rsa`]: ./tor-spec/relay-keys.md#legacy_linkauth_rsa
[`KP_relayid_rsa`]: ./tor-spec/relay-keys.md#relayid_rsa
[`KP_relaysign_ed`]:  ./tor-spec/relay-keys.md#relaysign_ed
[`KP_relayid_ed`]:  ./tor-spec/relay-keys.md#relayid_ed
[`KP_link_ed`]:  ./tor-spec/relay-keys.md#link_ed
[`KS_legacy_conn_tls`]: ./tor-spec/relay-keys.md#legacy_conn_tls
[`KS_relayid_rsa`]: ./tor-spec/relay-keys.md#relayid_rsa
[`KS_relaysign_ed`]:  ./tor-spec/relay-keys.md#relaysign_ed
[`KS_relayid_ed`]:  ./tor-spec/relay-keys.md#relayid_ed
[`KS_ntor`]: ./tor-spec/relay-keys.md#ntor
[`KS_link_ed`]:  ./tor-spec/relay-keys.md#link_ed
[`KP_hs_desc_sign`]: ./rend-spec/protocol-overview.md#hs_desc_sign
[`KS_hs_desc_sign`]: ./rend-spec/protocol-overview.md#hs_desc_sign
[`KP_hs_ipt_sid`]:  ./rend-spec/protocol-overview.md#hs_ipt_sid
[`KP_hss_ntor`]: ./rend-spec/protocol-overview.md#hss_ntor
[`KS_hs_blind_id`]: ./rend-spec/protocol-overview.md#hs_blind_id
[Legacy channel negotiation]: ./tor-spec/obsolete-channels.md
[Online signing keys]: ./tor-spec/relay-keys.md#online-signing
[CERTS cells]: ./tor-spec/negotiating-channels.md#CERTS-cells
[`EdCvt`]: ./dir-spec/converting-to-ed25519.md
[HsDesc (outer)]: ./rend-spec/hsdesc-outer.md#descriptor-signing-key-cert
[HsDesc (`auth-key`)]: ./rend-spec/hsdesc-encrypt.md#auth-key
[HsDesc (`enc-key-cert`)]: ./rend-spec/hsdesc-encrypt.md#enc-key-cert
[ntor cross-cert]: ./dir-spec/server-descriptor-format.md#ntor-onion-key-crosscert


<span id="note-1">Note 1:
The certificate types
[`[09] HS_IP_V_SIGNING`][HsDesc (`auth-key`)]
and
[`[0B] HS_IP_CC_SIGNING`][HsDesc (`enc-key-cert`)]
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.
</span>


<a id="cert-spec.txt-A.2"></a>

## List of extension types { #list-ext-types }

- `[04]` - [signed-with-ed25519-key](#signed-with-ed25519)

<a id="cert-spec.txt-A.3"></a>

## List of signature prefixes { #list-sig-prefixes }

We describe various documents as being signed with a prefix. Here
are those prefixes:

"Tor router descriptor signature v1" (see dir-spec.txt)

<a id="cert-spec.txt-A.4"></a>

## List of certified key types (CERT_KEY_TYPE field) { #list-key-types }

- `[01]`: ed25519 key
- `[02]`: SHA256 hash of an RSA key. (Not currently used.)
- `[03]`: SHA256 hash 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.

