p2p authentication and encryption BIPs

p2p authentication and encryption BIPs
2016-03-23 16:44 ` Tier Nolan
                   ` (6 more replies)
  
From: Jonas Schnelli @ 2016-03-23 15:24 UTC (permalink / raw)
  To: Bitcoin development mailing list


[-- Attachment #1.1: Type: text/plain, Size: 1045 bytes --]

Hi

I have just PRed a draft version of two BIPs I recently wrote.
https://github.com/bitcoin/bips/pull/362

Two BIPs that addresses the problem of decoupling wallets/clients from
nodes while assuming a user (or a group) know the remote peer.

Authentication would be necessary to selective allow bloom filtering of
transactions, encryption or any other node service that might lead to
fingerprinting or resource attacks. Authentication would also be a
pre-requirement for certificate free encryption-handshakes that is
(enough?) resistant to MITM attacks.

Encryption is highly recommended if you connect a SPV node to a trusted
node.

Authentication would allow accessing private p2p extensions from a
remote SPV peer (example: fee estimation).

I'm aware of other methods to increase privacy and integrity (tor, VPN,
stunnel, etc.), however I think authentication and a basic communication
encryption should be part of the protocol and its setup should be
complete hassle-free.

Thanks for your feeback.

/jonas


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

 permalink raw reply	[|nested]
2016-03-23 16:44 ` 
                   ` 
  
From: Jonas Schnelli @ 2016-03-23 15:24 UTC (permalink / raw)
  To: Bitcoin development mailing list


[-- Attachment #1.1: Type: text/plain, Size: 1045 bytes --]

Hi

I have just PRed a draft version of two BIPs I recently wrote.
https://github.com/bitcoin/bips/pull/362

Two BIPs that addresses the problem of decoupling wallets/clients from
nodes while assuming a user (or a group) know the remote peer.

Authentication would be necessary to selective allow bloom filtering of
transactions, encryption or any other node service that might lead to
fingerprinting or resource attacks. Authentication would also be a
pre-requirement for certificate free encryption-handshakes that is
(enough?) resistant to MITM attacks.

Encryption is highly recommended if you connect a SPV node to a trusted
node.

Authentication would allow accessing private p2p extensions from a
remote SPV peer (example: fee estimation).

I'm aware of other methods to increase privacy and integrity (tor, VPN,
stunnel, etc.), however I think authentication and a basic communication
encryption should be part of the protocol and its setup should be
complete hassle-free.

Thanks for your feeback.

/jonas


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

 permalink raw reply	[|nested]
* 
  2016-03-23 15:24 [bitcoin-dev] p2p authentication and encryption BIPs Jonas Schnelli

  2016-03-23 20:36 ` 
                   ` 
  6 siblings, 0 replies; 23+ messages in thread
From: Tier Nolan @ 2016-03-23 16:44 UTC (permalink / raw)
  Cc: Bitcoin development mailing list

