Newer
Older
Bramble Handshake Protocol (BHP) is a key agreement protocol for delay-tolerant networks. It enables two peers that have previously exchanged long-term public keys to establish an ephemeral shared secret key that is not known to any other party.
BHP is designed to be used with Bramble Transport Protocol (BTP) in handshake mode, which does not provide forward secrecy. The shared key produced by BHP can be used to upgrade BTP to transport mode, which provides forward secrecy.
BHP can operate over any connection-oriented, bidirectional transport protocol.
### 1.1 Adversary Model
We assume the adversary can observe, block, delay, replay and modify traffic on all underlying transports.
We do not assume that the peers exchanged their long-term public keys over a secure channel. If the adversary intercepted the prior exchange of long-term public keys and replaced them with its own public keys then BHP does not detect or prevent man-in-the-middle attacks. If the adversary knows both peers' long-term public keys but did not replace them during the prior exchange then BHP prevents man-in-the-middle attacks.
BHP does not rely on lower protocol layers to provide confidentiality, integrity, authenticity or forward secrecy. If the traffic between peers needs to be indistinguishable from random then BHP should be used with a protocol that provides concealability, such as BTP.
### 1.2 Prerequisites
Before two peers can communicate using BHP they must exchange long-term public keys. BHP does not specify how this should be done. Any synchronous or asynchronous communication channel can be used, subject to the caveat that if an adversary can replace the keys being exchanged then the adversary can carry out a man-in-the-middle attack against BHP.
The peers must also establish a connection over a bidirectional transport. Each peer needs to know which long-term public key to use for authenticating the other peer. When BHP is used with BTP in handshake mode, BTP enables the peers to identify each other so they can look up the appropriate long-term public keys. If BHP is used without BTP then some other means must be provided to determine which long-term public key to use.
The peers take the roles of **Alice** and **Bob** according to the lexicographic order of their long-term public keys, compared as byte strings. The peer with the earlier key plays the role of Alice, while the peer with the later key plays the role of Bob. The roles are symmetrical except for the order of the protocol steps.
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
### 1.3 Notation
- || denotes concatenation
- Double quotes denote an ASCII string
- len(x) denotes the length of x in bytes
- int\_n(x) denotes x represented as an unsigned, big-endian, n-bit integer
### 1.4 Cryptographic Primitives
BHP uses three cryptographic primitives:
1. **A cryptographic hash function**, H(m)
2. **A key agreement function**, DH(pri, pub), where pri is one party's private key and pub is the other party's public key
3. **A message authentication code**, MAC(k, m), which must be a pseudo-random function
We use H(m) to define a multi-argument hash function:
- HASH(x\_1, ..., x\_n) = H(int\_32(len(x\_1)) || x\_1 || ... || int\_32(len(x\_n)) || x\_n)
We use MAC(k, m) to define a key derivation function:
- KDF(k, x\_1, ..., x\_n) = MAC(k, int\_32(len(x\_1)) || x\_1 || ... || int\_32(len(x\_n)) || x\_n)
All hashes are HASH\_LEN bytes, all symmetric keys are KEY\_LEN bytes, and the output of MAC(k, m) is MAC\_LEN bytes. For simplicity we require that HASH\_LEN = KEY\_LEN = MAC\_LEN.
(*Note:* The current version of the protocol uses BLAKE2b as the hash function and keyed BLAKE2b as the message authentication code, both with an output length of 32 bytes. This gives HASH\_LEN = KEY\_LEN = MAC\_LEN = 32. The key agreement function is X25519.)
## 2 The Handshake Protocol
### 2.1 Records
The peers exchange a series of **records** over the transport connection. Each record has the following format:
- record\_header = int\_8(protocol\_version) || int\_8(record\_type) || int\_16(len(payload))
- record = record\_header || payload
The maximum length of the payload is 48 KiB.
The current version of the protocol is 0.1, which has three record types:
**0: EPHEMERAL\_PUBLIC\_KEY** - The payload consists of the sender's ephemeral public key.
**1: PROOF\_OF\_OWNERSHIP** - The payload consists of a message authentication code proving ownership of the sender's long-term and ephemeral public keys and binding them to the recipient's long-term and ephemeral public keys.
**2: MINOR\_VERSION** - The payload consists of a single byte giving the sender's protocol minor version, which must be non-zero.
A peer should reject any record with an unsupported protocol version and ignore any record with a supported protocol version but an unrecognised record type. This allows new record types to be added without breaking compatibility.
A peer must abort the protocol when no minor version is received from its remote peer, since the initial version 0 of BHP is vulnerable to attacks on forward secrecy.
### 2.2 Protocol Steps
The protocol has four steps:
1. Alice generates an ephemeral key pair and sends an EPHEMERAL\_PUBLIC\_KEY record
2. Bob generates an ephemeral key pair and sends an EPHEMERAL\_PUBLIC\_KEY record
3. Alice derives the shared secret and sends a PROOF\_OF\_OWNERSHIP record
4. Bob derives the shared secret and sends a PROOF\_OF\_OWNERSHIP record
### 2.3 Key Derivation
Alice calculates three "raw" shared secrets as follows:
- raw\_ephemeral = DH(pri\_ephemeral\_a, pub\_ephemeral\_b)
- raw\_static\_ephemeral = DH(pri\_long\_term\_a, pub\_ephemeral\_b)
- raw\_ephemeral\_static = DH(pri\_ephemeral\_a, pub\_long\_term\_b)
Bob calculates three "raw" shared secrets as follows:
- raw\_ephemeral = DH(pri\_ephemeral\_b, pub\_ephemeral\_a)
- raw\_static\_ephemeral = DH(pri\_ephemeral\_b, pub\_long\_term\_a)
- raw\_ephemeral\_static = DH(pri\_long\_term\_b, pub\_ephemeral\_a)
(*Note:* If a peer calculates an X25519 raw shared secret that is all zeroes, the peer must abort the protocol.)
If the adversary did not intercept the prior exchange of long-term public keys and has not modified the EPHEMERAL\_PUBLIC\_KEY records then both peers will calculate the same shared secrets. The peers then derive a "cooked" shared secret known as the **ephemeral master key**, which incorporates both peers' long-term and ephemeral public keys:
- ephemeral\_master\_key = HASH("org.briarproject.bramble.handshake/MASTER\_KEY", raw\_ephemeral, raw\_static\_ephemeral, raw\_ephemeral\_static, pub\_long\_term\_a, pub\_long\_term\_b, pub\_ephemeral\_a, pub\_ephemeral\_b)
The peers must then delete their ephemeral private keys and the raw shared secrets, allowing the calling application to use the master key for forward secret communication if required.
The master key depends on both peers' long-term and ephemeral public keys, as well as on shared secrets that can only be derived by the owners of those keys. Each peer sends proof that it has derived the correct master key, which in turn proves that it owns the long-term and ephemeral public keys received by the other peer, and has received the long-term and ephemeral public keys sent by the other peer.
Each peer calculates its own proof and the proof it expects to receive from the other peer. If the proof received from the other peer differs from the expected proof then the peer must abort the protocol.
- alice\_proof = KDF(ephemeral\_master\_key, "org.briarproject.bramble.handshake/ALICE\_PROOF")
- bob\_proof = KDF(ephemeral\_master\_key, "org.briarproject.bramble.handshake/BOB\_PROOF")
If the proof received from the other peer matches the expected proof, BHP returns the master key to the calling application, together with the open transport connection and a flag indicating whether the peer played the role of Alice or Bob. The application may use the master key and flag to derive keys for communicating securely over the transport connection, or for any other purpose.
As noted above, if an adversary intercepted the prior exchange of long-term public keys and replaced them with its own public keys then BHP does not prevent man-in-the-middle attacks. The adversary can intercept the BHP connection, replace the peers' ephemeral public keys with its own public keys, and produce a proof of ownership of its own long-term and ephemeral public keys that will satisfy each peer. Each peer will derive a master key that is known to the adversary rather than the other peer, giving the adversary access to any future communication between the peers that is secured with keys derived from the master key.
However, if the adversary did *not* intercept the prior exchange of long-term public keys then BHP prevents man-in-the-middle attacks. If the adversary intercepts the BHP connection and replaces the peers' ephemeral public keys with its own keys, the adversary will not be able to produce a proof of ownership that will satisfy either peer.