Voucher Design
In order to join or initiate a conversation, participants need to exchange cryptographic key material. To address this problem we have a slightly unusual design: Contact vouchers.
In many systems, invites to conversations flow from an existing member of the conversation to the user being invited. In our “Contact Voucher” protocol this flow is reversed: A member wishing to join a conversation hands a “Contact Voucher” (out of band) to the existing member, who then inducts the new member into the group.
This design mitigates two potential problem with the former way of doing it:
- If the Contact Voucher is observed by a third-party, the third-party does not get to read neither participants’ actual messages.
- Passive adversaries learn that the voucher was spent, but do not get to observe further interactions.
- Active adversaries can create a new fake group to induct the member into but does not learn anything about the existing group.
- In the future to prevent this one-way impersonation we could allow a “both parties bring something on paper to the meeting”:
- Bob brings Contact Voucher
- Alice brings fingerprint for the VoucherReplyPublicKey (thwarts the active attacker)
- In the future to prevent this one-way impersonation we could allow a “both parties bring something on paper to the meeting”:
- Only one thing needs to delivered out of band to achieve a 2-pass protocol (instead of a 3-pass protocol).
- Only one of the parties need to bring key material to a meeting in order to establish contact.
sequenceDiagram
actor Bob
participant VoucherSeq@{ "type" : "database" }
actor Alice
Bob-->>+Bob: Generates VoucherKeypair. <br>Generates BACAP write/read cap.<br>VoucherPayload := read cap || VoucherPublicKey<br>Voucher := Hash(VoucherPayload)
Bob->>+VoucherSeq: Publish: VoucherPayload
Bob-->>Alice: [Sent OOB] Voucher
Alice-->>+Alice: Derive VoucherSeq read/write caps from Voucher.<br>Read the first box in VoucherSeq
VoucherSeq->>+Alice: VoucherPayload
Alice-->>+Alice: VoucherReply := Encrypt(WhoReply + VoucherSalt)<br> to VoucherPublicKey<br><br>Derive Bob's ReadCap from<br>VoucherPayload + VoucherSalt
par_over All-Or-Nothing using COPY service
Alice->>+VoucherSeq: VoucherReply
Alice->>+Alice's Group: WhoReply<br>(incl. Bob's new ReadCap)
Alice->>+VoucherSeq: Tombstone VoucherPayload<br>to prevent Voucher reuse
end
Bob-->>+Bob: Poll the second VoucherSeq box until Alice replies
VoucherSeq->>+Bob: VoucherReply
Self-authenticating BACAP payload
The first message sent (The VoucherPayload) is authenticated in the following manner:
- The VoucherPayload is computed (first).
- A cryptographic hash of the VoucherPayload is computed. This hash is the Voucher*.
- The Voucher is then used to derive a BACAP read/write capability set.
- The VoucherPayload is uploaded to the sequence described by the capability (at index 0).
- Anyone who intercepts the Voucher can read and write the sequence.
- But: Since the Voucher is a hash over the VoucherPayload, writing the sequence with anything but the VoucherPayload will be detectable by the recipient.
- This means that the contents cannot be undetectably be modified by the interceptor.