mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-24 20:33:31 +01:00
Adjust spec to parameterize cell and key lengths. This should please Ian.
svn:r5922
This commit is contained in:
parent
cc349042f6
commit
7dbea118ce
159
doc/tor-spec.txt
159
doc/tor-spec.txt
@ -17,7 +17,9 @@ TODO: (very soon)
|
|||||||
- Copy prose from tor-design to make everything more readable.
|
- Copy prose from tor-design to make everything more readable.
|
||||||
when do we rotate which keys (tls, link, etc)?
|
when do we rotate which keys (tls, link, etc)?
|
||||||
|
|
||||||
0. Notation:
|
0. Preliminaries
|
||||||
|
|
||||||
|
0.1. Notation and encoding
|
||||||
|
|
||||||
PK -- a public key.
|
PK -- a public key.
|
||||||
SK -- a private key
|
SK -- a private key
|
||||||
@ -30,27 +32,79 @@ when do we rotate which keys (tls, link, etc)?
|
|||||||
|
|
||||||
All numeric values are encoded in network (big-endian) order.
|
All numeric values are encoded in network (big-endian) order.
|
||||||
|
|
||||||
Unless otherwise specified, all symmetric ciphers are AES in counter
|
H(m) -- a cryptographic hash of m.
|
||||||
mode, with an IV of all 0 bytes. Asymmetric ciphers are either RSA
|
|
||||||
with 1024-bit keys and exponents of 65537, or DH where the generator (g)
|
0.2. Security parameters
|
||||||
is 2 and the modulus (p) is the 1024-bit safe prime from rfc2409,
|
|
||||||
section 6.2, whose hex representation is:
|
Tor uses a stream cipher, a public-key cipher, the Diffie-Hellman
|
||||||
|
protocol, and and a hash function.
|
||||||
|
|
||||||
|
KEY_LEN -- the length of the stream cipher's key, in bytes.
|
||||||
|
|
||||||
|
PK_ENC_LEN -- the length of a public-key encrypted message, in bytes.
|
||||||
|
PK_PAD_LEN -- the number of bytes added in padding for public-key
|
||||||
|
encryption, in bytes. (The largest number of bytes that can be encrypted
|
||||||
|
in a single public-key operation is therefore PK_ENC_LEN-PK_PAD_LEN.)
|
||||||
|
|
||||||
|
DH_LEN -- the number of bytes used to represent a member of the
|
||||||
|
Diffie-Hellman group.
|
||||||
|
DH_SEC_LEN -- the number of bytes used in a Diffie-Hellman private key (x).
|
||||||
|
|
||||||
|
HASH_LEN -- the length of the hash function's output, in bytes.
|
||||||
|
|
||||||
|
CELL_LEN -- The length of a Tor cell, in bytes.
|
||||||
|
|
||||||
|
0.3. Ciphers
|
||||||
|
|
||||||
|
For a stream cipher, we use 128-bit AES in counter mode, with an IV of all
|
||||||
|
0 bytes.
|
||||||
|
|
||||||
|
For a public-key cipher, we use RSA with 1024-bit keys and a fixed
|
||||||
|
exponent of 65537. We use OAEP padding, with SHA1 as its digest
|
||||||
|
function. (For OAEP padding, see
|
||||||
|
ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf)
|
||||||
|
|
||||||
|
For Diffie-Hellman, we use a generator (g) of 2. For the modulus (p), the
|
||||||
|
1024-bit safe prime from rfc2409, (section 6.2) whose hex representation
|
||||||
|
is:
|
||||||
|
|
||||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
|
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
|
||||||
"8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
|
"8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
|
||||||
"302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
|
"302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
|
||||||
"A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
|
"A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
|
||||||
"49286651ECE65381FFFFFFFFFFFFFFFF"
|
"49286651ECE65381FFFFFFFFFFFFFFFF"
|
||||||
|
|
||||||
As an optimization, implementations SHOULD choose DH private keys (x) of
|
As an optimization, implementations SHOULD choose DH private keys (x) of
|
||||||
320 bits. Implementations that do this MUST never use any DH key more
|
320 bits. Implementations that do this MUST never use any DH key more
|
||||||
than once.
|
than once.
|
||||||
|
|
||||||
All "hashes" are 20-byte SHA1 cryptographic digests.
|
For a hash function, we use SHA1.
|
||||||
|
|
||||||
|
KEY_LEN=16.
|
||||||
|
DH_LEN=128; DH_GROUP_LEN=40.
|
||||||
|
PK_ENC_LEN=128; PK_PAD_LEN=42.
|
||||||
|
HASH_LEN=20.
|
||||||
|
|
||||||
When we refer to "the hash of a public key", we mean the SHA1 hash of the
|
When we refer to "the hash of a public key", we mean the SHA1 hash of the
|
||||||
DER encoding of an ASN.1 RSA public key (as specified in PKCS.1).
|
DER encoding of an ASN.1 RSA public key (as specified in PKCS.1).
|
||||||
|
|
||||||
|
All "random" values should be generated with a cryptographically strong
|
||||||
|
random number generator, unless otherwise noted.
|
||||||
|
|
||||||
|
The "hybrid encryption" of a byte sequence M with a public key PK is
|
||||||
|
computed as follows:
|
||||||
|
1. If M is less than PK_ENC_LEN-PK_PAD_LEN, pad and encrypt M with PK.
|
||||||
|
2. Otherwise, generate a KEY_LEN byte random key K.
|
||||||
|
Let M1 = the first PK_ENC_LEN-PK_PAD_LEN-KEY_LEN bytes of M,
|
||||||
|
and let M2 = the rest of M.
|
||||||
|
Pad and encrypt K|M1 with PK. Encrypt M2 with our stream cipher,
|
||||||
|
using the key K. Concatenate these encrypted values.
|
||||||
|
(Note that this "hybrid encryption" approach does not prevent an attacker
|
||||||
|
from adding or removing bytes to the end of M.)
|
||||||
|
|
||||||
|
0.4. Other parameter values
|
||||||
|
|
||||||
|
CELL_LEN=512
|
||||||
|
|
||||||
1. System overview
|
1. System overview
|
||||||
|
|
||||||
Onion Routing is a distributed overlay network designed to anonymize
|
Onion Routing is a distributed overlay network designed to anonymize
|
||||||
@ -74,7 +128,7 @@ when do we rotate which keys (tls, link, etc)?
|
|||||||
support "TLS_DHE_RSA_WITH_AES_128_CBC_SHA" if it is available.
|
support "TLS_DHE_RSA_WITH_AES_128_CBC_SHA" if it is available.
|
||||||
Implementations MAY support other ciphersuites, but MUST NOT
|
Implementations MAY support other ciphersuites, but MUST NOT
|
||||||
support any suite without ephemeral keys, symmetric keys of at
|
support any suite without ephemeral keys, symmetric keys of at
|
||||||
least 128 bits, and digests of at least 160 bits.
|
least KEY_LEN bits, and digests of at least HASH_LEN bits.
|
||||||
|
|
||||||
An OP or OR always sends a two-certificate chain, consisting of a
|
An OP or OR always sends a two-certificate chain, consisting of a
|
||||||
certificate using a short-term connection key and a second, self-
|
certificate using a short-term connection key and a second, self-
|
||||||
@ -95,7 +149,7 @@ when do we rotate which keys (tls, link, etc)?
|
|||||||
|
|
||||||
Once a TLS connection is established, the two sides send cells
|
Once a TLS connection is established, the two sides send cells
|
||||||
(specified below) to one another. Cells are sent serially. All
|
(specified below) to one another. Cells are sent serially. All
|
||||||
cells are 512 bytes long. Cells may be sent embedded in TLS
|
cells are CELL_LEN bytes long. Cells may be sent embedded in TLS
|
||||||
records of any size or divided across TLS records, but the framing
|
records of any size or divided across TLS records, but the framing
|
||||||
of TLS records MUST NOT leak information about the type or contents
|
of TLS records MUST NOT leak information about the type or contents
|
||||||
of the cells.
|
of the cells.
|
||||||
@ -116,8 +170,8 @@ when do we rotate which keys (tls, link, etc)?
|
|||||||
|
|
||||||
CircID [2 bytes]
|
CircID [2 bytes]
|
||||||
Command [1 byte]
|
Command [1 byte]
|
||||||
Payload (padded with 0 bytes) [509 bytes]
|
Payload (padded with 0 bytes) [CELL_LEN-3 bytes]
|
||||||
[Total size: 512 bytes]
|
[Total size: CELL_LEN bytes]
|
||||||
|
|
||||||
The CircID field determines which circuit, if any, the cell is
|
The CircID field determines which circuit, if any, the cell is
|
||||||
associated with.
|
associated with.
|
||||||
@ -168,41 +222,33 @@ when do we rotate which keys (tls, link, etc)?
|
|||||||
|
|
||||||
The payload for a CREATE cell is an 'onion skin', which consists
|
The payload for a CREATE cell is an 'onion skin', which consists
|
||||||
of the first step of the DH handshake data (also known as g^x).
|
of the first step of the DH handshake data (also known as g^x).
|
||||||
|
This value is hybrid-encrypted (see 0.3) to Bob's public key, giving
|
||||||
The data is encrypted to Bob's PK as follows: Suppose Bob's PK
|
an onion-skin of:
|
||||||
modulus is L octets long. If the data to be encrypted is shorter
|
PK-encrypted:
|
||||||
than L-42, then it is encrypted directly (with OAEP padding: see
|
Padding padding [PK_PAD_LEN bytes]
|
||||||
ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf). If the
|
Symmetric key [KEY_LEN bytes]
|
||||||
data is at least as long as L-42, then a randomly generated 16-byte
|
First part of g^x [PK_ENC_LEN-PK_PAD_LEN-KEY_LEN bytes]
|
||||||
symmetric key is prepended to the data, after which the first L-16-42
|
|
||||||
bytes of the data are encrypted with Bob's PK; and the rest of the
|
|
||||||
data is encrypted with the symmetric key.
|
|
||||||
|
|
||||||
So in this case, the onion skin can be thought of as:
|
|
||||||
RSA-encrypted:
|
|
||||||
OAEP padding [42 bytes]
|
|
||||||
Symmetric key [16 bytes]
|
|
||||||
First part of g^x [70 bytes]
|
|
||||||
Symmetrically encrypted:
|
Symmetrically encrypted:
|
||||||
Second part of g^x [58 bytes]
|
Second part of g^x [DH_LEN-(PK_ENC_LEN-PK_PAD_LEN-KEY_LEN)
|
||||||
|
bytes]
|
||||||
|
|
||||||
The relay payload for an EXTEND relay cell consists of:
|
The relay payload for an EXTEND relay cell consists of:
|
||||||
Address [4 bytes]
|
Address [4 bytes]
|
||||||
Port [2 bytes]
|
Port [2 bytes]
|
||||||
Onion skin [186 bytes]
|
Onion skin [DH_LEN+KEY_LEN+PK_PAD_LEN bytes]
|
||||||
Identity fingerprint [20 bytes]
|
Identity fingerprint [HASH_LEN bytes]
|
||||||
|
|
||||||
The port and address field denote the IPV4 address and port of the next
|
The port and address field denote the IPV4 address and port of the next
|
||||||
onion router in the circuit; the public key hash is the SHA1 hash of the
|
onion router in the circuit; the public key hash is the hash of the PKCS#1
|
||||||
PKCS#1 ASN1 encoding of the next onion router's identity (signing) key.
|
ASN1 encoding of the next onion router's identity (signing) key. (See 0.3
|
||||||
(Including this hash allows the extending OR verify that it is indeed
|
above.) (Including this hash allows the extending OR verify that it is
|
||||||
connected to the correct target OR, and prevents certain man-in-the-middle
|
indeed connected to the correct target OR, and prevents certain
|
||||||
attacks.)
|
man-in-the-middle attacks.)
|
||||||
|
|
||||||
The payload for a CREATED cell, or the relay payload for an
|
The payload for a CREATED cell, or the relay payload for an
|
||||||
EXTENDED cell, contains:
|
EXTENDED cell, contains:
|
||||||
DH data (g^y) [128 bytes]
|
DH data (g^y) [DH_LEN bytes]
|
||||||
Derivative key data (KH) [20 bytes] <see 4.2 below>
|
Derivative key data (KH) [HASH_LEN bytes] <see 4.2 below>
|
||||||
|
|
||||||
The CircID for a CREATE cell is an arbitrarily chosen 2-byte integer,
|
The CircID for a CREATE cell is an arbitrarily chosen 2-byte integer,
|
||||||
selected by the node (OP or OR) that sends the CREATE cell. To prevent
|
selected by the node (OP or OR) that sends the CREATE cell. To prevent
|
||||||
@ -232,12 +278,12 @@ when do we rotate which keys (tls, link, etc)?
|
|||||||
|
|
||||||
A CREATE_FAST cell contains:
|
A CREATE_FAST cell contains:
|
||||||
|
|
||||||
Key material (X) [20 bytes]
|
Key material (X) [HASH_LEN bytes]
|
||||||
|
|
||||||
A CREATED_FAST cell contains:
|
A CREATED_FAST cell contains:
|
||||||
|
|
||||||
Key material (Y) [20 bytes]
|
Key material (Y) [HASH_LEN bytes]
|
||||||
Derivative key data [20 bytes] (See 4.2 below)
|
Derivative key data [HASH_LEN bytes] (See 4.2 below)
|
||||||
|
|
||||||
The values of X and Y must be generated randomly.
|
The values of X and Y must be generated randomly.
|
||||||
|
|
||||||
@ -251,7 +297,7 @@ when do we rotate which keys (tls, link, etc)?
|
|||||||
and server MUST verify that the received g^x or g^y value is not degenerate;
|
and server MUST verify that the received g^x or g^y value is not degenerate;
|
||||||
that is, it must be strictly greater than 1 and strictly less than p-1
|
that is, it must be strictly greater than 1 and strictly less than p-1
|
||||||
where p is the DH modulus. Implementations MUST NOT complete a handshake
|
where p is the DH modulus. Implementations MUST NOT complete a handshake
|
||||||
with degenerate keys. Implementions MAY discard other "weak" g^x values.
|
with degenerate keys. Implementations MAY discard other "weak" g^x values.
|
||||||
|
|
||||||
(Discarding degenerate keys is critical for security; if bad keys are not
|
(Discarding degenerate keys is critical for security; if bad keys are not
|
||||||
discarded, an attacker can substitute the server's CREATED cell's g^y with
|
discarded, an attacker can substitute the server's CREATED cell's g^y with
|
||||||
@ -268,12 +314,15 @@ when do we rotate which keys (tls, link, etc)?
|
|||||||
If CREATE_FAST is used, the client and server base their key material on
|
If CREATE_FAST is used, the client and server base their key material on
|
||||||
K0=X|Y.
|
K0=X|Y.
|
||||||
|
|
||||||
From the base key material K0, they compute 100 bytes of derivative
|
From the base key material K0, they compute KEY_LEN*2+HASH_LEN*3 bytes of
|
||||||
key data as K = SHA1(K0 | [00]) | SHA1(K0 | [01]) | ... SHA1(K0 |
|
derivative key data as
|
||||||
[04]) where "00" is a single octet whose value is zero, [01] is a
|
K = H(K0 | [00]) | H(K0 | [01]) | H(K0 | [02]) | ...
|
||||||
single octet whose value is one, etc. The first 20 bytes of K form
|
|
||||||
KH, bytes 21-40 form the forward digest Df, 41-60 form the backward
|
|
||||||
digest Db, 61-76 form Kf, and 77-92 form Kb.
|
The first HASH_LEN bytes of K form KH; the next HASH_LEN form the forward
|
||||||
|
digest Df; the next HASH_LEN 41-60 form the backward digest Db; the next
|
||||||
|
KEY_LEN 61-76 form Kf, and the final KEY_LEN form Kb. Excess bytes from K
|
||||||
|
are discarded.
|
||||||
|
|
||||||
KH is used in the handshake response to demonstrate knowledge of the
|
KH is used in the handshake response to demonstrate knowledge of the
|
||||||
computed shared key. Df is used to seed the integrity-checking hash
|
computed shared key. Df is used to seed the integrity-checking hash
|
||||||
@ -399,7 +448,7 @@ when do we rotate which keys (tls, link, etc)?
|
|||||||
|
|
||||||
Otherwise, if the OR is not at the OP edge of the circuit (that is,
|
Otherwise, if the OR is not at the OP edge of the circuit (that is,
|
||||||
either an 'exit node' or a non-edge node), it de/encrypts the payload
|
either an 'exit node' or a non-edge node), it de/encrypts the payload
|
||||||
with AES/CTR, as follows:
|
with the stream cipher, as follows:
|
||||||
'Forward' relay cell (same direction as CREATE):
|
'Forward' relay cell (same direction as CREATE):
|
||||||
Use Kf as key; decrypt.
|
Use Kf as key; decrypt.
|
||||||
'Back' relay cell (opposite direction from CREATE):
|
'Back' relay cell (opposite direction from CREATE):
|
||||||
@ -415,7 +464,7 @@ when do we rotate which keys (tls, link, etc)?
|
|||||||
sends a DESTROY cell to tear down the circuit.
|
sends a DESTROY cell to tear down the circuit.
|
||||||
|
|
||||||
When a relay cell arrives at an OP, the OP decrypts the payload
|
When a relay cell arrives at an OP, the OP decrypts the payload
|
||||||
with AES/CTR as follows:
|
with the stream cipher as follows:
|
||||||
OP receives data cell:
|
OP receives data cell:
|
||||||
For I=N...1,
|
For I=N...1,
|
||||||
Decrypt with Kb_I. If the payload is recognized (see
|
Decrypt with Kb_I. If the payload is recognized (see
|
||||||
@ -438,7 +487,7 @@ when do we rotate which keys (tls, link, etc)?
|
|||||||
StreamID [2 bytes]
|
StreamID [2 bytes]
|
||||||
Digest [4 bytes]
|
Digest [4 bytes]
|
||||||
Length [2 bytes]
|
Length [2 bytes]
|
||||||
Data [498 bytes]
|
Data [CELL_LEN-14 bytes]
|
||||||
|
|
||||||
The relay commands are:
|
The relay commands are:
|
||||||
1 -- RELAY_BEGIN [forward]
|
1 -- RELAY_BEGIN [forward]
|
||||||
@ -461,7 +510,7 @@ when do we rotate which keys (tls, link, etc)?
|
|||||||
|
|
||||||
The 'recognized' field in any unencrypted relay payload is always set
|
The 'recognized' field in any unencrypted relay payload is always set
|
||||||
to zero; the 'digest' field is computed as the first four bytes of
|
to zero; the 'digest' field is computed as the first four bytes of
|
||||||
the running SHA-1 digest of all the bytes that have been destined for
|
the running digest of all the bytes that have been destined for
|
||||||
this hop of the circuit or originated from this hop of the circuit,
|
this hop of the circuit or originated from this hop of the circuit,
|
||||||
seeded from Df or Db respectively (obtained in section 4.2 above),
|
seeded from Df or Db respectively (obtained in section 4.2 above),
|
||||||
and including this RELAY cell's entire payload (taken with the digest
|
and including this RELAY cell's entire payload (taken with the digest
|
||||||
@ -763,7 +812,7 @@ The items' formats are as follows:
|
|||||||
|
|
||||||
"fingerprint"
|
"fingerprint"
|
||||||
|
|
||||||
A fingerprint (20 byte SHA1 hash of asn1 encoded public key, encoded
|
A fingerprint (a HASH_LEN-byte of asn1 encoded public key, encoded
|
||||||
in hex, with a single space after every 4 characters) for this router's
|
in hex, with a single space after every 4 characters) for this router's
|
||||||
identity key.
|
identity key.
|
||||||
|
|
||||||
@ -801,7 +850,7 @@ The items' formats are as follows:
|
|||||||
|
|
||||||
"router-signature" NL Signature NL
|
"router-signature" NL Signature NL
|
||||||
|
|
||||||
The "SIGNATURE" object contains a signature of the PKCS1-padded SHA1
|
The "SIGNATURE" object contains a signature of the PKCS1-padded
|
||||||
hash of the entire router descriptor, taken from the beginning of the
|
hash of the entire router descriptor, taken from the beginning of the
|
||||||
"router" line, through the newline after the "router-signature" line.
|
"router" line, through the newline after the "router-signature" line.
|
||||||
The router descriptor is invalid unless the signature is performed
|
The router descriptor is invalid unless the signature is performed
|
||||||
@ -909,7 +958,7 @@ descriptors, and a single "directory-signature" item.
|
|||||||
|
|
||||||
"directory-signature" nickname-of-dirserver NL Signature
|
"directory-signature" nickname-of-dirserver NL Signature
|
||||||
|
|
||||||
The signature is computed by computing the SHA-1 hash of the
|
The signature is computed by computing the digest of the
|
||||||
directory, from the characters "signed-directory", through the newline
|
directory, from the characters "signed-directory", through the newline
|
||||||
after "directory-signature". This digest is then padded with PKCS.1,
|
after "directory-signature". This digest is then padded with PKCS.1,
|
||||||
and signed with the directory server's signing key.
|
and signed with the directory server's signing key.
|
||||||
@ -981,6 +1030,8 @@ B.1. ... but which will require backward-incompatible change
|
|||||||
- Circuit IDs should be longer.
|
- Circuit IDs should be longer.
|
||||||
- IPv6 everywhere.
|
- IPv6 everywhere.
|
||||||
- Maybe, keys should be longer.
|
- Maybe, keys should be longer.
|
||||||
|
- Maybe, key-length should be adjustable. How to do this without
|
||||||
|
making anonymity suck?
|
||||||
- Drop backward compatibility.
|
- Drop backward compatibility.
|
||||||
- We should use a 128-bit subgroup of our DH prime.
|
- We should use a 128-bit subgroup of our DH prime.
|
||||||
- Handshake should use HMAC.
|
- Handshake should use HMAC.
|
||||||
|
Loading…
Reference in New Issue
Block a user