mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-03-07 22:18:18 +01:00
akwizgran created page: BTP
32
BTP.markdown
32
BTP.markdown
@@ -6,7 +6,7 @@ The underlying transport is not required to provide any security properties. We
|
||||
|
||||
### Notation
|
||||
|
||||
We use || to denote concatenation, double quotes to denote a UTF-8 string, int64(x) to denote x represented as a 64-bit two's complement big-endian integer, len(x) to denote the length of x in bytes, and pack(x) as shorthand for int64(len(x)) || x.
|
||||
We use || to denote concatenation, double quotes to denote an ASCII string, int(x) to denote x represented as a 64-bit signed big-endian integer, len(x) to denote the length of x in bytes, and pack(x) as shorthand for int(len(x)) || x.
|
||||
|
||||
### Crypto primitives
|
||||
|
||||
@@ -36,18 +36,18 @@ The devices must also agree which of them will play the role of Alice and which
|
||||
|
||||
### Key derivation
|
||||
|
||||
BTP's key derivation function is based on a pseudo-random function. The key derivation function takes an input key k, a label p, and zero or more optional arguments a_1 to a_n, and returns an output key. The label describes the purpose of the output key, and the additional arguments vary according to the purpose. The label and additional arguments are unambiguously concatenated using the pack function.
|
||||
BTP's key derivation function is based on a pseudo-random function:
|
||||
|
||||
KDF(k, p, a_1, ..., a_n) = MAC(k, pack(p) || pack(a_1) || ... || pack(a_n))
|
||||
KDF(k, x_1, ..., x_n) == MAC(k, pack(x_1) || ... || pack(x_n))
|
||||
|
||||
Each device derives four initial keys from S:
|
||||
|
||||
* alice_tag = KDF(S, "ALICE_TAG_KEY")
|
||||
* alice_cipher = KDF(S, "ALICE_CIPHER_KEY")
|
||||
* bob_tag = KDF(S, "BOB_TAG_KEY")
|
||||
* bob_cipher = KDF(S, "BOB_CIPHER_KEY")
|
||||
* atk = KDF(S, "ALICE_TAG_KEY")
|
||||
* ack = KDF(S, "ALICE_CIPHER_KEY")
|
||||
* btk = KDF(S, "BOB_TAG_KEY")
|
||||
* bck = KDF(S, "BOB_CIPHER_KEY")
|
||||
|
||||
Alice sets out_tag = alice_tag, out_cipher = alice_cipher, in_tag = bob_tag, and in_cipher = bob_cipher. Bob sets out_tag = bob_tag, out_cipher = bob_cipher, in_tag = alice_tag and in_cipher = alice_cipher. Thus Alice's outgoing keys (out_tag and out_cipher) are the same as Bob's incoming keys (in_tag and in_cipher), and vice versa. Both devices then erase S.
|
||||
Alice initialises her outgoing tag and cipher keys to otk = atk and ock = ack, and her incoming tag and cipher keys to itk = btk and ick = bck. Bob initialises his outgoing tag and cipher keys to otk = btk and ock = bck, and his incoming tag and cipher keys to itk = atk and ick = ack. Thus Alice's outgoing keys are Bob's incoming keys and vice versa. Both devices then erase S.
|
||||
|
||||
### Key rotation
|
||||
|
||||
@@ -57,10 +57,10 @@ The length of each rotation period is R = D + L seconds. Rotation periods are al
|
||||
|
||||
The initial keys derived from S are the keys for period P. The keys for each subsequent period i are derived from the previous period's keys as follows:
|
||||
|
||||
* next_out_tag = KDF(out_tag, "ROTATE_OUTGOING_TAG_KEY", int64(i))
|
||||
* next_out_cipher = KDF(out_cipher, "ROTATE_OUTGOING_CIPHER_KEY", int64(i))
|
||||
* next_in_tag = KDF(in_tag, "ROTATE_INCOMING_TAG_KEY", int64(i))
|
||||
* next_in_cipher = KDF(in_cipher, "ROTATE_INCOMING_CIPHER_KEY", int64(i))
|
||||
* next_otk = KDF(otk, "ROTATE_OUTGOING_TAG_KEY", int(i))
|
||||
* next_ock = KDF(ock, "ROTATE_OUTGOING_CIPHER_KEY", int(i))
|
||||
* next_itk = KDF(itk, "ROTATE_INCOMING_TAG_KEY", int(i))
|
||||
* next_ick = KDF(ick, "ROTATE_INCOMING_CIPHER_KEY", int(i))
|
||||
|
||||
If the sender starts sending a stream at time t according to the sender's clock, the recipient may start receiving the stream at any time between t - D and t + D + L according to the recipient's clock. Therefore each device must retain the incoming keys for the previous, current and next rotation periods, along with the outgoing keys for the current rotation period. Keys are erased when they are no longer needed.
|
||||
|
||||
@@ -68,7 +68,11 @@ If the sender starts sending a stream at time t according to the sender's clock,
|
||||
|
||||
Each stream starts with a pseudo-random tag, which is tag_len bytes long. The recipient calculates the tag in advance and uses it to recognise which sender the stream comes from and which incoming cipher key should be used.
|
||||
|
||||
The tag for the i^th stream from the sender to the recipient in a given rotation period is the first tag_len bytes of MAC(k, int64(i)), where k is the sender's outgoing tag key. We require that mac_len >= tag_len.
|
||||
The tag for the i^th stream from the sender to the recipient in a given rotation period is the first tag_len bytes of MAC(k, int(i)), where k is the sender's outgoing tag key. We require that mac_len >= tag_len. Streams are counted starting from zero in each rotation period.
|
||||
|
||||
> Implementation note: The current implementation uses tag_len == 16.
|
||||
|
||||
### Reordering windows
|
||||
|
||||
BTP uses reordering windows to allow the recipient to recognise streams that are received out of order due to reordering or loss by the underlying transport. The recipient maintains reordering windows for the previous, current and next rotation periods. Each window contains *W* tags, each of which is marked as seen or unseen. When a previously unseen tag is marked as seen, the window slides according to the following rules:
|
||||
|
||||
@@ -79,7 +83,7 @@ If the window slides past a tag that has not been seen, the recipient can no lon
|
||||
|
||||
To avoid reusing tags, which would allow the adversary to distinguish BTP traffic from random, the sender must persistently store the number of streams sent to the recipient in the current rotation period. To avoid accepting replayed streams, the recipient must persistently store the reordering windows for the previous, current and next rotation periods.
|
||||
|
||||
> Implementation note: The current implementation uses tag_len == 16 and W == 32. Different values of W may be suitable for different transports.
|
||||
> Implementation note: The current implementation uses W == 32. Different values of W may be suitable for different transports.
|
||||
|
||||
### Stream header
|
||||
|
||||
|
||||
Reference in New Issue
Block a user