Client is the party that opens a connection. Server is the listener. Client sends AUTHCHALLENGE X1 = H(session_id || "1" || believed_server_pubkey) Server checks its list of its own auth pubkeys (probably just one) to see if it finds any that hash to X1 for this session. Server sends AUTHREPLY 64 byte signature with server_pubkey of the session ID. or 64 bytes of zeros if X1 was no hit. Client checks signature in reply sends AUTHPROPOSE: X2 = H(session_ID || "2" || client_pubkey) or random bytes if the signature failed or the client has no pubkey for this server. Server looks in its list of clients for a key matching X2. Server sends AUTHCHALLENGE X3 = H(session_id || "3" || client_pubkey) or 32 zero bytes if there was no match. Client sends AUTHREPLY 64 byte signature with client_pubkey of the session_id. or 64 zero bytes if client auth not used or the server failed to authenticate, or the server's AUTHCHALLENGE didn't match.. Then both parties rekey. The pubkeys (0, 1, or 2) are included in the rekeying hash operation. Properties: server leaks his identity only if the client proves he already knows it. otherwise server leaks nothing. Client leaks his identity only if the server proves he knows it and already successfully authenticated as the expected server. Constant amount of traffic sent in all cases (even when auth is not actually used.) Rekeying using this data means that even if ECC is broken, past communication is private so long as public keys are not published, reducing the benefit for a global observer to take the time to monitor and log this traffic. [Whole protocol could be made post-quantum pretty easily... e.g. replace the signatures with SPHINCS (with the 'pubkey' in the signature) and the pubkey hash used as the pubkey] Downsides: Protocol is kinda slow if server has _many_ client keys. I think that for our use it's fine. Server also learns which client is connecting, rather than just learning that it's one client in a set. I think this is fairly undesirable (now the server can track wallet usage-- e.g. which transactions a particular user broadcasts-- even if the user connects via TOR), though it can be avoided by just not configuring client authentication.