Return-Path: Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 799CFDB5 for ; Sat, 9 Apr 2016 19:41:30 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from sasl.smtp.pobox.com (pb-smtp0.pobox.com [208.72.237.35]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 5BFE1100 for ; Sat, 9 Apr 2016 19:41:29 +0000 (UTC) Received: from sasl.smtp.pobox.com (unknown [127.0.0.1]) by pb-smtp0.pobox.com (Postfix) with ESMTP id 24A3750870 for ; Sat, 9 Apr 2016 15:41:28 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=pobox.com; h=date:from:to :subject:message-id:in-reply-to:references:mime-version :content-type:content-transfer-encoding; s=sasl; bh=UYSSGiMHqQCm fYC+bDfZICpDRXg=; b=OrF67MDDJRsuZpNJdBZjaiFg8HqwkCCswA/IBFkzby6s ExnY9bBJrzjIzrfV3Hl2gowHTJUGoInhUxRlC9IfjIVHKtKDK9npU4NUDivTTEA3 il7wqzMtzKy+haU6nODlf55uUTiQxfbniPXaidQKkG2xFGqVGXFTM6l6sdqlmMg= Received: from pb-smtp0.int.icgroup.com (unknown [127.0.0.1]) by pb-smtp0.pobox.com (Postfix) with ESMTP id 1C8205086E for ; Sat, 9 Apr 2016 15:41:28 -0400 (EDT) Received: from laptop-m1330 (unknown [173.30.28.99]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by pb-smtp0.pobox.com (Postfix) with ESMTPSA id 97EAE5086D for ; Sat, 9 Apr 2016 15:41:27 -0400 (EDT) Date: Sat, 9 Apr 2016 15:40:38 -0400 From: Lee Clagett To: Jonas Schnelli via bitcoin-dev Message-ID: <20160409154038.4c04dd9b@laptop-m1330> In-Reply-To: <56FEE39B.3040401@jonasschnelli.ch> References: <56F2B51C.8000105@jonasschnelli.ch> <56FEE39B.3040401@jonasschnelli.ch> MIME-Version: 1.0 Content-Type: text/plain; charset=windows-1252 X-Pobox-Relay-ID: 0D027E88-FE8B-11E5-AC02-45AF6BB36C07-92142693!pb-smtp0.pobox.com Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org X-Mailman-Approved-At: Sat, 09 Apr 2016 19:56:18 +0000 Subject: Re: [bitcoin-dev] p2p authentication and encryption BIPs X-BeenThere: bitcoin-dev@lists.linuxfoundation.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: Bitcoin Development Discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 09 Apr 2016 19:41:30 -0000 On Fri, 1 Apr 2016 23:09:47 +0200 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 =20 >=20 > Hi. > I just updated the PR above with another overhaul of the BIP. > It's still under heavy review/work, nevertheless =96 at this point =96 = any > feedback is highly welcome. >=20 > 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 ('=3Dhash(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 =20 >=20 > It is very likely that the encrypted message format performs slightly > better than the current message format (removing the SHA256 checksum). >=20 > --- > >=20 The quotes below are from the BIPs and not the email chain ... > Rejecting the auth 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).=20 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 encinit > message to the responding peer and waits for a encack > message. The responding node must do the same > encinit/encack 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=3D"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. > K_1 must be used to only encrypt the payload size of the > encrypted message to avoid leaking information by revealing the > message size.=20 >=20 > K_2 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 encinit/encack > 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=3D"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 encack message containing 33byte of zeros to > indicate that all encrypted message following after this > encack message will be encrypted with ''the next > symmetric cipher key''. > > The new symmetric cipher key will be calculated by > SHA256(SHA256(old_symetric_cipher_key)). > > 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