This BIP describes a way for peers to authenticate to other peers to guarantee node ownership and/or allow peers to access additional or limited node services, without the possibility of fingerprinting.
We assume peer operators want to limit the access of different node services or increase datastream priorities to a selective subset of peers. Also we assume that peers want to connect to specific peers to broadcast or filter transactions (or similar actions that reveal sensitive information) and therefore operators want to authenticate the remote peer and ensure that they have not connected to a MITM (man-in-the-middle) attacker.
A simple authentication scheme based on elliptic cryptography will allow peers to identify each other and selectively allow access to restricted services or reject the connection if the peer identity cannot be verified.
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.
# '''known-peers''' contains known identity-public-keys together with a network identifier (IP & port), similar to the "known-host" file supported by openssh.
Each peer can configure multiple identity-keys (ECC, 32 bytes). Peers should make sure that 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).
Authentication based on this BIP will require both sides to authenticate. Signatures/public-keys will only be revealed if the remote peer can prove that they already know the remote identity-public-key.
A peer can send an authentication challenge to see if the responding peer can produce a valid signature with the expected responding peer's identity-public-key by sending an <code>AUTHCHALLENGE</code>-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.
{|class="wikitable"
! Field Size !! Description !! Data type !! Comments
<code>challenge_type</code> is a single character. <code>i</code> if the <code>AUTHCHALLENGE</code>-message is the first, requesting challenge or <code>r</code> if it's the second, remote peers challenge message.
=== <code>AUTHREPLY</code> message ===
A peer must reply an <code>AUTHCHALLENGE</code>-message with an <code>AUTHREPLY</code>-message.
{|class="wikitable"
! Field Size !! Description !! Data type !! Comments
|-
| 64bytes || signature || normalized comp.-signature || A signature of the encryption-session-ID done with the identity-key
If the challenge-hash from the <code>AUTHCHALLENGE</code>-message did not match the local authentication public-key, the signature must contain 64 bytes of zeros.
The requesting peer can check the responding peer's 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 <code>AUTHPROPOSE</code>-message with 32 random bytes.
=== <code>AUTHPROPOSE</code> message ===
A peer can propose authentication of the channel by sending an <code>AUTHPROPOSE</code>-message to the remote peer.
If the signature sent in <code>AUTHREPLY</code> was invalid, the peer must still send an <code>AUTHPROPOSE</code>-message containing 32 random bytes.
The <code>AUTHPROPOSE</code> message must be answered with an <code>AUTHCHALLENGE</code>-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 <code>AUTHCHALLENGE</code>-message must contains 32 bytes of zeros.
After the second <code>AUTHREPLY</code> message (requesting peer's signature -> responding peer), both clients must re-key the symmetric encryption according to BIP151 while using '''a slightly different re-key key derivation hash'''.
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 <code>0x0F</code> followed by an identity-address version number (=<code>0xFF01</code>).
# Responding peer does create the same hash <code>(encryption-session-ID || "i" || <remote-peers-expected-identity-public-key>)</code> with its local identity-public-key
# If the hash does not match, response with an <code>AUTHREPLY</code> message containing 64bytes of zeros.
# In case of a match, response with an <code>AUTHREPLY</code> 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 <code>remote-peers-identity-public-key</code>
# If the signature is invalid, requesting peer answers with an <code>AUTHREPLY</code> message containing 32 random bytes
# In case of a valid signature, requesting peer sends an <code>AUTHPROPOSE</code> message
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 peer identity-public-keys.