mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-03-08 06:28:18 +01:00
akwizgran created page: BTP
35
BTP.markdown
35
BTP.markdown
@@ -10,10 +10,10 @@ We use *||* to denote concatenation, double quotes to denote a UTF-8 string, *in
|
|||||||
|
|
||||||
BTP uses the following cryptographic primitives:
|
BTP uses the following cryptographic primitives:
|
||||||
|
|
||||||
* A pseudorandom function, *r = MAC(k, m)*, where *r* is *mac_len* bytes long
|
* A pseudo-random function, *MAC(k, m)*
|
||||||
* An authenticated cipher, *c = ENC(k, n, m)* and *m = DEC(k, n, c)*, where *n* is a nonce and *c* is *auth_len* bytes longer than *m*
|
* An authenticated cipher, *ENC(k, n, m)* and *DEC(k, n, m)*, where *n* is a nonce
|
||||||
|
|
||||||
All keys are *key_len* bytes long and all nonces are *nonce_len* bytes long. For simplicity we require that *mac_len == key_len*.
|
All keys are *key_len* bytes and all nonces are *nonce_len* bytes. The output of *MAC* is *mac_len* bytes, and the output of *ENC(k, n, m)* is *auth_len* bytes longer than *m*. For simplicity we require that *mac_len == key_len*.
|
||||||
|
|
||||||
### Initial state
|
### Initial state
|
||||||
|
|
||||||
@@ -24,13 +24,13 @@ Before two devices can communicate using BTP they must establish the following s
|
|||||||
* The maximum expected difference between the devices' clocks, *D*
|
* The maximum expected difference between the devices' clocks, *D*
|
||||||
* The maximum expected latency of the transport, *L*
|
* The maximum expected latency of the transport, *L*
|
||||||
|
|
||||||
How this state is established is outside the scope of BTP. The devices must establish a separate *S* for each transport over which they wish to communicate, and *T* must be in the past according to both devices' clocks.
|
How this state is established is outside the scope of BTP. The devices must establish a separate *S* for each transport over which they wish to communicate. *T* is measured in seconds since the Unix epoch and must be in the past according to both devices' clocks. *D* and *L* may be hard-coded.
|
||||||
|
|
||||||
The devices must also agree which of them will play the role of Alice and which will play the role of Bob. The roles are identical except for some key derivation constants.
|
The devices must also agree which of them will play the role of Alice and which will play the role of Bob. The roles are identical except for some key derivation constants.
|
||||||
|
|
||||||
### Key derivation
|
### Key derivation
|
||||||
|
|
||||||
BTP's key derivation function is based on a pseudorandom function. It is broadly similar to the counter mode KDF from NIST SP 800-108, but as it always produces *key_len* bytes of output, we can omit the counter and output length arguments.
|
BTP's key derivation function is based on a pseudo-random function. It is broadly similar to the counter mode KDF from NIST SP 800-108, but since we always require *key_len* bytes of output we can omit the counter and the output length argument.
|
||||||
|
|
||||||
The key derivation function takes an input key *k*, a label *p*, and zero or more additional 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 key derivation function takes an input key *k*, a label *p*, and zero or more additional 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.
|
||||||
|
|
||||||
@@ -43,19 +43,34 @@ Each device derives four initial keys from *S*:
|
|||||||
* *atk = KDF(S, "ALICE_TAG_KEY")*
|
* *atk = KDF(S, "ALICE_TAG_KEY")*
|
||||||
* *btk = KDF(S, "BOB_TAG_KEY")*
|
* *btk = KDF(S, "BOB_TAG_KEY")*
|
||||||
|
|
||||||
Alice sets *ock = ack*, *ick = bck*, *otk = atk*, and *itk = btk*. Bob sets *ock = bck*, *ick = ack*, *otk = btk*, and *itk = atk*. Thus Alice's outgoing keys (*ock* and *otk*) are the same as Bob's incoming keys (*ick* and *itk*) and vice versa.
|
Alice sets *ock = ack*, *ick = bck*, *otk = atk*, and *itk = btk*. Bob sets *ock = bck*, *ick = ack*, *otk = btk*, and *itk = atk*. Thus Alice's outgoing keys (*ock* and *otk*) are the same as Bob's incoming keys (*ick* and *itk*), and vice versa.
|
||||||
|
|
||||||
### Key rotation
|
### Key rotation
|
||||||
|
|
||||||
BTP achieves forward secrecy by rotating keys periodically. The key rotation function is deterministic, so devices that start from the same *S* will have matching keys in each rotation period.
|
BTP achieves forward secrecy by rotating keys periodically. The key rotation function is deterministic, so devices that start from the same *S* will have matching keys in each rotation period.
|
||||||
|
|
||||||
The length of each rotation period is *R = D + L*. Rotation periods are aligned with the Unix epoch, *E*. The timestamp *T* falls in rotation period *P = floor((T - E) / R)*, where all times are measured in seconds.
|
The length of each rotation period is *R = D + L*. Rotation periods are aligned with the Unix epoch. The timestamp *T* falls in rotation period *P = floor(T / R)*, where all times are measured in seconds.
|
||||||
|
|
||||||
If a sender starts sending a stream at time *t* according to the sender's clock, the recipient may start receiving it 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.
|
The initial keys derived from *S* are the keys for period *P - 1*. The keys for each subsequent period *i* are derived from the previous period's keys as follows:
|
||||||
|
|
||||||
The four initial keys derived from *S* are the keys for period *P - 1*. The keys for each subsequent period *i* are derived from the previous period's keys as follows:
|
|
||||||
|
|
||||||
* *next_ock = KDF(ock, "ROTATE_OUTGOING_CIPHER_KEY", int(64, i))*
|
* *next_ock = KDF(ock, "ROTATE_OUTGOING_CIPHER_KEY", int(64, i))*
|
||||||
* *next_ick = KDF(ick, "ROTATE_INCOMING_CIPHER_KEY", int(64, i))*
|
* *next_ick = KDF(ick, "ROTATE_INCOMING_CIPHER_KEY", int(64, i))*
|
||||||
* *next_otk = KDF(otk, "ROTATE_OUTGOING_TAG_KEY", int(64, i))*
|
* *next_otk = KDF(otk, "ROTATE_OUTGOING_TAG_KEY", int(64, i))*
|
||||||
* *next_itk = KDF(itk, "ROTATE_INCOMING_TAG_KEY", int(64, i))*
|
* *next_itk = KDF(itk, "ROTATE_INCOMING_TAG_KEY", int(64, i))*
|
||||||
|
|
||||||
|
If a sender starts sending a stream at time *t* according to the sender's clock, the recipient may start receiving it 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.
|
||||||
|
|
||||||
|
### Tags
|
||||||
|
|
||||||
|
Each stream starts with a pseudo-random tag. The recipient calculates the tag in advance and uses it to recognise which sender the stream comes from and which key should be used to authenticate and decrypt it.
|
||||||
|
|
||||||
|
For each sender, the recipient keeps three reordering windows: one for each of the previous, current and next rotation periods. Reordering windows allow streams to be recognised if they are received out of order due to reordering or loss by the underlying transport.
|
||||||
|
|
||||||
|
Each window contains *W* tags, each of which is marked as expected or received. When an expected tag is marked as received, the window slides according to the following rules:
|
||||||
|
|
||||||
|
1. Slide the window until all tags in the top half of the window are expected.
|
||||||
|
2. Slide the window until the lowest tag in the window is expected.
|
||||||
|
|
||||||
|
If the window slides past a tag before it is received, the tag can no longer be recognised. Larger values of *W* make it possible to tolerate more reordering and loss by the underlying transport, but require the recipient to store larger windows.
|
||||||
|
|
||||||
|
The tag for the *i'th* stream from a given sender to a given recipient in a given rotation period is equal to the first *tag_len* bytes of *MAC(k, int(64, i))*, where *k* is *otk* for the sender and *itk* for the recipient. We require that *mac_len >= tag_len*.
|
||||||
|
|||||||
Reference in New Issue
Block a user