LearnBitcoin

Bitcoin Dev Archive 2016

Authentication BIP

6 messages, 8 to 12 Aug 2016. Started by Jonas Schnelli.

Jonas Schnelli (3), Andy Schroder (2), Gregory Maxwell

Permalink Original thread on gnusha.org

Jonas Schnelli permalink original

Hi

As already mentioned in the recent BIP151 thread (https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-June/012826.html), I propose the following authentication scheme to basically allow MITM detection and rejection in conjunction with BIP151.

The proposed authentication BIP does require BIP151.

The propose BIP does assume, node operators want to build trusted connections for various reasons.

BIPs mediawiki github page available here: https://github.com/bitcoin/bips/compare/master...jonasschnelli:2016/07/auth_bip?expand=1

===================================================

  BIP: ???
  Title: Peer Authentication
  Author: Jonas Schnelli <dev@jonasschnelli•ch>
  Status: Draft
  Type: Standards Track
  Created: 2016-03-23

== Abstract ==

This BIP describes a way how peers can authenticate – without opening fingerprinting possibilities – to other peers to guarantee ownership and/or allowing to access additional or limited services.

== Motivation ==

We assume peer operators want to limit the access of different services or increase datastream priorities to a selective subset of peers. Also we assume peers want to connect to specific peers to broadcast or filter transactions (or similar action that reveals sensitive informations) and therefore they want to authenticate the remote peer and make sure that they have not connected to a MITM.

Benefits with peer authentication: * Peers could detect MITM attacks when connecting to known peers * Peers could allow resource hungry transaction filtering only to specific peers * Peers could allow access to sensitive information that can lead to node fingerprinting (fee estimation) * Peers could allow custom message types (private extensions) to authenticated peers

A simple authentication scheme based on elliptic cryptography will allow peers to identify each other and selective allow access to restricted services or reject the connection if the identity could not be verified.

== Specification ==

The authentication scheme proposed in this BIP uses ECDSA, ___secrets will never be transmitted___.

___Authentication initialization must only happen if encrypted channels have been established (according to BIP-151 [1]).___

The ___encryption-session-ID___ is available once channels are encrypted (according to BIP-151 [1]).

The identity-public-keys used for the authentication must be pre-shared over a different channel (Mail/PGP, physical paper exchange, etc.). This BIP does not cover a "trust on first use" (TOFU) concept.

The authentication state must be kept until the encryption/connection terminates.

Only one authentication process is allowed per connection. Re-authenticate require re-establishing the connection.

=== Known-peers and authorized-peers database === Each peer that supports p2p authentication must provide two users editable "databases"

# ___known-peers___ contains known identity-public-keys together with a network identifier (IP & port), similar to the "known-host" file supported by openssh. # ___authorized-peers___ contains authorized identity-public-keys

=== Local identity key management === Each peer can configure one identity-key (ECC, 32 bytes) per listening network interface (IPv4, IPv6, tor). The according identity-public-key can be shared over a different channel with other node-operators (or non-validating clients) to grant authorized access.

=== Authentication procedure === Authentication after this BIP will require both sides to authenticate. Signatures/public-keys will only be revealed if the remote peer could prove that they already know the remote identity-public-key.

# -> Requesting peer sends `AUTHCHALLENGE` (hash) # <- Responding peer sends `AUTHREPLY` (signature) # -> Requesting peer sends `AUTHPROPOSE` (hash) # <- Responding peer sends `AUTHCHALLENGE` (hash) # -> Requesting peer sends `AUTHREPLY` (signature)

For privacy reasons, dropping the connection or aborting during the authentication process must not be possible.

=== `AUTHCHALLENGE` message === A peer can send an authentication challenge to see if the responding peer can produce a valid signature with the expected responding peers identity-public-key by sending an `AUTHCHALLENGE`-message to the remote peer.

The responding peer needs to check if the hash matches the hash calculated with his own local identity-public-key. Fingerprinting the requesting peer is not possible.

