1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
|
<pre>
BIP: 151
Title: Peer-to-Peer Communication Encryption
Author: Jonas Schnelli <dev@jonasschnelli.ch>
Status: Draft
Type: Standards Track
Created: 2016-03-23
</pre>
== Abstract ==
This BIP describes an alternative way that a peer can encrypt their communication between a selective subset of remote peers.
== Motivation ==
The Bitcoin network does not encrypt communication between peers today. This opens up security issues (eg: traffic manipulation by others) and allows for mass surveillance / analysis of bitcoin users. Mostly this is negligible because of the nature of Bitcoins trust model, however for SPV nodes this can have significant privacy impacts [1] and could reduce the censorship-resistance of a peer.
Encrypting peer traffic will make analysis and specific user targeting much more difficult than it currently is. Today it's trivial for a network provider or any other men-in-the-middle to identify a Bitcoin user and its controlled addresses/keys (and link with his Google profile, etc.). Just created and broadcasted transactions will reveal the amount and the payee to the network provider.
This BIP also describes a way that data manipulation (blocking commands by a intercepting TCP/IP node) would be identifiable by the communicating peers.
Analyzing the type of p2p communication would still be possible because of the characteristics (size, sending-interval, etc.) of the encrypted messages.
Encrypting traffic between peers is already possible with VPN, tor, stunnel, curveCP or any other encryption mechanism on a deeper OSI level, however, most mechanism are not practical for SPV or other DHCP/NAT environment and will require significant knowhow in how to setup such a secure channel.
== Specification ==
A peer that supports encryption must accept encryption requests from all peers.
A independent ECDH negotiation for both communication directions is required and therefore a bidirectional communication will use two symmetric cipher keys (one per direction).
Both peers must only send encrypted messages after a successful ECDH negotiation in ''both directions''.
Encryption initialization must happen before sending any other messages to the responding peer (<code>encinit</code> message after a <code>version</code> message must be ignored).
=== Symmetric Encryption Cipher Keys ===
The symmetric encryption cipher keys will be calculated with ECDH/HKDF by sharing the pubkeys of a ephemeral key. Once the ECDH secret is calculated on each side, the symmetric encryption cipher keys must be derived with HKDF [2] after the following specification:
1. HKDF extraction
<code>PRK = HKDF_EXTRACT(hash=SHA256, salt="bitcoinechd", ikm=ecdh_secret|cipher-type)</code>.
2. Derive Key1
<code>K_1 = HKDF_EXPAND(prk=PRK, hash=SHA256, info="BitcoinK1", L=32)</code>
3. Derive Key2
<code>K_2 = HKDF_EXPAND(prk=PRK, hash=SHA256, info="BitcoinK2", L=32)</code>
It is important to include the cipher-type into the symmetric cipher key derivation to avoid weak-cipher-attacks.
=== Session ID ===
Both sides must also calculate the 256bit session-id using <code>SID = HKDF_EXPAND(prk=PRK, hash=SHA256, info="BitcoinSessionID", L=32)</code>. The session-id can be used for linking the encryption-session to an identity check.
=== The <code>encinit</code> message type ===
To request encrypted communication, the requesting peer generates an EC ephemeral-session-keypair and sends an <code>encinit</code> message to the responding peer and waits for a <code>encack</code> message. The responding node must do the same <code>encinit</code>/<code>encack</code> interaction for the opposite communication direction.
{|class="wikitable"
! Field Size !! Description !! Data type !! Comments
|-
| 33bytes || ephemeral-pubkey || comp.-pubkey || The session pubkey from the requesting peer
|-
| 1bytes || symmetric key cipher type || int8 || symmetric key cipher type to use
|}
Possible symmetric key ciphers types
{|class="wikitable"
! Number !! symmetric key ciphers type
|-
| 0 || chacha20-poly1305@openssh.com
|}
=== ChaCha20-Poly1305 Cipher Suite ===
ChaCha20 is a stream cipher designed by Daniel Bernstein [3]. It operates by permuting 128 fixed bits, 128 or 256 bits of key,
a 64 bit nonce and a 64 bit counter into 64 bytes of output. This output is used as a keystream, with any unused bytes simply discarded.
Poly1305, also by Daniel Bernstein [4], is a one-time Carter-Wegman MAC that computes a 128 bit integrity tag given a message and a single-use
256 bit secret key.
The chacha20-poly1305@openssh.com specified and defined by openssh [5] combines these two primitives into an authenticated encryption mode. The construction used is based on that proposed for TLS by Adam Langley [6], but differs in the layout of data passed to the MAC and in the addition of encyption of the packet lengths.
<code>K_1</code> must be used to only encrypt the payload size of the encrypted message to avoid leaking information by revealing the message size.
<code>K_2</code> must be used in conjunction with poly1305 to build an AEAD.
Optimized implementations of ChaCha20-Poly1305 are very fast in general, therefore it is very likely that encrypted messages require less CPU cycles per bytes then the current unencrypted p2p message format. A quick analysis by Pieter Wuille of the current ''standard implementations'' has shown that SHA256 requires more CPU cycles per byte then ChaCha20 & Poly1304.
=== The <code>encack</code> message type ===
The responding peer accepts the encryption request by sending a <code>encack</code> message.
{|class="wikitable"
! Field Size !! Description !! Data type !! Comments
|-
| 33bytes || ephemeral-pubkey || comp.-pubkey || The session pubkey from the responding peer
|}
At this point, the shared secret key for the symmetric key cipher must be calculated by using ECDH (own privkey x remote pub key).
Private keys will never be transmitted. The shared secret can only be calculated if an attacker knows at least one private key and the remote peer's public key.
* '''The <code>encinit</code>/<code>encack</code> interaction must be done from both sides.'''
* Each communication direction uses its own secret key for the symmetric cipher.
* The second <code>encinit</code> request (from the responding peer) must use the same symmetric cipher type.
* All unencrypted messages before the second <code>encack</code> response (from the responding peer) must be ignored.
* After a successful <code>encinit</code>/<code>encack</code> interaction, the "encrypted messages structure" must be used. Non-encrypted messages from the requesting peer must lead to a connection termination.
After a successful <code>encinit</code>/<code>encack</code> interaction from both sides, the messages format must use the "encrypted messages structure". Non-encrypted messages from the requesting peer must lead to a connection termination (can be detected by the 4 byte network magic in the unencrypted message structure).
=== Encrypted Messages Structure ===
{|class="wikitable"
! Field Size !! Description !! Data type !! Comments
|-
| 4 || length || uint32_t || Length of ciphertext payload in number of bytes
|-
| ? || ciphertext payload || ? || One or many ciphertext command & message data
|-
| 16 || MAC tag || ? || 128bit MAC-tag
|}
Encrypted messages do not have the 4byte network magic.
The maximum message length needs to be chosen carefully. The 4 byte length field can lead to a required message buffer of 4 GiB.
Processing the message before the authentication succeeds must not be done.
The 4byte sha256 checksum is no longer required because the AEAD.
Both peers need to track the message sequence number (uint32) of sent messages to the remote peer for building a 64 bit symmetric cipher IV. Sequence numbers are allowed to overflow to zero after 4294967295 (2^32-1).
The encrypted payload will result decrypted in one or many unencrypted messages:
{|class="wikitable"
! Field Size !! Description !! Data type !! Comments
|-
| ? || command || varlen || ASCII string identifying the packet content, we are using varlen in the encrypted messages.
|-
| 4 || length || uint32_t || Length of plaintext payload
|-
| ? || payload || ? || The actual data
|}
If more data is present, another message must be deserialized. There is no explicit amount-of-messages integer.
=== Re-Keying ===
A responding peer can inform the requesting peer over a re-keying with a <code>encack</code> message containing 33byte of zeros to indicate that all encrypted message following after this <code>encack</code> message will be encrypted with ''the next symmetric cipher key''.
The new symmetric cipher key will be calculated by <code>SHA256(SHA256(old_symetric_cipher_key))</code>.
Re-Keying interval is a peer policy with a minimum timespan of 10 seconds.
The Re-Keying must be done after every 1GB of data sent or received (recommended by RFC4253 SSH Transport).
=== Risks ===
The encryption does not include an identity authentication scheme. This BIP does not cover a proposal to avoid MITM attacks during the encryption initialization.
Identity authentication will be covered in another BIP and will presume communication encryption after this BIP.
== Compatibility ==
This proposal is backward compatible. Non-supporting peers will ignore the <code>encinit</code> messages.
== Reference implementation ==
== References ==
* [1] http://e-collection.library.ethz.ch/eserv/eth:48205/eth-48205-01.pdf
* [2] HKDF (RFC 5869) https://tools.ietf.org/html/rfc5869
* [3] ChaCha20 http://cr.yp.to/chacha/chacha-20080128.pdf
* [4] Poly1305 http://cr.yp.to/mac/poly1305-20050329.pdf
* [5] https://github.com/openssh/openssh-portable/blob/05855bf2ce7d5cd0a6db18bc0b4214ed5ef7516d/PROTOCOL.chacha20poly1305
* [6] "ChaCha20 and Poly1305 based Cipher Suites for TLS", Adam Langley http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-03
== Acknowledgements ==
* Pieter Wuille and Gregory Maxwell for most of the ideas in this BIP.
== Copyright ==
This work is placed in the public domain.
|