<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On 20 December 2015 at 10:11, Max Skibinsky <span dir="ltr"><<a href="mailto:max@skibinsky.com" target="_blank">max@skibinsky.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><div style="font-family:arial,helvetica,sans-serif;font-size:small">Our design constraints are different, so zax is build around different architecture. When there is no gossip between nodes, no mutual discovery, no pre-registration, no "central" relays - all this eliminates most of the issues you mentioned and greatly simplifies the codebase. Relay becomes very lightweight, can even be run even on Raspberry (one of the properties we wanted). Address space is global between all relays: clients can leave messages to anybody on any relay. Node discovery moves to the client layer. Any device can prove "ownership" of HPK to a relay, and collect traffic (if any) for itself from that relay: it's up to a device to make sure it checked all relays it expects traffic at. Naturally, all that at the cost of creating different tradeoffs: for example delivery becomes unreliable with bigger task load for the client device.</div></div><div style="font-family:arial,helvetica,sans-serif;font-size:small"><br></div><div style="font-family:arial,helvetica,sans-serif;font-size:small">Overall, apps using these relays should be agonistic about providers of the relays: some of can be app vendors, some can be power users themselves. App do not need to know all relays in the network, just large enough number to have high degree of confidence that messages (duplicated across relays) do reach their intended destination. </div></div></div></div></blockquote><div><br></div><div>This is great Max, thanks for sharing. <br><br></div><div>Couple of comments:<br><br></div><div>1) I'd suggest simplifying the first two interactions to the following (to minimise stored state on the server)<br></div><div>Alice does a GET to /sessions and receives {difficulty, verify_token}<br></div><div>Alice does POST to /sessions/[verify_token] with diff_nonce if needed, and receives r_sess_pk<br><br></div><div>In this situation, the client treats verify_token as an opaque byte array. On the server it will probably be implemented as concat(nonce, timestamp, difficulty, HMAC( concat(nonce, timestamp, difficulty) ). The server then just verifies the token is current, difficulty matches, MAC is correct, and it has not already been used.<br><br></div><div>This means the server doesn't store any state until after the difficulty requirement is met.<br><br></div><div>2) All of the encryption work in the second phase seems to imply you don't trust the TLS layer? Otherwise you would just send messages signed by the a_comm_pk to the server. If you really don't trust the TLS layer, you need to have the relay send a long term public key in the first message, and the client should store it and use it in key derivation (TOFU style).<br><br></div><div>3) What is the reason to use H2 instead of just a single hash iteration?<br><br></div><div>4) What is the reason to use the hash of the public key as the address?<br><br></div><div>5) Why use encryption of a secret as the ZKP of a_comm_pk? A signature would be the more conventional route.<br><br></div><div>6) I'd suggest considering also being able to use verify_token from 1 above in the upload command (maybe as a 'fast upload' command). It simplifies dumb send-only clients (don't have an HPK, may not need asymmetric crypto implementations).<br></div></div></div></div>