32bytes challenge-hash `hash(encryption-session-ID || challenge_type ||
remote-peers-expected-identity-public-key)`

`challenge_type` is a single character. `i` if the `AUTHCHALLENGE`-message is the first, requesting challenge or `r` if it's the second, remote peers challenge message.

=== `AUTHREPLY` message === A peer must reply an `AUTHCHALLENGE`-message with an `AUTHREPLY`-message.

| 64bytes || signature || normalized comp.-signature || A signature of
the encryption-session-ID done with the identity-key

If the challenge-hash from the `AUTHCHALLENGE`-message did not match the local authentication public-key, the signature must contain 64bytes of zeros.

The requesting peer can check the responding peers identity by checking the validity of the sent signature against with the pre-shared remote peers identity-public-key.

If the signature was invalid, the requesting peer must still proceed with the authentication by sending an `AUTHPROPOSE`-message with 32 random bytes.

=== `AUTHPROPOSE` message === A peer can propose authentication of the channel by sending an `AUTHPROPOSE`-message to the remote peer.

If the signature sent in `AUTHREPLY` was invalid, the peer must still send an `AUTHPROPOSE`-message containing 32 random bytes.

The `AUTHPROPOSE` message must be answered with an `AUTHCHALLENGE`-message – even if the proposed requesting-peers identity-public-key has not been found in the authorized_peers database. In case of no match, the responding `AUTHCHALLENGE`-message must contains 32 bytes of zeros.