[-- Attachment #1: Type: text/plain, Size: 932 bytes --]

There is probably not much loss due to per message encryption.  Even if a
MITM determined that a message was an inv message (or bloom filter
message), it wouldn't be able to extract much information.  Since the
hashes in those messages are fixed size, there is very little leakage.

You could make it so that the the encryption messages effectively create a
second data stream and break/weaken the link between message size and
wrapped message size.  This requires state though, so there is a complexity
tradeoff.

There is no real need to include an IV, since you are including a 32 byte
context hash.  The first 16 bytes of the context hash could be used as IV.

In terms of generating the context hash, it would be easier to make it
linear.

context_hash_n = SHA256(context_hash_(n-1) | message_(n-1))

As the session gets longer, both nodes would have to do more and more
hashing to compute the hash of the entire conversation.

[-- Attachment #2: Type: text/html, Size: 1141 bytes --]

^ permalink raw reply	[|nested] 23+ messages in thread
* 
  2016-03-23 15:24 [bitcoin-dev] p2p authentication and encryption BIPs Jonas Schnelli
  2016-03-23 16:44 ` Tier Nolan

  2016-03-23 21:40   ` 
                     ` 
  2016-03-24  2:16 ` Luke Dashjr
                   ` (4 subsequent siblings)
  6 siblings, 3 replies; 23+ messages in thread
From: Tom @ 2016-03-23 20:36 UTC (permalink / raw)
  To: bitcoin-dev

On Wednesday 23 Mar 2016 16:24:12 Jonas Schnelli via bitcoin-dev wrote:
> Hi
> 
> I have just PRed a draft version of two BIPs I recently wrote.
> https://github.com/bitcoin/bips/pull/362

I suggest running a spellchecker ;)

Some questions;

* why would you not allow encryption on non-pre-approved connections?
* we just removed (ssl) encryption from the JSON interface, how do you suggest 
this encryption to be implemented without openSSL?
* What is the reason for using the p2p code to connect a wallet to a node?
I suggest using one of the other connection methods to connect to the node. 
This avoids a change in the bitcoin protocol for a very specific usecase.
* Why do you want to do a per-message encryption (wrapping the original)? 
Smaller messages that contain predictable content and are able to be matched 
to the unencrypted versions on the wire send to other nodes will open this 
scheme up to various old statistical attacks.

> Responding peers must ignore (banning would lead to fingerprinting) the 
requesting peer after 5 unsuccessfully authentication tries to avoid resource 
attacks.

Any implementation of that kind would itself again be open to resource 
attacks.
Why 5? Do you want to allow a node to make a typo?


> To ensure that no message was dropped or blocked, the complete communication 
must be hashed (sha256). Both peers keep the SHA256 context of the encryption 
session. The complete <code>enc</code> message (leaving out the hash itself) 
must be added to the hash-context by both parties. Before sending a 
<code>enc</code> command, the sha256 context will be copied and finalized.

You write "the complete communication must be hashed" and every message has a 
hash of the state until it is at that point.
I think you need to explain how that works specifically.




^ permalink raw reply	[|nested] 23+ messages in thread
2016-03-23 20:36 ` Tom
  2016-03-23 21:40   ` Eric Voskuil

  2016-03-25 10:36     ` Tom
  2016-03-24  0:37   ` Sergio Demian Lerner
  
From: Jonas Schnelli @ 2016-03-23 21:55 UTC (permalink / raw)
  To: bitcoin-dev


[-- Attachment #1.1: Type: text/plain, Size: 3363 bytes --]


>> I have just PRed a draft version of two BIPs I recently wrote.
>> https://github.com/bitcoin/bips/pull/362
> 
> I suggest running a spellchecker ;)

Thanks. Will do.


> * why would you not allow encryption on non-pre-approved connections?

The encryption should be optional.
The proposed authentication scheme does take care of the
identity-management and therefor prevent MITM attacks.
Without the identity management, you might not detect sending/receiving
encrypted data from/to a MITM.

> * we just removed (ssl) encryption from the JSON interface, how do you suggest 
> this encryption to be implemented without openSSL?

The proposed encryption schema is based on ECDSA/ECDH (implemented in
libsecp256k1) and AES256CBC (implementation is on the way see
https://github.com/bitcoin/bitcoin/pull/7689).
OpenSSL is not required.

> * What is the reason for using the p2p code to connect a wallet to a node?
> I suggest using one of the other connection methods to connect to the node. 
> This avoids a change in the bitcoin protocol for a very specific usecase.

Most known use-case: SPV.

> * Why do you want to do a per-message encryption (wrapping the original)? 
> Smaller messages that contain predictable content and are able to be matched 
> to the unencrypted versions on the wire send to other nodes will open this 
> scheme up to various old statistical attacks.

It's probably extremely inefficient to create a constant time stream.
Even most SSL/SSH application leak information because of the
communication message characteristics.

The current wrapping message proposal is not very efficient.
I will change it so that the p2p message header will contain the
encryption metadata. This should lead to a tiny overhead.


> 
>> Responding peers must ignore (banning would lead to fingerprinting) the 
> requesting peer after 5 unsuccessfully authentication tries to avoid resource 
> attacks.
> 
> Any implementation of that kind would itself again be open to resource 
> attacks.
> Why 5? Do you want to allow a node to make a typo?

Good point. Maybe one false try should lead to ignoring the peer.

> 
> 
>> To ensure that no message was dropped or blocked, the complete communication 
> must be hashed (sha256). Both peers keep the SHA256 context of the encryption 
> session. The complete <code>enc</code> message (leaving out the hash itself) 
> must be added to the hash-context by both parties. Before sending a 
> <code>enc</code> command, the sha256 context will be copied and finalized.
> 
> You write "the complete communication must be hashed" and every message has a 
> hash of the state until it is at that point.
> I think you need to explain how that works specifically.

This is a relative simple concept and does not require rehashing the
whole communication. You just append the "new data".

Some pseudocode:

SHA256CTX ctx;

// first com
SHA256CTX_Update(ctx, 1stmessage);

// copy context
SHA256CTX ctxnew = ctx;

// finalize the copied context
sha256hash = SHA256CTX_Finalize(ctxnew); //use as checksum hash


//////// next message
SHA256CTX_Update(ctx, 2ndmessage);

// copy context
SHA256CTX ctxnew = ctx;

// finalize the copied context
sha256hash = SHA256CTX_Finalize(ctxnew); //use as checksum hash

... etc.

</jonas>


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

 permalink raw reply	[|nested]
2016-03-23 20:36 ` Tom
  2016-03-23 21:40   ` Eric Voskuil
  2016-03-23 21:55   ` Jonas Schnelli

  
From: Sergio Demian Lerner @ 2016-03-24  0:37 UTC (permalink / raw)
  To: bitcoin-dev

[-- Attachment #1: Type: text/plain, Size: 2341 bytes --]

It seems that every message must be signed (the protocols lacks MACs). This
can be very resource consuming in terms of CPU and bandwidth since most p2p
messages are small.


On Wed, Mar 23, 2016 at 5:36 PM, Tom via bitcoin-dev <
bitcoin-dev@lists•linuxfoundation.org> wrote:

> On Wednesday 23 Mar 2016 16:24:12 Jonas Schnelli via bitcoin-dev wrote:
> > Hi
> >
> > I have just PRed a draft version of two BIPs I recently wrote.
> > https://github.com/bitcoin/bips/pull/362
>
> I suggest running a spellchecker ;)
>
> Some questions;
>
> * why would you not allow encryption on non-pre-approved connections?
> * we just removed (ssl) encryption from the JSON interface, how do you
> suggest
> this encryption to be implemented without openSSL?
> * What is the reason for using the p2p code to connect a wallet to a node?
> I suggest using one of the other connection methods to connect to the node.
> This avoids a change in the bitcoin protocol for a very specific usecase.
> * Why do you want to do a per-message encryption (wrapping the original)?
> Smaller messages that contain predictable content and are able to be
> matched
> to the unencrypted versions on the wire send to other nodes will open this
> scheme up to various old statistical attacks.
>
> > Responding peers must ignore (banning would lead to fingerprinting) the
> requesting peer after 5 unsuccessfully authentication tries to avoid
> resource
> attacks.
>
> Any implementation of that kind would itself again be open to resource
> attacks.
> Why 5? Do you want to allow a node to make a typo?
>
>
> > To ensure that no message was dropped or blocked, the complete
> communication
> must be hashed (sha256). Both peers keep the SHA256 context of the
> encryption
> session. The complete <code>enc</code> message (leaving out the hash
> itself)
> must be added to the hash-context by both parties. Before sending a
> <code>enc</code> command, the sha256 context will be copied and finalized.
>
> You write "the complete communication must be hashed" and every message
> has a
> hash of the state until it is at that point.
> I think you need to explain how that works specifically.
>
>
> _______________________________________________
> bitcoin-dev mailing list
> bitcoin-dev@lists•linuxfoundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>

[-- Attachment #2: Type: text/html, Size: 3119 bytes --]

 permalink raw reply	[|nested]
* 
  2016-03-23 15:24 [bitcoin-dev] p2p authentication and encryption BIPs Jonas Schnelli
  2016-03-23 16:44 ` Tier Nolan

  2016-03-23 21:40   ` 
                     ` 
  2016-03-24  2:16 ` 
                   ` 
  6 siblings, 3 replies; 23+ messages in thread
From: Tom @ 2016-03-23 20:36 UTC (permalink / raw)
  To: bitcoin-dev

On Wednesday 23 Mar 2016 16:24:12 Jonas Schnelli via bitcoin-dev wrote:
> Hi
> 
> I have just PRed a draft version of two BIPs I recently wrote.
> https://github.com/bitcoin/bips/pull/362

I suggest running a spellchecker ;)

Some questions;

* why would you not allow encryption on non-pre-approved connections?
* we just removed (ssl) encryption from the JSON interface, how do you suggest 
this encryption to be implemented without openSSL?
* What is the reason for using the p2p code to connect a wallet to a node?
I suggest using one of the other connection methods to connect to the node. 
This avoids a change in the bitcoin protocol for a very specific usecase.
* Why do you want to do a per-message encryption (wrapping the original)? 
Smaller messages that contain predictable content and are able to be matched 
to the unencrypted versions on the wire send to other nodes will open this 
scheme up to various old statistical attacks.

> Responding peers must ignore (banning would lead to fingerprinting) the 
requesting peer after 5 unsuccessfully authentication tries to avoid resource 
attacks.

Any implementation of that kind would itself again be open to resource 
attacks.
Why 5? Do you want to allow a node to make a typo?


> To ensure that no message was dropped or blocked, the complete communication 
must be hashed (sha256). Both peers keep the SHA256 context of the encryption 
session. The complete <code>enc</code> message (leaving out the hash itself) 
must be added to the hash-context by both parties. Before sending a 
<code>enc</code> command, the sha256 context will be copied and finalized.

You write "the complete communication must be hashed" and every message has a 
hash of the state until it is at that point.
I think you need to explain how that works specifically.




^ permalink raw reply	[|nested] 23+ messages in thread
* 
  2016-03-23 15:24 [bitcoin-dev] p2p authentication and encryption BIPs Jonas Schnelli
  2016-03-23 16:44 ` Tier Nolan
  2016-03-23 20:36 ` Tom

  2016-03-24 17:20 ` 
                   ` 
  6 siblings, 0 replies; 23+ messages in thread
From: Luke Dashjr @ 2016-03-24  2:16 UTC (permalink / raw)
  To: bitcoin-dev, Jonas Schnelli

On Wednesday, March 23, 2016 3:24:12 PM Jonas Schnelli via bitcoin-dev wrote:
> I have just PRed a draft version of two BIPs I recently wrote.
> https://github.com/bitcoin/bips/pull/362

In the future, please submit BIP drafts to the mailing list for comment and 
initial peer review before opening a pull request (or requesting a BIP number 
assignment), per BIP 1.

> Each peer that supports p2p authentication, must provide two user editable
> databases (can be a simple record-per-line file).

As long as the format of these databases is not standardised, it seems 
inappropriate to define *any* of this implementation detail in a BIP.

> A peer can send an authenticate message by wrapping the desired message into
> an <code>auth</code>-message-wrapper to the remote peer.

How does a peer know what messages the other peer requires to be 
authenticated?

> 33bytes || identity-pubkey || comp.-pubkey || The identity pubkey of the
> requesting peer

Seems a waste to include this with every single [authenticated] message...

> 8bytes || auth-msg-id || int64 || up-counting auth-msg-id (0 to INT64MAX)

Is this required to persist across connections/restarts/possibly complete 
reinstalls?

Can the same auth-msg-id be used for multiple peers, so a message can be 
signed once and sent to all N peers?

> Responding peers must ignore (banning would lead to fingerprinting) the
> requesting peer after 5 unsuccessfully authentication tries to avoid
> resource attacks.

How does banning in this specific case enable fingerprinting as opposed to any 
other banning?

> The peers should display the identity-pubkey as a identity-address to the
> users, which is a base58-check encoded ripemd160(sha256) hash.

If this is going to become a general-purpose identity system, I think more is 
needed than a simple EC keypair. At the very least, it should probably use a 
HD chain and use a new key for every signature (notice you already have auth-
msg-id to use with this!).

> This proposal is backward compatible. Non supporting peers will ignore the
> <code>auth</code> message.

... and not process it at all? How is that backward compatible?

> 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 a secure channel.

I don't see how Tor fails this criteria...

> The responding peer will set a session timeout time-interval. The default
> must be 1'800 seconds.

What default? Is the timeout field optional? Why not simply require it?

> This proposal is backward compatible. Non supporting peers will ignore the
> <code>enc*</code> messages.

How should the supporting peer handle the message being ignored?

Luke


^ permalink raw reply	[|nested] 23+ messages in thread
* 
  2016-03-23 15:24 [bitcoin-dev] p2p authentication and encryption BIPs Jonas Schnelli
                   ` (2 preceding siblings ...)
  2016-03-24  2:16 ` Luke Dashjr

  2016-03-25 10:41   ` Tom
  2016-03-25  7:17 ` 
                   ` 
  6 siblings, 1 reply; 23+ messages in thread
From: Chris @ 2016-03-24 17:20 UTC (permalink / raw)
  To: bitcoin-dev

[-- Attachment #1: Type: text/plain, Size: 1223 bytes --]

Thanks for doing some work on this Jonas. It's something I've been
interested in for a while. I haven't had an opportunity to read the bips
but I will do so soon and comment.

As far as the use cases others mentioned, connecting and SPV wallet to
your full node is certainly one. It would make it easy to, say, connect
the android bitcoin-wallet to your own node. I've hacked on that wallet
to make it connect to my .onion node, but it's very slow border-line
unusable. Basic encryption and authentication would make that viable.

Also, while bloom filtering in bitcoinj is broken, it could be fixed by
just creating a single filter and filling it with 1000 addresses and
persisting it to disk. The main issue is you can't restore from seed
that way and would have to revert to what bitcoinj does now and blow
your privacy. If you had the ability to make an encrypted connection to
a trusted node just for restoring from seed, you could save your privacy
during a restore.

On 03/23/2016 11:24 AM, Jonas Schnelli via bitcoin-dev wrote:
>
>
> _______________________________________________
> bitcoin-dev mailing list
> bitcoin-dev@lists•linuxfoundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev


[-- Attachment #2: Type: text/html, Size: 1936 bytes --]

^ permalink raw reply	[|nested] 23+ messages in thread
2016-03-23 15:24 [bitcoin-dev] p2p authentication and encryption BIPs Jonas Schnelli
                   ` (4 preceding siblings ...)
  2016-03-25  7:17 ` Lee Clagett

  2016-04-01 21:09 ` Jonas Schnelli
  
From: Jonas Schnelli @ 2016-03-25 10:17 UTC (permalink / raw)
  To: bitcoin-dev


[-- Attachment #1.1: Type: text/plain, Size: 2236 bytes --]

> I have just PRed a draft version of two BIPs I recently wrote.
> https://github.com/bitcoin/bips/pull/362

Thanks for the feedback and IRC discussions.

I have overhauled both BIPs.
https://github.com/bitcoin/bips/pull/362/files#diff

Main changes for the encryption BIP:
* No message wrapping. Once encryption is established, everything is
encrypted. No timeout.
* Added MAC: proposed AEAD is now ChaCha20-Poly1305 with an alternative
for AES256-GCH
* Independent ECDH negotiation and independent secrets for the symmetric
cipher for both communication directions
* Optimized message format and message-batch-option for encrypted data

It could be that the p2p performance for Chacha20-poly1305 encrypted
message is slightly better then the current plaintext message format
(dropping the network magic and the sha256 per message).

P2p authentication BIP:
* No message wrapping. Peers keep the state once authenticated.
* Simplified and auth now requires encrypted channels.


Some answers...

> How does a peer know what messages the other peer requires to be
authenticated?

This is not covered by the auth BIP. Peers could agree on a protocol
extension outside of any BIP.
Once auth is possible, new BIPs could be written. Things like only
allowing filtering (or other services) to authenticated peers (and
disabling NODE_BLOOM).

> How does banning in this specific case enable fingerprinting as
opposed to any other banning?

Current nodes ignore a unknown message with a command like "auth".
Banning would allow a requesting peer to identify nodes that support
auth and attack them over different channels ("ah, ... this guy supports
auth, they must have some secret data, lets attack over SSH).

>> This proposal is backward compatible. Non supporting peers will
ignore the <code>auth</code> message.
> ... and not process it at all? How is that backward compatible?

Depends how we define backward compatibility. :-)
Peers supporting this "extension" can still interact with older peers.

> This proposal is backward compatible. Non supporting peers will ignore
the > <code>enc*</code> messages.

Current p2p implementation ignores any unknown command.


</jonas>


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

 permalink raw reply	[|nested]
2016-03-23 21:55   ` Jonas Schnelli

  2016-03-25 18:43       ` Jonas Schnelli
  
From: Tom @ 2016-03-25 10:36 UTC (permalink / raw)
  To: bitcoin-dev

On Wednesday 23 Mar 2016 22:55:34 Jonas Schnelli via bitcoin-dev wrote:
> >> I have just PRed a draft version of two BIPs I recently wrote.
> > * why would you not allow encryption on non-pre-approved connections?
> 
> The encryption should be optional.
> The proposed authentication scheme does take care of the
> identity-management and therefor prevent MITM attacks.
> Without the identity management, you might not detect sending/receiving
> encrypted data from/to a MITM.

If you want to extend the Bitcoin protocol itself, you will have to resolve 
that. Which many other solutions do (ssh for instance).

It would not be Ok to have an peer-to-peer encryption system that doesn't 
allow non-pre-approved connections.

> > * What is the reason for using the p2p code to connect a wallet to a node?
> > I suggest using one of the other connection methods to connect to the
> > node.
> > This avoids a change in the bitcoin protocol for a very specific usecase.
> 
> Most known use-case: SPV.

You didn't answer the question.

> > * Why do you want to do a per-message encryption (wrapping the original)?
> > Smaller messages that contain predictable content and are able to be
> > matched to the unencrypted versions on the wire send to other nodes will
> > open this scheme up to various old statistical attacks.
> 
> It's probably extremely inefficient to create a constant time stream.

Your use of "probably" makes me wonder if you already have an implementation. 
Doing any encryption and handshaking design *without* actually having it coded 
and gone though testing yet makes no sense.
I do not belief Bitcoin will benefit from "design by committee" where a 
specification is drawn before an implementation is written.

Also, you didn't actually address the attack-vector.

 
> >> Responding peers must ignore (banning would lead to fingerprinting) the
> > 
> > requesting peer after 5 unsuccessfully authentication tries to avoid
> > resource attacks.
> > 
> > Any implementation of that kind would itself again be open to resource
> > attacks.
> > Why 5? Do you want to allow a node to make a typo?
> 
> Good point. Maybe one false try should lead to ignoring the peer.

That doesn't take away the resource attack at all.

 
> >> To ensure that no message was dropped or blocked, the complete
> >> communication> 
> > must be hashed (sha256). Both peers keep the SHA256 context of the
> > encryption session. The complete <code>enc</code> message (leaving out
> > the hash itself) must be added to the hash-context by both parties.
> > Before sending a <code>enc</code> command, the sha256 context will be
> > copied and finalized.
> > 
> > You write "the complete communication must be hashed" and every message
> > has a hash of the state until it is at that point.
> > I think you need to explain how that works specifically.
> 
> This is a relative simple concept and does not require rehashing the
> whole communication. 

Apologies, I should have been more clear; the BIP should specify the actual 
algorithm, otherwise you can't create an implementation from just reading the 
BIP.

Also, this may be a good time to ask why you want to have a per-message 
encryption?
Practically every single popular end-to-end encryption uses one approach or 
another were it just encrypts as another layer. (the  L in ssl). You are 
mixing layers, and unless you do that for a very good reason, or have a very 
good reason why everyone else is doing it wrong, I suggest using a layered 
encryption approach.


 permalink raw reply	[|nested]
2016-03-24 17:20 ` Chris

  
From: Tom @ 2016-03-25 10:41 UTC (permalink / raw)
  To: bitcoin-dev, Chris

On Thursday 24 Mar 2016 13:20:48 Chris via bitcoin-dev wrote:
> As far as the use cases others mentioned, connecting and SPV wallet to
> your full node is certainly one. It would make it easy to, say, connect
> the android bitcoin-wallet to your own node. I've hacked on that wallet
> to make it connect to my .onion node, but it's very slow border-line
> unusable. Basic encryption and authentication would make that viable.

What about using some interface, much like the JSON one (but more likely the 
zeroMQ one) instead? Would that not solve the problem?

I'm thinking that would not be a replacement for a full-node-connection but in 
addition.

Which means that some questions can be asked over that channel that you need 
authentication for. It would be a much better separation of concerns.


 permalink raw reply	[|nested]
2016-03-25 10:36     ` Tom

  2016-03-25 20:42         ` Tom
  
From: Jonas Schnelli @ 2016-03-25 18:43 UTC (permalink / raw)
  To: bitcoin-dev


[-- Attachment #1.1: Type: text/plain, Size: 5182 bytes --]

Hi Tom

>> The encryption should be optional.
>> The proposed authentication scheme does take care of the
>> identity-management and therefor prevent MITM attacks.
>> Without the identity management, you might not detect sending/receiving
>> encrypted data from/to a MITM.
> 
> If you want to extend the Bitcoin protocol itself, you will have to resolve 
> that. Which many other solutions do (ssh for instance).

Please check the newest auth BIP (it solves MITM).

The encryption BIP itself does not cover peer authentication.
Encryption without authentication of peers can also be valuable.


>>> * What is the reason for using the p2p code to connect a wallet to a node?
>>> I suggest using one of the other connection methods to connect to the
>>> node.
>>> This avoids a change in the bitcoin protocol for a very specific usecase.
>>
>> Most known use-case: SPV.
> 
> You didn't answer the question.

I hope you see the today's problem with SPV.
You fully reveal to your ISP / WiFi provider most of your wallet
controlled addresses (when using BF). The ISP/WiFi provider can link
your bitcoin usage to other inet traffic and/or they could sell
information to statistics company like google.

Also, an attacker controlling a WiFi router or any other network peer
between your SPV node and the remote full node could censorship
transactions.

Etc. etc.

An encrypted channel together with a trusted full node would finally
allow to have a secure and save SPV communication.


>>> * Why do you want to do a per-message encryption (wrapping the original)?
>>> Smaller messages that contain predictable content and are able to be
>>> matched to the unencrypted versions on the wire send to other nodes will
>>> open this scheme up to various old statistical attacks.
>>
>> It's probably extremely inefficient to create a constant time stream.
> 
> Your use of "probably" makes me wonder if you already have an implementation. 
> Doing any encryption and handshaking design *without* actually having it coded 
> and gone though testing yet makes no sense.
> I do not belief Bitcoin will benefit from "design by committee" where a 
> specification is drawn before an implementation is written.
> 
> Also, you didn't actually address the attack-vector.

Which attack-vector? MITM? Is conceptual solved with the auth BIP (that
requires encryption).

There is no implementation done yet.
It would be a waste of time to start writing a such implementation
_before_ having this discusses and improved by the community.

But the encryption BIP now recommends Chacha20-Polay1305 as AEAD which
is widely used.

I'm ready to write an implementation as soon as I have some signs that
the BIP does make sense.

Also, auth and enc is not something we will have in the next couple of
weeks. This might require a couple of months until its stable and ready
for production.

> 
>  
>>>> Responding peers must ignore (banning would lead to fingerprinting) the
>>>
>>> requesting peer after 5 unsuccessfully authentication tries to avoid
>>> resource attacks.
>>>
>>> Any implementation of that kind would itself again be open to resource
>>> attacks.
>>> Why 5? Do you want to allow a node to make a typo?
>>
>> Good point. Maybe one false try should lead to ignoring the peer.
> 
> That doesn't take away the resource attack at all.
> 
>  
>>>> To ensure that no message was dropped or blocked, the complete
>>>> communication> 
>>> must be hashed (sha256). Both peers keep the SHA256 context of the
>>> encryption session. The complete <code>enc</code> message (leaving out
>>> the hash itself) must be added to the hash-context by both parties.
>>> Before sending a <code>enc</code> command, the sha256 context will be
>>> copied and finalized.
>>>
>>> You write "the complete communication must be hashed" and every message
>>> has a hash of the state until it is at that point.
>>> I think you need to explain how that works specifically.
>>
>> This is a relative simple concept and does not require rehashing the
>> whole communication. 
> 
> Apologies, I should have been more clear; the BIP should specify the actual 
> algorithm, otherwise you can't create an implementation from just reading the 
> BIP.

The sha256 context is gone now and replaced by a proper MAC.

> 
> Also, this may be a good time to ask why you want to have a per-message 
> encryption?
> Practically every single popular end-to-end encryption uses one approach or 
> another were it just encrypts as another layer. (the  L in ssl). You are 
> mixing layers, and unless you do that for a very good reason, or have a very 
> good reason why everyone else is doing it wrong, I suggest using a layered 
> encryption approach.

Like most other encryption layers, we would still use messages. But we
call them "encrypted messages", the have a tiny header of plaintext data
(message length, AEAD-tag) and they will contain <n> plaintext p2p
messages _after_ decrypting. The plaintext messages have a much simpler
header (removed the 4 bytes sha256 checksum, removed the 4byte network)

</jonas>


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

 permalink raw reply	[|nested]
2016-03-25 18:43       ` Jonas Schnelli

  2016-03-26  9:01           ` Jonas Schnelli
  2016-03-26 23:23           ` James MacWhyte
  
From: Tom @ 2016-03-25 20:42 UTC (permalink / raw)
  To: bitcoin-dev

On Friday 25 Mar 2016 19:43:00 Jonas Schnelli via bitcoin-dev wrote:
> An encrypted channel together with a trusted full node would finally
> allow to have a secure and save SPV communication.

I guess my question didn't get across. 

Why would you want to make your usecase do connections over the peer2peer 
(net.cpp) connection at all?

Mixing messages that are being sent to everyone and encrypted messages is 
asking for trouble.
Making your private connection out-of-band would work much better.

> > Also, you didn't actually address the attack-vector.
> 
> Which attack-vector?

The statistical attack I mentioned earlier.  Which comes from knowing which 
plain text messages are being sent over the encrypted channel, So as long as 
you keep saying you want to encrypt data that identical copies of are being 
sent to other nodes at practically the same time, you will keep being 
vulnerable to that.




 permalink raw reply	[|nested]
2016-03-25 20:42         ` Tom

  2016-03-26 23:23           ` James MacWhyte
  
From: Jonas Schnelli @ 2016-03-26  9:01 UTC (permalink / raw)
  To: bitcoin-dev


[-- Attachment #1.1: Type: text/plain, Size: 2764 bytes --]


> I guess my question didn't get across. 
> 
> Why would you want to make your usecase do connections over the peer2peer 
> (net.cpp) connection at all?

First, because there _are_ a hight amount of SPV wallets in the field.
SPV wallets are "dumb-clients" with only a tiny value for the bitcoin
network (they don't validate, they don't relay). They already are
decoupled wallets. We need solution that offers higher privacy and
higher traffic analysis resistance.

Using the p2p channel for communication between full validation peers
and wallet-only-peers makes sense IMO because wallet-only-peers can
slowly validate the chain and create a UTXO set in the background (could
take a couple of weeks) or solve other purposes that increases the
security and/or serving something back to the bitcoin network.

Sure, you can always use client/server wallets (Coinbase / Copay, etc.)
that offers SSL.
But I strongly recommend to improve the communication and interface
possibilities between wallet-nodes (SPV) and full-validation-nodes.

Otherwise we will very likely see centralization regarding end-user
wallets (with all the large risks of disrupting the community in case of
attacks/thefts, etc.).

_If we think Bitcoin should scale, we also need to scale and improve at
the point where users enter the network and start using Bitcoin._

> Mixing messages that are being sent to everyone and encrypted messages is 
> asking for trouble.
> Making your private connection out-of-band would work much better.

The current encryption BIP requires to encrypt the complete traffic.
Having an option to do analysis resistant communication with a remote
peer within the protocol itself is something that is very valuable IMO.


>>> Also, you didn't actually address the attack-vector.
>>
>> Which attack-vector?
> 
> The statistical attack I mentioned earlier.  Which comes from knowing which 
> plain text messages are being sent over the encrypted channel, So as long as 
> you keep saying you want to encrypt data that identical copies of are being 
> sent to other nodes at practically the same time, you will keep being 
> vulnerable to that.

The encryption BIP recommends Chacha20-Poly1305 as encryption AEAD. This
is a very broad used encryption scheme (Google uses it to connect
Android phones with their cloud services).

Completely avoiding side channel on data analysis would probably require
extremely inefficient constant time encrypted datastreams.

Also, the BIP allows combining of multiple plaintext message in one
encrypted message.

Additionally we could extend the enc. BIP by allowing random padding of
encrypted messages or other techniques to reduce side channel analysis.

</jonas>


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

 permalink raw reply	[|nested]
2016-03-25 20:42         ` Tom
  2016-03-26  9:01           ` Jonas Schnelli

  2016-03-27 11:58             ` Jonas Schnelli
  
From: James MacWhyte @ 2016-03-26 23:23 UTC (permalink / raw)
  To: Tom, bitcoin-dev

[-- Attachment #1: Type: text/plain, Size: 1876 bytes --]

On Sat, Mar 26, 2016 at 1:34 AM Tom via bitcoin-dev <
bitcoin-dev@lists•linuxfoundation.org> wrote:

> On Friday 25 Mar 2016 19:43:00 Jonas Schnelli via bitcoin-dev wrote:
> > An encrypted channel together with a trusted full node would finally
> > allow to have a secure and save SPV communication.
>
> I guess my question didn't get across.
>
> Why would you want to make your usecase do connections over the peer2peer
> (net.cpp) connection at all?
>
> Mixing messages that are being sent to everyone and encrypted messages is
> asking for trouble.
> Making your private connection out-of-band would work much better.
>
>
I agree doing it out-of-band is the easiest solution for people who need
this privacy right now, but I do like the idea of adding this feature as
the number of SPV wallets is going to increase. I think the best way to
organize things would be to give encrypted messages their own port number,
similar to how http vs. https works.

We don't want two networks to develop, separated by which nodes support
encryption and which don't, so ideally nodes would rebroadcast messages
they receive on both (encrypted and non-encrypted) channels. This would
essentially double the required bandwidth of the network, which is
something to think about.


> > > Also, you didn't actually address the attack-vector.
> >
> > Which attack-vector?
>
> The statistical attack I mentioned earlier.  Which comes from knowing which
> plain text messages are being sent over the encrypted channel, So as long
> as
> you keep saying you want to encrypt data that identical copies of are being
> sent to other nodes at practically the same time, you will keep being
> vulnerable to that.
>
>
> _______________________________________________
> bitcoin-dev mailing list
> bitcoin-dev@lists•linuxfoundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>

[-- Attachment #2: Type: text/html, Size: 2602 bytes --]

 permalink raw reply	[|nested]
2016-03-26 23:23           ` James MacWhyte

  2016-03-27 17:04               ` James MacWhyte
  
From: Jonas Schnelli @ 2016-03-27 11:58 UTC (permalink / raw)
  To: bitcoin-dev


[-- Attachment #1.1: Type: text/plain, Size: 2571 bytes --]


>     I guess my question didn't get across.
> 
>     Why would you want to make your usecase do connections over the
>     peer2peer
>     (net.cpp) connection at all?
> 
>     Mixing messages that are being sent to everyone and encrypted
>     messages is
>     asking for trouble.
>     Making your private connection out-of-band would work much better.
> 
> 
> I agree doing it out-of-band is the easiest solution for people who need
> this privacy right now, but I do like the idea of adding this feature as
> the number of SPV wallets is going to increase. I think the best way to
> organize things would be to give encrypted messages their own port
> number, similar to how http vs. https works.

I'm not sure if different ports would make sense. I can't see a benefit
(happy if someone can convince me).
How would this affect p2p address management (address relay)? Wouldn't
this require to extend the current address message to support two port
numbers?


> We don't want two networks to develop, separated by which nodes support
> encryption and which don't, so ideally nodes would rebroadcast messages
> they receive on both (encrypted and non-encrypted) channels. This would
> essentially double the required bandwidth of the network, which is
> something to think about.

It can be the same "p2p network". The only difference would be, that
once two peers has negotiated encryption, the whole traffic between
_these two peers_, and _only_ these two pears, would be encrypted (would
_not_ affect traffic to/from other peers).

A simplified example:
1. Peer Alice connects to peer Bob
2. Alice asks Bob: "lets do encrypted communication, here is my session
pubkey"
3. Bob also supports encryption and answers "Yes, let's do this, here is
my session pubkey"
4. Alice tells Bob (encrypted now): "Perfect. Here I prove that I'm
Alice by signing the session ID with my identity pubkey"
5. Bob checks his "authorized-peers" database and look-up Alices pubkey
and verifies the signatures.
6. Bob tells Alice: "Good! I trust you now Alice, here is my identity
pubkey with a signature of our session-ID"
7. Alice looks up Bobs pubkey in her "known-peers" database and verifies
the signature.
8. Alice response to bob: "Perfect. Indeed, you are Bob!"
---
At this point, the communication is encrypted and the identities has
been verified (MITM protection).


(simplified negotiation [only one-way, missing dh explanation, missing
KDF, session-ID, cipher suite nego., missing re-keying, etc.])


</jonas>


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

 permalink raw reply	[|nested]
2016-03-27 11:58             ` Jonas Schnelli

  
From: James MacWhyte @ 2016-03-27 17:04 UTC (permalink / raw)
  To: Jonas Schnelli, bitcoin-dev

[-- Attachment #1: Type: text/plain, Size: 4160 bytes --]

On Sun, Mar 27, 2016 at 5:49 AM Jonas Schnelli via bitcoin-dev <
bitcoin-dev@lists•linuxfoundation.org> wrote:

>
> >     I guess my question didn't get across.
> >
> >     Why would you want to make your usecase do connections over the
> >     peer2peer
> >     (net.cpp) connection at all?
> >
> >     Mixing messages that are being sent to everyone and encrypted
> >     messages is
> >     asking for trouble.
> >     Making your private connection out-of-band would work much better.
> >
> >
> > I agree doing it out-of-band is the easiest solution for people who need
> > this privacy right now, but I do like the idea of adding this feature as
> > the number of SPV wallets is going to increase. I think the best way to
> > organize things would be to give encrypted messages their own port
> > number, similar to how http vs. https works.
>
> I'm not sure if different ports would make sense. I can't see a benefit
> (happy if someone can convince me).
> How would this affect p2p address management (address relay)? Wouldn't
> this require to extend the current address message to support two port
> numbers?
>
> I'm assuming clients that connect with encryption don't want to use
unencrypted connections, and are only interested in other peers that
support encryption. From their perspective, it is quite inefficient to get
a generic list of peers and then have to connect to each one searching for
those that accept encryption. If we use port numbers, we can assume any
connection that comes on the encrypted port is only interested in encrypted
communication, so a getaddr to an encrypted port would only return a list
of other encryption-capable peers.

This isn't an issue if the plan is to require all peers to support
encryption, and we assume the majority of the network will upgrade before
too long.


>
> > We don't want two networks to develop, separated by which nodes support
> > encryption and which don't, so ideally nodes would rebroadcast messages
> > they receive on both (encrypted and non-encrypted) channels. This would
> > essentially double the required bandwidth of the network, which is
> > something to think about.
>
> It can be the same "p2p network". The only difference would be, that
> once two peers has negotiated encryption, the whole traffic between
> _these two peers_, and _only_ these two pears, would be encrypted (would
> _not_ affect traffic to/from other peers).
>
>
You're right, there would not be an increase in bandwidth. Please forget I
said that :) But following the logic I wrote above, it would be possible
for peers to become segregated (those who require encryption would only
connect to each other). It wouldn't be a problem as long as there are
enough peers that provide both encrypted and non-encrypted connections; or,
as I said above, if we can assume every peer will support it. Maybe the
issues I'm thinking of are just growing pains that will be solved once the
majority of people upgrade?


> A simplified example:
> 1. Peer Alice connects to peer Bob
> 2. Alice asks Bob: "lets do encrypted communication, here is my session
> pubkey"
> 3. Bob also supports encryption and answers "Yes, let's do this, here is
> my session pubkey"
> 4. Alice tells Bob (encrypted now): "Perfect. Here I prove that I'm
> Alice by signing the session ID with my identity pubkey"
> 5. Bob checks his "authorized-peers" database and look-up Alices pubkey
> and verifies the signatures.
> 6. Bob tells Alice: "Good! I trust you now Alice, here is my identity
> pubkey with a signature of our session-ID"
> 7. Alice looks up Bobs pubkey in her "known-peers" database and verifies
> the signature.
> 8. Alice response to bob: "Perfect. Indeed, you are Bob!"
> ---
> At this point, the communication is encrypted and the identities has
> been verified (MITM protection).
>
>
> (simplified negotiation [only one-way, missing dh explanation, missing
> KDF, session-ID, cipher suite nego., missing re-keying, etc.])
>
>
> </jonas>
>
> _______________________________________________
> bitcoin-dev mailing list
> bitcoin-dev@lists•linuxfoundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>

[-- Attachment #2: Type: text/html, Size: 5344 bytes --]

 permalink raw reply	[|nested]
2016-03-23 15:24 [bitcoin-dev] p2p authentication and encryption BIPs Jonas Schnelli
                   ` (5 preceding siblings ...)
  2016-03-25 10:17 ` Jonas Schnelli

  2016-04-09 19:40   ` Lee Clagett
  
From: Jonas Schnelli @ 2016-04-01 21:09 UTC (permalink / raw)
  To: bitcoin-dev


[-- Attachment #1.1: Type: text/plain, Size: 1045 bytes --]


> I have just PRed a draft version of two BIPs I recently wrote.
> https://github.com/bitcoin/bips/pull/362

Hi.
I just updated the PR above with another overhaul of the BIP.
It's still under heavy review/work, nevertheless – at this point – any
feedback is highly welcome.

Changes since last update:
-> Removed AES256-GCM as cipher suite
-> Focusing on Chacha20-Poly1305 (implementation size ~300L)
-> Two symmetric cipher keys must be calculated by HMAC_SHA512 from the
ecdh secret
-> A session-ID (both directions) must be calculated (HMAC_SHA256) for
linking an identity authentication (ecdsa sig of the session-ID) with
the encryption
-> Re-Keying ('=hash(old_key)') can be announced by the responding peer
(after x minutes and/or after x GB, local peer policy but not shorter
then 10mins).
-> AEAD tag is now the last element in the new message format

It is very likely that the encrypted message format performs slightly
better than the current message format (removing the SHA256 checksum).

---
</jonas>


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

 permalink raw reply	[|nested]
2016-04-01 21:09 ` Jonas Schnelli

  2016-05-18  8:00     ` Jonas Schnelli
  
From: Lee Clagett @ 2016-04-09 19:40 UTC (permalink / raw)
  To: Jonas Schnelli via bitcoin-dev

On Fri, 1 Apr 2016 23:09:47 +0200
Jonas Schnelli via bitcoin-dev <bitcoin-dev@lists•linuxfoundation.org>
wrote:
> > I have just PRed a draft version of two BIPs I recently wrote.
> > https://github.com/bitcoin/bips/pull/362  
> 
> Hi.
> I just updated the PR above with another overhaul of the BIP.
> It's still under heavy review/work, nevertheless – at this point – any
> feedback is highly welcome.
> 
> Changes since last update:
> -> Removed AES256-GCM as cipher suite
> -> Focusing on Chacha20-Poly1305 (implementation size ~300L)
> -> Two symmetric cipher keys must be calculated by HMAC_SHA512 from
> the ecdh secret
> -> A session-ID (both directions) must be calculated (HMAC_SHA256)
> for linking an identity authentication (ecdsa sig of the session-ID)
> with the encryption
> -> Re-Keying ('=hash(old_key)') can be announced by the responding
> peer (after x minutes and/or after x GB, local peer policy but not
> shorter then 10mins).
> -> AEAD tag is now the last element in the new message format  
> 
> It is very likely that the encrypted message format performs slightly
> better than the current message format (removing the SHA256 checksum).
> 
> ---
> </jonas>
> 


The quotes below are from the BIPs and not the email chain ...

> Rejecting the <code>auth</code> request will not reveal the
> responding peers identity that could lead to fingerprinting the node,
> however this BIP does not cover protection against fingerprinting the
> requesting node from the perspective of the responding node.

In many use cases the requesting node will want to make a connection to
a peer with a specific identity. After encryption initialization, the
requesting node could generate an ECDH secret from the long-term public
key of the expected peer and its own session private-key to encrypt (no
MAC) the signature with the same symmetric cipher agreed upon
previously. The requesting node will not reveal its identity if the
connection has been MitM'ed, while still being the first to provide
authentication. And since this would be "inside" the session-key
crypto, it still has forward-secrecy if the responding-peers longterm
private-key is later compromised.

*Key Revocation*
This is probably too complicated, but an additional public key would
allow for cold-storage key revocation. Spreading the knowledge of such
an event is always painful, but it could be stored in the blockchain. I
think this is likely too complicated, but having these long-term keys
constantly in memory/disk is unfortunate.


> Responding peers must ignore the requesting peer after a
> unsuccessfully authentication initialization to avoid resource
> attacks (banning would lead to fingerprinting of peers that support
> authentication). 

Once the responding peer has read the `auth` message, a TCP ACK can be
sent. From the requesting peer perspective, a TCP ACK of the `auth`
request indicates that it was read by the process or some
intermediary buffer (TOE, proxy, etc) has successfully forwarded it to
the next step. If the requesting peer waits RTT * some constant from
the ACK and gets no response, then either: a failed `auth` occurred,
`auth` is not supported, or the machine was suddenly overloaded. The
requesting peer can then send another message; a response message
indicates the responding peer does not support `auth`, and another no
response wait period indicates an overloaded peer or an `auth` enabled
peer. Initiating a new connection (no banning has occurred) indicates
either `auth` is enabled or a load-balancer re-directed the new
connection to another machine under less load. I think the latter case
is going to be rare, so you should be able to identify with high
probability nodes that support `auth` and what message types require
`auth`. And if this is process repeated multiple times, it will increase
the chances of a correct fingerprint.

Should encryption enabled peers who do _not_ support `auth` ignore all
subsequent messages after an `auth` attempt too? Fingerprinting on
`auth` required message types would still be possible. I do not see a
reliable way to prevent this from occurring.


> 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.

Why are there two key exchanges? A single shared-secret could be used
to generate keys for each direction. And it would reinforce the single
symmetric cipher rule.


> Possible symmetric key ciphers types
> {|class="wikitable"
> ! Number !! symmetric key ciphers type !! Comments
> |-
> | 0 || Chacha20-Poly1305 [3] || encrypted message length must be used
> as AAD. |}
>

Chacha20-Poly1305 defined in an IETF draft [0] and RFC 7539 both
include the ciphertext length in the authentication tag generation. Is
this a unique authentication construction? Or one of the previously
mentioned designs?

*Symmetric Cipher Negotiation*
Should the symmetric cipher choices be removed? I am mainly asking for
the intended use-case. If the intent is to replace a weakened cipher
then leave the cipher negotiation. If the intent is to give
implementations multiple options, then I would remove this negotiation.


> <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.

Chacha20 is a stream cipher, so only a single encryption key is needed.
The first 32 bytes of the keystream would be used for the Poly1305 key,
the next 4 bytes would be used to encrypt the length field, and the
remaining keystream would be used to encrypt the payload. Poly1305
would then generate a tag over the length and payload. The receiver
would generate the same keystream to decrypt the length which
identifies the length of the message and the MAC offset, then
authenticate the length and payload, then decypt with the remaining
keystream.

Is it safer to define two keys to prevent implementations from screwing
this up? You have to split the decryption and authentication, so the
basic modes of libsodium cannot be used for instance. If a custom tag
generation scheme is being used, then the basic modes are already
unusable ...

*Failed Authentication*
What happens on a failed MAC attempt? Connection closure is the
easiest way to handle the situation.


> 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).

The magic bytes are at the same offset and size as the encrypted length
field in the encrypted messages structure. So the magic bytes are not a
reliable way to identify unencrypted messages, although the probability
of collision is low.


> {|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
> |-
> | 8 || MAC tag || ? || MAC-tag truncated to 8 bytes
> |}

Why have a fixed MAC length? I think the MAC length should be inferred
from the cipher + authentication mode. And the Poly1305 tag is 16 bytes.

*Unauthenticated Buffering*
Implementations are unlikely to (i.e. should not) process the payload
until authentication succeeds. Since the length field is 4 bytes, this
means an implementation may have to buffer up to 4 GiB of data _per
connection_ before it can authenticate the length field. If the outter
length field were reduced to 2 or 3 bytes, the unauthenticated
buffering requirements drop to 64 KiB and 16 MiB respectively. Inner
messages already have their own length, so they can span multiple
encrypted blocks without other changes. This will increase the
bandwidth requirements when the size of a single message exceeds 64 KiB
or 16 MiB, since it will require multiple authentication tags for that
message. I think an additional 16 bytes per 16 MiB seems like a good
tradeoff.


> 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 600
> seconds.

Should the int64_t message count be reset to 0 on a re-key? Or should
the value reset to zero after 2^63-1? Hopefully the peer re-keys before
that rollover, or keystream reusage will occur. Unlikely that many
messages are sent on a single connection though. And presumably this
only re-keys the senders side? Bi-directional re-keying would be racy.



Lee

[0]https://tools.ietf.org/html/draft-ietf-tls-chacha20-poly1305-04


 permalink raw reply	[|nested]
2016-04-09 19:40   ` Lee Clagett

  2016-05-25  0:22       ` Lee Clagett
  
From: Jonas Schnelli @ 2016-05-18  8:00 UTC (permalink / raw)
  To: bitcoin-dev


[-- Attachment #1.1: Type: text/plain, Size: 5740 bytes --]

Hi Lee

Thank you very much for the valuable input.
I'm still processing your feedback....

> 
> *Key Revocation*
> This is probably too complicated, but an additional public key would
> allow for cold-storage key revocation. Spreading the knowledge of such
> an event is always painful, but it could be stored in the blockchain. I
> think this is likely too complicated, but having these long-term keys
> constantly in memory/disk is unfortunate.
> 

Yes. This could be something that could be extended once the BIP is
stable and/or implemented.



>> <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.
> 
> Chacha20 is a stream cipher, so only a single encryption key is needed.
> The first 32 bytes of the keystream would be used for the Poly1305 key,
> the next 4 bytes would be used to encrypt the length field, and the
> remaining keystream would be used to encrypt the payload. Poly1305
> would then generate a tag over the length and payload. The receiver
> would generate the same keystream to decrypt the length which
> identifies the length of the message and the MAC offset, then
> authenticate the length and payload, then decypt with the remaining
> keystream.
> 

Right. The AEAD construct I though of is probably called
chacha20-poly1305@openssh•com and specified in
https://github.com/openssh/openssh-portable/blob/05855bf2ce7d5cd0a6db18bc0b4214ed5ef7516d/PROTOCOL.chacha20poly1305#L34

I think this construct has already serval implementations and is widely
used.

I have updated the BIP to mention the chacha20-poly1305@openssh•com
specification.

> Is it safer to define two keys to prevent implementations from screwing
> this up? You have to split the decryption and authentication, so the
> basic modes of libsodium cannot be used for instance. If a custom tag
> generation scheme is being used, then the basic modes are already
> unusable ...
> 
> *Failed Authentication*
> What happens on a failed MAC attempt? Connection closure is the
> easiest way to handle the situation.

Yes. I think closing would make sense.

>> 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).
> 
> The magic bytes are at the same offset and size as the encrypted length
> field in the encrypted messages structure. So the magic bytes are not a
> reliable way to identify unencrypted messages, although the probability
> of collision is low.

Yes. This is a good point.
The implementation should probably also accept messages that contain the
4 byte network magic from unencrypted messages (to avoid possible
collisions).
If the message is unencrypted, the length check or the unsuccessful
authentication check will lead to a disconnect.

>> {|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
>> |-
>> | 8 || MAC tag || ? || MAC-tag truncated to 8 bytes
>> |}
> 
> Why have a fixed MAC length? I think the MAC length should be inferred
> from the cipher + authentication mode. And the Poly1305 tag is 16 bytes.
> 
> *Unauthenticated Buffering*
> Implementations are unlikely to (i.e. should not) process the payload
> until authentication succeeds. Since the length field is 4 bytes, this
> means an implementation may have to buffer up to 4 GiB of data _per
> connection_ before it can authenticate the length field. If the outter
> length field were reduced to 2 or 3 bytes, the unauthenticated
> buffering requirements drop to 64 KiB and 16 MiB respectively. Inner
> messages already have their own length, so they can span multiple
> encrypted blocks without other changes. This will increase the
> bandwidth requirements when the size of a single message exceeds 64 KiB
> or 16 MiB, since it will require multiple authentication tags for that
> message. I think an additional 16 bytes per 16 MiB seems like a good
> tradeoff.
> 

Good point.
I have mentioned this now in the BIP but I think the BIP should allow
message > 16 MiB.
I leave the max. message length up to the implementation while keeping
the 4 byte length on the protocol level.

> 
>> 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 600
>> seconds.
> 
> Should the int64_t message count be reset to 0 on a re-key? Or should
> the value reset to zero after 2^63-1? Hopefully the peer re-keys before
> that rollover, or keystream reusage will occur. Unlikely that many
> messages are sent on a single connection though. And presumably this
> only re-keys the senders side? Bi-directional re-keying would be racy.

I just added the RFC4253 recommendation as a must (re-key after every
1GB of data sent or received).


</jonas>


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

 permalink raw reply	[|nested]
2016-05-18  8:00     ` Jonas Schnelli

  2016-05-25  9:36         ` Jonas Schnelli
  
From: Lee Clagett @ 2016-05-25  0:22 UTC (permalink / raw)
  To: bitcoin-dev

On Wed, 18 May 2016 10:00:44 +0200
Jonas Schnelli via bitcoin-dev <bitcoin-dev@lists•linuxfoundation.org>
wrote:

> Hi Lee
> 
> Thank you very much for the valuable input.
> I'm still processing your feedback....

[...]

> > Why have a fixed MAC length? I think the MAC length should be
> > inferred from the cipher + authentication mode. And the Poly1305
> > tag is 16 bytes.
> > 
> > *Unauthenticated Buffering*
> > Implementations are unlikely to (i.e. should not) process the
> > payload until authentication succeeds. Since the length field is 4
> > bytes, this means an implementation may have to buffer up to 4 GiB
> > of data _per connection_ before it can authenticate the length
> > field. If the outter length field were reduced to 2 or 3 bytes, the
> > unauthenticated buffering requirements drop to 64 KiB and 16 MiB
> > respectively. Inner messages already have their own length, so they
> > can span multiple encrypted blocks without other changes. This will
> > increase the bandwidth requirements when the size of a single
> > message exceeds 64 KiB or 16 MiB, since it will require multiple
> > authentication tags for that message. I think an additional 16
> > bytes per 16 MiB seems like a good tradeoff.
> >   
> 
> Good point.
> I have mentioned this now in the BIP but I think the BIP should allow
> message > 16 MiB.
> I leave the max. message length up to the implementation while keeping
> the 4 byte length on the protocol level.

I expect the implementation defined max size to work (SSH 2.0 does this
after all), but I want to make sure my suggestion is understood
completely.

There is a length field for the encrypted data, and length field(s)
inside of the encrypted data to indicate the length of the plaintext
Bitcoin messages. I am suggesting that the outter (encrypted) length
field be reduced, which will _not limit_ the length of Bitcoin
messages. For example, if a 1 GiB Bitcoin message needed to be sent
and the encrypted length field was 3 bytes - the sender is forced to
send a minimum of 64 MACs for this message. The tradeoff is allowing
the receiver to detect malformed data sooner and have a lower max
buffering window **against** slightly higher bandwidth and CPU
requirements due to the additional headers+MACs (the CPU requirements
should primarily be in "finalizing each Poly1305").

An alternative way to think about the suggestion is tunnelling Bitcoin
messages over TLS or SSH. TLS 1.2 has a 2-byte length field and SSH 2.0
a 4-byte length field, but neither prevents larger Bitcoin messages from
being tunnelled; the lengths are independent.

[...]

> 
> </jonas>
> 

Lee


 permalink raw reply	[|nested]
2016-05-25  0:22       ` Lee Clagett

  
From: Jonas Schnelli @ 2016-05-25  9:36 UTC ( / )
  To: bitcoin-dev





>> Good point.
>> I have mentioned this now in the BIP but I think the BIP should allow
>> message > 16 MiB.
>> I leave the max. message length up to the implementation while keeping
>> the 4 byte length on the protocol level.
> 
> I expect the implementation defined max size to work (SSH 2.0 does this
> after all), but I want to make sure my suggestion is understood
> completely.
> 
> There is a length field for the encrypted data, and length field(s)
> inside of the encrypted data to indicate the length of the plaintext
> Bitcoin messages. I am suggesting that the outter (encrypted) length
> field be reduced, which will _not limit_ the length of Bitcoin
> messages. For example, if a 1 GiB Bitcoin message needed to be sent
> and the encrypted length field was 3 bytes - the sender is forced to
> send a minimum of 64 MACs for this message. The tradeoff is allowing
> the receiver to detect malformed data sooner and have a lower max
> buffering window **against** slightly higher bandwidth and CPU
> requirements due to the additional headers+MACs (the CPU requirements
> should primarily be in "finalizing each Poly1305").

Okay. Got your point.
The current BIPs assumption is that an encrypted package/message can
contain 1..n bitcoin messages (a single bitcoin message distributed over
multiple encrypted messages/packages was not specified).

But right, this could make sense.
Let me think this through....

> An alternative way to think about the suggestion is tunnelling Bitcoin
> messages over TLS or SSH. TLS 1.2 has a 2-byte length field and SSH 2.0
> a 4-byte length field, but neither prevents larger Bitcoin messages from
> being tunnelled; the lengths are independent.

TLS/SSH tunneling is already possible with third party software like
stunnel.
Also there is promising projects that would encrypt the traffic "on a
deeper layer" (see CurveCP).

I think what we want is a simple, openssl-independent traffic encryption
built into the core p2p layer.

IMO the risk of screwing up the implementation is moderate.

The implementation is not utterly-complex:
OpenSSH chacha20:
https://github.com/openssh/openssh-portable/blob/0235a5fa67fcac51adb564cba69011a535f86f6b/chacha.c

Chacha20-Poly1305:
https://github.com/openssh/openssh-portable/blob/0235a5fa67fcac51adb564cba69011a535f86f6b/cipher-chachapoly.c

Sure. Before an implementation will be deployed to the endusers it will
require intense cryptoanalysis first.

</jonas>