two clients talk end to end through a mailbox
the testbed now runs two clients that talk under an end-to-end layer, a kk handshake and a hash ratchet, through a mailbox on the last node of their chains. the mailbox holds records it cannot read, and offline deniability is shown by a forgery.
until now the last node of a chain read the message and echoed it back. now two clients talk to each other, and the last node keeps only what it cannot read. the numbers on the research page are the same preliminary series as before: they are taken on the echo topology, and the conversation of two clients does not enter them.
two clients on the testbed
the testbed runs five relays and two clients, client-a and client-b, in -peer mode. both keep
their queues on the mailbox of relay-5: client-a sends a message every 2 s and client-b
answers each. a client draws its entry at random among the other four relays, verifies the bundles
of every listed node and draws the middle hop among the verified ones; its chain ends on the
mailbox.
each client prints only the hash of its contact card at start. the card itself, the suite, the mailbox address, the queue and the static key, is served on a loopback admin port. a script takes each card through a port-forward, checks it against the hash in the log of the same container and hands it to the other client, which pins it for the life of the process. a client that is offered another card after the pin refuses it and stops until the operator restarts it.
a kk handshake and a hash ratchet
both clients know each other’s static keys from the cards before they talk, so the handshake follows the kk pattern: two records, each with a fresh ephemeral key, each mixing in agreements with the peer’s keys. after it each direction has its own key chain. every step derives the key of one record and the next chain key and wipes the previous one, so a key taken now does not open past records. every operation goes through the same crypto interface as the rest of the system, on both suites.
the relays do not open this layer: to them a record is part of the cell payload. a record the mailbox or a node changed does not open at the recipient and is dropped, and a copy or a late record changes nothing in the session.
the mailbox
the last node runs as a mailbox. it keeps queues of records in memory only and answers every request with a reply of a constant length. on every tick a client sends a request that fetches a record from its own queue; with cover puts, the default, the request also puts a record into the contact’s queue, a dummy one when no message waits, and the mailbox cannot tell a dummy from a real record.
what the mailbox still learns:
- both circuits of a conversation, linked through the queues: per circuit the fetch capability in clear, the put queue, the time of every request, the outcome of a put, the kind and number of a record and the copies of one record.
- the moment of the handshake, since before the session the puts carry handshake records only.
- with an observer of both entry links, possibly who talks to whom. how well that does is not measured yet.
a client’s exit is pinned to its mailbox, so a rogue mailbox is in every conversation of its clients.
offline deniability, shown by a forgery
the handshake is made of key agreements only and the client holds no signing key. the recipient is sure of the author, but it can compute every value of the transcript from its own keys, so it can build a transcript with the same messages, distributed like the genuine one. a transcript, even together with the recipient’s private keys, does not prove to a third party that the sender took part.
the lab shows this with the production session code. cmd/lab -set deny runs on both suites with
the recipient in both roles: the recipient forges the conversation, and the genuine and the forged
transcript pass one check and have the same structure. a forgery made with a fresh key in place of
the recipient’s fails the check at its first record. a wrapper over the crypto provider sees the
sender’s private key in the genuine session and sees it neither in the forgery nor in the check.
this is a demonstration on concrete keys, not a measurement.
the claim stops at a witnessed transcript: a mailbox or an observer of the sender’s link colluding with the recipient keeps an independent record of who sent the ciphertexts. online deniability, against a judge acting with the recipient during the session, and deniability of metadata are not claimed.
a bounded rebuild
a client in -peer mode does not exit when its circuit ends. it dials the same chain again through
the same entry, and draws new middle hops only when that chain cannot be dialled, at most twice per
process. so a rogue entry that keeps closing circuits gets at most three draws of the middle hop,
the first and two more, and past that it can only stall the conversation, which it could do anyway. the bound holds per
process: a client that cannot build a circuit for 10 min exits, and the new process is a new
identity that has to be introduced again.
how it was checked
- golden vectors of the kk handshake on both suites.
- end-to-end tests: a changed or foreign record does not open, a copy and a late record are dropped, and none of them changes the session.
- conversation tests through relays with the mailbox at the exit, and two client processes that talk through a mailbox.
- on the kind testbed: a round trip between
client-aandclient-bthroughrelay-5, and a card of a foreign key, then the previous card, refused without a restart of the client.
what is not done
- a backlog does not drain under cover puts: every tick a side misses leaves one more record of its peer in its queue, and every later record waits longer, up to the queue depth (#148).
- a record lost in a fetch reply is not put again. when it is the initiator’s first record after the handshake, the responder sends no real message until the next record of the initiator opens, and it has no way to ask for the lost one (#149).
- there is no recovery after a compromise: the ratchet has no diffie-hellman step (#136).
- the mailbox sees the kind, number and copies of a record (#137), and there is no formal model of the handshake or of the deniability claim (#138).
- one contact per process, and the identity and the pin live only in process memory: a restart means a new introduction. lasting storage comes with the client vault (#20), circuits and queues per contact are planned (#96).
- the introduction on the testbed trusts the cluster’s api (#90).
next
the client vault with two volumes (#20), the measurement topology of the end-to-end path, two entries and the mailbox (#47), and the attack blocks: key extraction from memory dumps (#24), node compromise (#117) and an active adversary with a timing watermark (#116).
the full list is on the limits page and in limitations, the layer and the deniability argument in crypto, the threats and countermeasures in the threat model.