| 32bytes || auth-propose-hash || hash || `hash(encryption-session-ID

== Post-Authentication Re-Keying ==

After the second `AUTHREPLY` message (requesting peers signature -> responding peer), both clients must re-key the symmetric encryption according to BIP151 while using ___a slightly different re-key key derivation hash___.

They both re-key with `hash(encryption-session-ID ||
old_symmetric_cipher_key || requesting-peer-identity-public-key ||
responding-peer-identity-public-key)`

== Identity-Addresses == The peers should display/log the identity-public-key as an identity-address to the users, which is a base58-check encoded ripemd160(sha256) hash. The purpose of this is for better visual comparison (logs, accept-dialogs). The base58check identity byte is `0x0F` followed by an identity-address version number (=`0xFF01`).

An identity address would look like `TfG4ScDgysrSpodWD4Re5UtXmcLbY5CiUHA` and can be interpreted as a remote peers fingerprint.

== Compatibility ==

This proposal is backward compatible. Non-supporting peers will ignore the new `AUTH*` messages.

== Example of an auth interaction ==

Before authentication (once during peer setup or upgrade) # Requesting peer and responding peer create each an identity-keypair (standard ECC priv/pubkey) # Requesting and responding peer share the identity-public-key over a different channel (PGP mail, physical exchange, etc.) # Responding peer stores requesting peers identity-public-key in its authorized-peers database (A) # Requesting peer stores responding peers identity-public-key in its known-peers database together with its IP and port (B)

Encryption # Encrypted channels must be established (according to BIP-151 [1])

Authentication
# Requesting peer sends an `AUTHCHALLENGE` message
  AUTHCHALLENGE:
    [32 bytes, hash(encryption-session-ID || "i" ||
<remote-peers-expected-identity-public-key>)]
# Responding peer does create the same hash `(encryption-session-ID ||
"i" || <remote-peers-expected-identity-public-key>)` with its local
identity-public-key
# If the hash does not match, response with an `AUTHREPLY` message
containing 64bytes of zeros.
# In case of a match, response with an `AUTHREPLY` message
  AUTHREPLY:
    [64 bytes normalized compact ECDSA signature (H)] (sig of the
encryption-session-ID done with the identity-key)
# Requesting peer does verify the signature with the
`remote-peers-identity-public-key`
# If the signature is invalid, requesting peer answers with an
`AUTHREPLY` message containing 32 random bytes
# In case of a valid signature, requesting peer sends an `AUTHPROPOSE`
message
  AUTHPROPOSE:
    [32 bytes, hash(encryption-session-ID || "p" ||
<client-identity-public-key>)]
# Responding peer iterates over authorized-peers database (A), hashes
the identical data and looks for a match.
# If the hash does not match, responding peer answer with an
`AUTHCHALLENGE` message containing 32 bytes of zeros.
# In case of a match, responding peer sends an `AUTHCHALLENGE` message
with the hashed client public-key
  AUTHCHALLENGE:
    [32 bytes, hash(encryption-session-ID || "r" ||
<client-identity-public-key>)]
# Requesting peer sends an `AUTHREPLY` message containing 64 bytes of
zeros if server failed to authenticate
# Otherwise, response with signature in the `AUTHREPLY` message
  AUTHREPLY:
    [64 bytes normalized compact ECDSA signature (H)] (sig of the
encryption-session-ID done with the identity-key)
# Responding peer must verify the signature and can grant access to
restricted services.
# Both peers re-key the encryption after BIP151 including the
requesting-peer-identity-public-key and responding-peer-identity-public-key

== Disadvantages ==

The protocol may be slow if a peer has a large authorized-peers database due to the requirement of iterating and hashing over all available authorized peers identity-public-keys.

== Reference implementation ==

== References ==

* [1] [[bip-0151.mediawiki|BIP 151: Peer-to-Peer Communication Encryption]]

== Acknowledgements == * Gregory Maxwell and Pieter Wuille for most of the ideas in this BIP.

== Copyright == This work is placed in the public domain.

Andy Schroder in reply to Jonas Schnelli permalink original

On 08/08/2016 11:00 AM, Jonas Schnelli via bitcoin-dev wrote:

Quoted text (3 lines)
> # ___known-peers___ contains known identity-public-keys together with a
> network identifier (IP & port), similar to the "known-host" file
> supported by openssh.

I have mixed feelings about strictly tying the identity-public-keys with a network identifier. I think the purpose of this is to detect if someone has physically stolen and compromised my bitcoin node and placed it on another network under control of an attacker. This seems to be a bit of a benefit, however, an attacker could always spoof the original network identifier anyway.

I run my bitcoin node on an internet connection that does not guarantee a static IP address (although it usually stays the same for several weeks or months at a time). I'd like to be able to make secure connections back to my own node, even if I know the IP address may change from time to time. There are several reasons for wanting to this with a changing IP. The first is because the bandwidth on my internet connection with a guaranteed static IP address is considerably more expensive than my internet connection without a guaranteed static IP address. The second reason is because the DNS PTR record for my static IP address is personally identifiable based on other reasons/services. The internet connection that my bitcoin node is using without a guaranteed static IP address just has a PTR record that basically includes my IP address and ISP name. This isn't much use to the general public (although my ISP obviously knows who I am). The third reason is that I consider it a good thing from a privacy perspective if my IP address changes every once and a while.

Maybe a strict check option where the identity-public-keys must optionally match a specific network identifier would be a compromise? Maybe this is up to the client implementation to decide, so it should just be suggested in the BIP rather than required?

Quoted text (1 line)
> # ___authorized-peers___ contains authorized identity-public-keys

Is there an option for a wildcard here? Couldn't there be a case where the client wants to authenticate, but the bitcoin node does not care who it's clients are? This would be similar to many of the http based bitcoin block explorer API services that are out there. The API operators have built up some reputation, so people use them, but they don't necessarily care about who their users are.

Quoted text (3 lines)
> === Local identity key management ===
> Each peer can configure one identity-key (ECC, 32 bytes) per listening
> network interface (IPv4, IPv6, tor).

What if I have bitcoind listening on multiple IPv4 interfaces? Can I have a different identity-key for each IPv4 interface?

Also, would it be possible to only allow this authentication on specific interfaces? In my example above where I have two internet connections, if you don't agree to loosening the tie between the network identifier and the identity-public-keys, maybe I would just connect my bitcoin node to both internet connections, but only allow a few authorized-peers on the static IP (which would be low bandwidth), and then not authenticate on the internet connection with the changing IP at all

If you don't want to increase complexity by adding these options, one could always accomplish the same thing by runing two instances of bitcoind and pairing the two over a local network, it would just be a waste of resources.

Quoted text (5 lines)
> == Disadvantages ==
>
> The protocol may be slow if a peer has a large authorized-peers database
> due to the requirement of iterating and hashing over all available
> authorized peers identity-public-keys.

Does openssh have this same problem?

I'm assuming this could be parallelized very easily, so it is not a huge problem?

Gregory Maxwell in reply to Andy Schroder permalink original

On Mon, Aug 8, 2016 at 5:09 PM, Andy Schroder via bitcoin-dev <bitcoin-dev@lists•linuxfoundation•org> wrote:

Quoted text (1 line)
> I have mixed feelings about strictly tying the identity-public-keys with a

[...]

Quoted text (1 line)
> guaranteed static IP address. The second reason is because the DNS PTR

I don't see any reason that it couldn't also accept a DNS name there.

The purpose of that table is so the client knows which server ID to expect.

Quoted text (2 lines)
> I consider it a good thing from a privacy perspective if my IP address
> changes every once and a while.

And the design seeks to preserve that privacy.

Quoted text (2 lines)
> Maybe a strict check option where the identity-public-keys must optionally
> match a specific network identifier would be a compromise? Maybe this is up

The client must know the identity of the server it is expecting. The server does not announce itself. If it did then your changing of IPs would provide you with no privacy at all.

If the design is to provide any protection against MITM you need to know who you expected to connect to in any case.

Quoted text (1 line)
> I think the purpose of this is to detect if someone has physically stolen and compromised my bitcoin node and placed it on another network under control of an attacker.

Huh. No. Almost the opposite. The system is designed to inhibit fingerprinting. You can't tell what identity key(s) a node has unless you already know them. This means that if you don't publish your node pubkey, no one can use it to track your node around the network.

Quoted text (6 lines)
> Is there an option for a wildcard here? Couldn't there be a case where the
> client wants to authenticate, but the bitcoin node does not care who it's
> clients are? This would be similar to many of the http based bitcoin block
> explorer API services that are out there. The API operators have built up
> some reputation, so people use them, but they don't necessarily care about
> who their users are.

Then they're just not listed in the file. The client can ask the server to authenticate without authenticating itself.

Quoted text (1 line)
> Does openssh have this same problem?

No. OpenSSH doesn't make an effort to protect the privacy of its users.

Quoted text (2 lines)
> I'm assuming this could be parallelized very easily, so it is not a huge
> problem?

It's not a issue because we're not aware of any usecase where a node would have a large list of authenticated peers.

Quoted text (1 line)
> Each peer can configure one identity-key (ECC, 32 bytes) per listening

network interface (IPv4, IPv6, tor).

I'm not aware of any reason for this limitation to exist. A node should be able to have as many listening identities as it wants, with a similar cost to having a large authorized keys list.

Andy Schroder in reply to Gregory Maxwell permalink original

On 08/08/2016 01:42 PM, Gregory Maxwell wrote:

Quoted text (8 lines)
> On Mon, Aug 8, 2016 at 5:09 PM, Andy Schroder via bitcoin-dev
> <bitcoin-dev@lists•linuxfoundation•org> wrote:
>> I have mixed feelings about strictly tying the identity-public-keys with a
> [...]
>> guaranteed static IP address. The second reason is because the DNS PTR
> I don't see any reason that it couldn't also accept a DNS name there.
>
> The purpose of that table is so the client knows which server ID to expect.

Okay, that may be fine. You are saying otherwise you'd have to do a trial and error and this tying to a network identifier just speeds things up? If the DNS is spoofed, it's no big deal because the authentication will fail anyway?

Quoted text (10 lines)
>
>> I consider it a good thing from a privacy perspective if my IP address
>> changes every once and a while.
> And the design seeks to preserve that privacy.
>
>> Maybe a strict check option where the identity-public-keys must optionally
>> match a specific network identifier would be a compromise? Maybe this is up
> The client must know the identity of the server it is expecting. The
> server does not announce itself. If it did then your changing of IPs
> would provide you with no privacy at all.

Good point.

Quoted text (9 lines)
>
> If the design is to provide any protection against MITM you need to
> know who you expected to connect to in any case.
>
>> I think the purpose of this is to detect if someone has physically stolen and compromised my bitcoin node and placed it on another network under control of an attacker.
> Huh. No. Almost the opposite. The system is designed to inhibit
> fingerprinting. You can't tell what identity key(s) a node has unless
> you already know them. This means that if you don't publish your node
> pubkey, no one can use it to track your node around the network.

Cool.

Quoted text (9 lines)
>
>> Is there an option for a wildcard here? Couldn't there be a case where the
>> client wants to authenticate, but the bitcoin node does not care who it's
>> clients are? This would be similar to many of the http based bitcoin block
>> explorer API services that are out there. The API operators have built up
>> some reputation, so people use them, but they don't necessarily care about
>> who their users are.
> Then they're just not listed in the file. The client can ask the server to
> authenticate without authenticating itself.

Simple enough.

Quoted text (16 lines)
>
>> Does openssh have this same problem?
> No. OpenSSH doesn't make an effort to protect the privacy of its users.
>
>> I'm assuming this could be parallelized very easily, so it is not a huge
>> problem?
> It's not a issue because we're not aware of any usecase where a node
> would have a large list of authenticated peers.
>
>> Each peer can configure one identity-key (ECC, 32 bytes) per listening
> network interface (IPv4, IPv6, tor).
>
> I'm not aware of any reason for this limitation to exist. A node
> should be able to have as many listening identities as it wants, with
> a similar cost to having a large authorized keys list.
>

So you are saying that you agree with me that the original text needs to be revised slightly or I am just misinterpreting the original text?

Jonas Schnelli in reply to Andy Schroder permalink original

Hi Andy

Quoted text (19 lines)
>>
>>> Does openssh have this same problem?
>> No. OpenSSH doesn't make an effort to protect the privacy of its users.
>>
>>> I'm assuming this could be parallelized very easily, so it is not a huge
>>> problem?
>> It's not a issue because we're not aware of any usecase where a node
>> would have a large list of authenticated peers.
>>
>>> Each peer can configure one identity-key (ECC, 32 bytes) per listening
>> network interface (IPv4, IPv6, tor).
>>
>> I'm not aware of any reason for this limitation to exist. A node
>> should be able to have as many listening identities as it wants, with
>> a similar cost to having a large authorized keys list.
>>
>
> So you are saying that you agree with me that the original text needs to
> be revised slightly or I am just misinterpreting the original text?

Yes. I think this limitation could be removed. A responding node can have – in theory – multiple identity-keys per network interface (network interfaces is also confusing, because you could run multiple bitcoind instances on the same interface with different ports).

The BIP should just make clear, that it is probably wise, to use different identity-keys for each network interface (ipv4, v6, tor).

I'll try to overhaul that part.

</jonas>

Jonas Schnelli in reply to Jonas Schnelli permalink original
Quoted text (9 lines)
> Yes. I think this limitation could be removed.
> A responding node can have – in theory – multiple identity-keys per
> network interface (network interfaces is also confusing, because you
> could run multiple bitcoind instances on the same interface with
> different ports).
>
> The BIP should just make clear, that it is probably wise, to use
> different identity-keys for each network interface (ipv4, v6, tor).
>

I have updated that part of the BIP

----------- Each peer can configure multiple identity-keys (ECC, 32 bytes). Peers should make sure, each network interface (IPv4, IPv6, tor) has its own identity-key (otherwise it would be possible to link a tor address to a IPvX address). The identity-public-key(s) can be shared over a different channel with other node-operators (or non-validating clients) to grant authorized access. -----------

https://github.com/bitcoin/bips/compare/master...jonasschnelli:2016/07/auth_bip?expand=1

</jonas>