diff options
author | Nick Mathewson <nickm@torproject.org> | 2023-11-16 15:50:00 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2023-11-16 15:50:00 +0000 |
commit | 00109f5880328a53638dfb9e877980221712d84e (patch) | |
tree | e031e4a11eb2fa1dfe401d6819953036b1ada797 /spec | |
parent | 13bbf97025b1818b305c1e932be20adfa1ca80ec (diff) | |
parent | 354b16ca43e9af3edb9d9e75d3c39cf96c24043f (diff) | |
download | torspec-00109f5880328a53638dfb9e877980221712d84e.tar.gz torspec-00109f5880328a53638dfb9e877980221712d84e.zip |
Merge branch 'ssh' into 'main'
ssh-protocols: Document Arti keystore key types
Closes arti#1109
See merge request tpo/core/torspec!223
Diffstat (limited to 'spec')
-rw-r--r-- | spec/ssh-protocols.md | 263 |
1 files changed, 254 insertions, 9 deletions
diff --git a/spec/ssh-protocols.md b/spec/ssh-protocols.md index a54cb9c..bcc0a3a 100644 --- a/spec/ssh-protocols.md +++ b/spec/ssh-protocols.md @@ -11,10 +11,10 @@ The Tor Project uses names ending `@spec.torproject.org`. | Id(s) | Namespace | Summary | Specification<br>link (retrieved at) | |----------|--------------|----------|-------------------------------------| -| **`ed25519-expaneded@`** | [Public key algorithm](https://datatracker.ietf.org/doc/html/rfc4250#section-4.11.3) (in [OpenSSH format](https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.key?annotate=HEAD) key file) | Expanded ed25519 private key | [Arti keystore](https://gitlab.torproject.org/tpo/core/arti/-/blob/main/crates/tor-keymgr/src/key_type/ssh.rs?ref_type=heads) (2023-11-08) | -| **`x25519@`** | [Public key algorithm](https://datatracker.ietf.org/doc/html/rfc4250#section-4.11.3) (in [OpenSSH format](https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.key?annotate=HEAD) key file) | X25519 private key | [Arti keystore](https://gitlab.torproject.org/tpo/core/arti/-/blob/main/crates/tor-keymgr/src/key_type/ssh.rs?ref_type=heads) (2023-11-08) | +| **`ed25519-expaneded@`** | [Public key algorithm](https://datatracker.ietf.org/doc/html/rfc4250#section-4.11.3) (in SSH/OpenSSH key file) | Expanded ed25519 private key | [Arti keystore types] +| **`x25519@`** | [Public key algorithm](https://datatracker.ietf.org/doc/html/rfc4250#section-4.11.3) (in SSH/OpenSSH key file) | X25519 keys | [Arti keystore types] | -### Registration process +## Registration process New entries may be added to this table after peer review by the Tor Project developers, @@ -32,22 +32,267 @@ Ideally, before a protocol is deployed, its specification should be transferred to the Tor Specifications (and the link in the table adjusted). -### Interpretation +## Interpretation + +This section uses +the notation and conventions from +[`PROTOCOL.key`](https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.key?annotate=HEAD)) +and +SSH including [RFC4251 s5](https://datatracker.ietf.org/doc/html/rfc4251#section-5)), +not those from the rest of the Tor Specifications. + +### Interpreting the table For example, the row for `x25519@` indicates that: * The Tor Project has assigned `x25519@spec.torproject.org` * In the namespace of public key algorithms - see [RFC4250 table 4.11.3](https://datatracker.ietf.org/doc/html/rfc4250#section-4.11.3), - but only when found within an OpenSSH format key file, - as [defined by the OpenSSH Project](https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.key?annotate=HEAD). + but only when found within an SSH/OpenSSH format key file. * The meaning of this name is summarised as "X25519 private key" - * The full details can be found at the linked document, - which is part of the Arti keystore. - * The link was last checked on the 8th November 2023. + * The full details can be found at the linked text, + which is part of the Arti keystore section, below. The registered names resemble email addresses, but they are **not email addresses** and mail to them will not be delivered. For further information, consult the linked specifications. + +## SSH key types for the Arti keystore + +[Arti keystore types]: #ssh-key-types-for-the-arti-keystore + +The +[Arti keystore](https://tpo.pages.torproject.net/core/doc/rust/tor_keymgr/index.html) +stores private keys +in OpenSSH key format +(and, sometimes, public keys, in SSH format). +But it needs to store some key types that are +not used in the SSH protocols. +So the following key types are defined. + +These are in the namespace of Public Key Algorithms +([RFC4250 4.11.3](https://datatracker.ietf.org/doc/html/rfc4250#section-4.11.3)) +but they are only meaningful in +OpenSSH format private key files +([OpenSSH `PROTOCOL.key` document](https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.key?annotate=HEAD)) +and +SSH public key files +([RFC4716 3.4](https://datatracker.ietf.org/doc/html/rfc4716#section-3.4)). + +In each case we specify/reference + * the name of the "public key algorithm" (RFC4250 4.11.3), + * the underlying cryptographic algorithm(s), + * the public key data + ("key/certificate data" in + [RFC4253 6.6](https://datatracker.ietf.org/doc/html/rfc4253#section-6.6)), + see [Encoding of the public key data](#encoding-of-the-public-key-data) + * the private key data + (see [Encoding of the private key data](#encoding-of-the-private-key-data)) + +### Encoding of the public key data + +OpenSSH `PROTOCOL.key` does not clearly state +the contents of the `publickey1`/`publickey2`/`publickeyN` fields +in the outer (unencrypted) section (`PROTOCOL.key` s1), +so we state it here. + +Each `publickey` consists of the encoded public key +as per +[RFC4253 6.6](https://datatracker.ietf.org/doc/html/rfc4253#section-6.6) +(under "Certificates and public keys are encoded as follows"). + +So the overall format of this part of the file is: + +``` + uint32 number of keys, N + string publickey1, where the contained binary data is: + string public key algorithm name (RFC4250 table 4.11.3) + byte[] public key data (algorithm-specific) + ... keys 2 to N-1 inclusive, each as for publickey1 ... + string publickeyN (as for publickey1) +``` + +### Encoding of the private key data + +OpenSSH `PROTOCOL.key` defines +the representation of the private key data as, simply: +"using the same rules as used for SSH agent". +However, +no specific section is referred to; +the SSH agent protocol is only available as +an Internet Draft +[draft-miller-ssh-agent-04](https://datatracker.ietf.org/doc/html/draft-miller-ssh-agent-04); +and, the actual encoding used by OpenSSH is hard to relate +to that document. +So we document our understanding here. + +The contents of each `privatekey1`/`privatekey2`/`privatekeyN` is: + +``` + string public key algorithm name (RFC4250 table 4.11.3) + byte[] public key data (algorithm-specific) + byte[] private key data (algorithm-specific) +``` + +> Note that this depends on the reader knowing the public key algorithm. +> The public key data must be self-delimiting, +> since the file format doesn't provide a separate length field. +> Although here we discuss only algorithms whose +> public key data, and private key data, +> are each a single `string`, that is not always the case: +> for example, +> the `ssh-rsa` algorithm's key data formats are sequences of `mpint`s +> without any surrounding overall length. +> +> Note also that the encrypted section does not separately state +> the number of keys or their total length. +> The reader must keep reading until it encounters either the end, +> or something that looks like padding (starting with a byte 0x01). + +### `x25519@spec.torproject.org` + +These refer to keys for +X25519, +ie, Diffie-Hellman on +Curve25519, +as per +[RFC7748 6.1](https://datatracker.ietf.org/doc/html/rfc7748#section-6.1). +and +[s5](https://datatracker.ietf.org/doc/html/rfc7748#section-5). + +The public key data is: +``` + string wrapper for the following fixed-length data: + byte[32] the u-coordinate encoded as u[] from RFC7748 s5 +``` + +The private key data is: +``` + string wrapper for the following fixed-length data: + byte[32] the scalar k encoded according to RFC7748 s5 +``` + +k MUST be stored as the true scalar value. +So if the private key was generated from 32 random bytes +according to the procedure described in RFC7748 s5 +"in order to decode 32 random bytes as an integer scalar". +the value stored MUST be the "clamped" form: +that is, the value +*after* the transformation. +If a stored value is a byte string which doesn't represent +a valid scalar according to RFC7748 s5 +(i.e. an "unclamped" value) +it SHOULD be rejected; +if it is not rejected, +it MUST NOT be used unchanged, but MUST instead be clamped. + +Keys whose `string` wrapper is not of the expected length MUST be rejected. + +> <span id="useless-string">The +> `string` wrapper is useless, +> but the same wrapper approach is used in official SSH for +> ed25519 public keys ([RFC8709 +> s4](https://datatracker.ietf.org/doc/html/rfc8709#name-public-key-format)). +> and for ed25519 private keys in the SSH agent protocol +> ([draft-miller-ssh-agent-04 4.2.3](https://datatracker.ietf.org/doc/html/draft-miller-ssh-agent-04#section-4.2.3)). +> We do the same here for consistency +> (and implementation convenience).</span> + +> X25519 keys are +> [interconvertible with ed25519 keys](dir-spec/converting-to-ed25519.md). +> So, it would be possible to store the ed25519 form instead, +> and convert on load/save. +> However, we use a different key type +> to avoid needing conversions during load/save, and +> to avoid key type punning and accidental key misuse: +> using the same key material for different algorithms is a poor idea. + +### `ed25519-expanded@spec.torproject.org` + +These refer to the expanded form of private keys for +ed25519 +([RFC8032](https://datatracker.ietf.org/doc/html/rfc8032)). + +This key type appears within OpenSSH private key files. +When it does, the `ed25519-expanded@spec.torproject.org` +algorithm name is used for +the private key (`PROTOCOL.key` section 3, `privatekey1` etc.) +but also for +the public key (`PROTOCOL.key` section 1, `publickey1` etc.). + +> In `PROTOCOL.key` we interpret the requirement that there be +> "matching" public and private keys +> to include the requirement that +> the public key algorithm name strings must be the same. + +> In the Arti keystore a private key file +> whose filename ends with `.ed25519_private` +> may contain either +> a standard ed25519 keypair with SSH type `ed25519` +> or +> an `ed25519-expanded@spec.torproject.org` keypair. + +`ed25519-expanded@spec.torproject.org` +SHOULD NOT appear in RFC4716 *public* key files. +Software which is aware of this key type +MUST NOT generate such public key files +and SHOULD reject them on loading. +(Software handling keys in a type-agnostic manner +MAY, and probably will, process such files without complaint.) + +> These rules are because +> public keys should always be advertised as `ed25519` +> even if the private key is only available as `ed25519-expanded@`: +> this avoids leaking information about the key generation process +> to relying parties, +> and simplifies certification and verification. + +> Arti will provide a utility to convert +> anomalous RFC4716 public key files +> containing keys declared to be of type +> `ed25519-expanded@spec.torproject.org` +> to fully conforming files containg `ed25519` keys. +> In other circumstances Arti will reject such anomalous files. + +The public key data is the same as for the official `ed25519` type: +``` + string wrapper for the following fixed-length data: + byte[32] the actual public key, ENC(A) from RFC8032 3.2 +``` +(Reference: [RFC8032 3.2](https://datatracker.ietf.org/doc/html/rfc8032#section-3.2).) + +The private key data is as follows: +``` + string wrapper for the following fixed-length data: + byte[32] ENC(s) as per RFC8032 3.2, "expanded secret key" + byte[32] `h_b...h_(2b-1)` as per RFC8032 3.3, "separation nonce" +``` +(References: `ENC(s)` in [RFC8032 3.2](https://datatracker.ietf.org/doc/html/rfc8032#section-3.2); +`h_b || ... || h_(2b-1)` as per [RFC8032 3.3](https://datatracker.ietf.org/doc/html/rfc8032#section-3.3).) + +Keys whose `string` wrapper is not of the expected length MUST be rejected. + +> [As with `x25519`, the `string` wrapper is useless](#useless-string). +> We adopt it here for the same reasons. + +This private key format does not provide a way to convey or establish +a corresponding (unexpanded, standard) ed25519 private key `k`. + +> The ed25519 standards define the private key for ed25519 +> as a 32-byte secret `k`. +> `k` is then hashed and processed into parameters used for signing, +> and the public key for verification. +> The `ed25519-expanded@spec.torproject.org` can represent private keys +> which can be used with the ed25519 signature algorithm, +> and for which a corresponding working public key is known, +> but for which there is no known value of `k` +> (the "real ed25519" private key). +> Allowing such keys can be convenient when +> one wishes to find private keys whose public keys have particular patterns, +> for example when trying to find a `.onion` domain +> for a [Tor Hidden Service](rend-spec/). +> This format is also used where +> [blinded ed25519 keys](rend-spec/keyblinding-scheme.md) +> need to be stored. |