Confirmed users
385
edits
(10 intermediate revisions by the same user not shown) | |||
Line 50: | Line 50: | ||
*Desktop: Client that has Fx Sync already set up | *Desktop: Client that has Fx Sync already set up | ||
*Device: Client that needs to be set up, usually phone (of course this could be another desktop computer, too) | *Device: Client that needs to be set up, usually phone (of course this could be another desktop computer, too) | ||
*PIN: code that is displayed on | *PIN: code that is displayed on Device and entered on Desktop made up of the weak secret & the channel id. | ||
*Secret: weak secret that is used to start the J-PAKE algorithm | *Secret: weak secret that is used to start the J-PAKE algorithm | ||
*Key: strong secret that both clients derive through J-PAKE | *Key: strong secret that both clients derive through J-PAKE | ||
== Overview == | == Overview == | ||
*Device and Desktop complete the two roundtrips of J-PAKE messages to agree upon a strong secret K | |||
*A 256 bit key is derived from K using HMAC-SHA256 using a fixed extraction key. | |||
*The encryption and HMAC keys are derived from that 256 bit key using HMAC-SHA256. | |||
*In third round trip: | |||
**Device encrypts the known message "0123456789ABCDEF" with the AES key and uploads it. | |||
**Between 3 and 4 is when the user may have to create an account. There may be significant delay here. | |||
*In the 4th round trip: | |||
**Desktop verifies that against the known message encrypted with its own key, encrypts the credentials with the encryption key and uploads the encrypted credentials in turn, adding a HMAC-SHA256 hash of the ciphertext (using the HMAC key). | |||
**Device verifies whether Desktop had the right key by checking the ciphertext against the HMAC-SHA256 hash. | |||
**If that verification is successful, Device decrypts ciphertext and applies credentials, and triggers the first download to Device. | |||
<pre> | <br> | ||
Device Server Desktop | <pre>Device Server Desktop | ||
=================================================================== | =================================================================== | ||
| | | | ||
retrieve channel | retrieve channel <---------------| | ||
generate random secret | | generate random secret | | ||
show PIN = secret + channel | ask user for PIN | show PIN = secret + channel | ask user for PIN | ||
upload | upload Device's message 1 ------>| | ||
|---- | |----> retrieve Device's message 1 | ||
| | |<----- upload Desktop's message 1 | ||
retrieve Desktop's message 1 | retrieve Desktop's message 1 <---| | ||
upload | upload Device's message 2 ------>| | ||
|---- | |----> retrieve Device's message 2 | ||
| compute key | | compute key | ||
| | |<----- upload Desktop's message 2 | ||
retrieve Desktop's message 2 | retrieve Desktop's message 2 <---| | ||
compute key | | compute key | | ||
encrypt known value ------------ | encrypt known value ------------>| | ||
| verify against local known value | | verify against local known value | ||
| | |||
| Optionally create account | |||
|-------> retrieve encrypted value | |||
| encrypt credentials | | encrypt credentials | ||
| | |<------------- upload credentials | ||
retrieve credentials | retrieve credentials <-----------| | ||
verify HMAC | | verify HMAC | | ||
decrypt credentials | | decrypt credentials | ||
Device begins download | | |||
</pre> | </pre> | ||
Line 213: | Line 215: | ||
<ol> | <ol> | ||
<li> | <li>Device asks server for new channel ID (3 characters a-z0-9) | ||
<pre>C: GET /new_channel HTTP/1.1 | <pre>C: GET /new_channel HTTP/1.1 | ||
S: "a7id"</pre></li> | S: "a7id"</pre></li> | ||
<li> | <li>Device generates PIN from random weak secret (4 characters a-z0-9) and the channel ID, computes and uploads J-PAKE msg 1.To prevent double uploads in case of retries, the If-None-Match: * header is specified. This makes sure that the message is only uploaded if the channel is empty. If it is not then the request will fail with a 412 Precondition Failed which should be considered the same as 200 OK. The 412 will also contain the Etag of the data was the client just uploaded. | ||
<b>New in version 3:</b> Timeouts will need to be increased to accommodate the case where users have to create an account on the Desktop before proceeding. | |||
<pre> | <pre> | ||
C: PUT /a7id HTTP/1.1 | C: PUT /a7id HTTP/1.1 | ||
Line 255: | Line 256: | ||
S: ETag: "etag-of-receiver1-message" | S: ETag: "etag-of-receiver1-message" | ||
</pre></li> | </pre></li> | ||
<li>Desktop asks user for the PIN, extracts channel ID and weak secret, fetches | <li>Desktop asks user for the PIN, extracts channel ID and weak secret, fetches Devce's msg 1 | ||
<pre> | <pre> | ||
C: GET /a7id HTTP/1.1 | C: GET /a7id HTTP/1.1 | ||
Line 267: | Line 268: | ||
</pre></li> | </pre></li> | ||
<li>Desktop computes and uploads msg 1. | <li>Desktop computes and uploads msg 1. The If-Match header is set so that we only upload this message if the other side's previous message is still in the channel. This is to prevent double PUTs during retries. If a 412 is received then it means that our first PUT was actually correctly received by the server and that the other side has already uploaded it's next message. So just consider the 412 to be a 200. | ||
<pre> | <pre> | ||
C: PUT /a7id HTTP/1.1 | C: PUT /a7id HTTP/1.1 | ||
Line 304: | Line 303: | ||
S: Etag: "etag-of-sender1-message" | S: Etag: "etag-of-sender1-message" | ||
</pre></li> | </pre></li> | ||
<li> | <li>Device polls for Desktop's msg 1 | ||
<pre> | <pre> | ||
C: GET /a7id HTTP/1.1 | C: GET /a7id HTTP/1.1 | ||
Line 311: | Line 310: | ||
S: HTTP/1.1 304 Not Modified | S: HTTP/1.1 304 Not Modified | ||
</pre> | </pre> | ||
<p> | <p>Device tries again after 1s</p> | ||
<pre> | <pre> | ||
C: GET /a7id HTTP/1.1 | C: GET /a7id HTTP/1.1 | ||
Line 319: | Line 318: | ||
... | ... | ||
</pre> | </pre> | ||
<p> | <p>Device computes and uploads msg 2. The If-Match header is set so that we only upload this message if the other side's previous message is still in the channel. This is to prevent double PUTs during retries. If a 412 is received then it means that our first PUT was actually correctly received by the server and that the other side has already uploaded it's next message. So just consider the 412 to be a 200. | ||
</p> | </p> | ||
<pre>C: PUT /a7id HTTP/1.1 | <pre>C: PUT /a7id HTTP/1.1 | ||
Line 344: | Line 341: | ||
S: ETag: "etag-of-receiver2-message" | S: ETag: "etag-of-receiver2-message" | ||
</pre></li> | </pre></li> | ||
<li>Desktop polls for and eventually retrieves | <li>Desktop polls for and eventually retrieves Device's msg 2 | ||
<pre> | <pre> | ||
C: GET /a7id HTTP/1.1 | C: GET /a7id HTTP/1.1 | ||
Line 357: | Line 354: | ||
... | ... | ||
</pre> | </pre> | ||
<p>Desktop computes key, computes and uploads msg 2. | <p>Desktop computes key, computes and uploads msg 2. The If-Match header is set so that we only upload this message if the other side's previous message is still in the channel. This is to prevent double PUTs during retries. If a 412 is received then it means that our first PUT was actually correctly received by the server and that the other side has already uploaded it's next message. So just consider the 412 to be a 200. | ||
</p> | </p> | ||
<pre> | <pre> | ||
Line 384: | Line 379: | ||
</pre></li> | </pre></li> | ||
<li> | <li>Device retrieves Desktop's msg 2 | ||
<pre> | <pre> | ||
C: GET /a7id HTTP/1.1 | C: GET /a7id HTTP/1.1 | ||
Line 396: | Line 391: | ||
S: Etag: "etag-of-sender2-message" | S: Etag: "etag-of-sender2-message" | ||
</pre> | </pre> | ||
<p> | <p>Device uploads encrypted known message "0123456789ABCDEF" to prove its knowledge (msg 3). | ||
<b>New in version 3:</b>No longer includes the key, just the known message. | |||
<b>New in version | The If-Match header is set so that we only upload this message if the other side's previous message is still in the channel. This is to prevent double PUTs during retries. If a 412 is received then it means that our first PUT was actually correctly received by the server and that the other side has already uploaded it's next message. So just consider the 412 to be a 200. | ||
</p> | </p> | ||
<pre> | <pre> | ||
Line 407: | Line 402: | ||
C: 'type': 'receiver3', | C: 'type': 'receiver3', | ||
C: 'payload': { | C: 'payload': { | ||
C: 'IV': "base64encoded=", | C: 'IV': "base64encoded=", | ||
C: } | C: } | ||
Line 420: | Line 414: | ||
</li> | </li> | ||
<li>Desktop retrieves | <li>Desktop retrieves Device's msg 3 to confirm connection. <b>new in version 3</b> No longer includes encrypted key. That will come in the 4th exchange once account creation has happened if needed and first sync upload has occurred. | ||
<pre> | <pre> | ||
C: GET /a7id HTTP/1.1 | C: GET /a7id HTTP/1.1 | ||
Line 429: | Line 423: | ||
... | ... | ||
</pre> | </pre> | ||
Desktop verifies it against its own version. If the hash matches, it encrypts and uploads Sync credentials. | Desktop verifies it against its own version. If the hash matches, it acquires (either the existing account or by creating a new one), then encrypts and uploads Sync credentials. | ||
The If-Match header is set so that we only upload this message if the other side's previous message is still in the channel. This is to prevent double PUTs during retries. If a 412 is received then it means that our first PUT was actually correctly received by the server and that the other side has already uploaded it's next message. So just consider the 412 to be a 200. | |||
<pre> | <pre> | ||
Line 440: | Line 434: | ||
C: 'type': 'sender3', | C: 'type': 'sender3', | ||
C: 'payload': { | C: 'payload': { | ||
C: 'IV': "base64encoded=", | C: 'IV': "base64encoded=", | ||
C: 'hmac': "base64encoded=", | C: 'hmac': "base64encoded=", | ||
C: } | C: } | ||
C: } | C: } | ||
S: HTTP/1.1 200 OK | S: HTTP/1.1 200 OK | ||
Line 460: | Line 452: | ||
... | ... | ||
</pre> | </pre> | ||
This means that | This means that Device will receive a 404 when it tries to retrieve the encrypted credentials. | ||
</li></li> | </li></li> | ||
<li> | </li> | ||
<li><b>New in version 3:</b> Desktop signals that uploading sync has finished by encrypting and sending over the key. This is the 4th and last exchange. | |||
<pre> | |||
C: PUT /a7id HTTP/1.1 | |||
C: If-Match: "etag-of-receiver4-message" | |||
C: | |||
C: { | |||
C: 'type': 'sender4', | |||
C: 'payload': { | |||
C: 'ciphertext': "base64encoded=", | |||
C: } | |||
C: } | |||
Success response: | |||
S: HTTP/1.1 200 OK | |||
S: ETag: "etag-of-receiver4-message" | |||
</pre> | |||
</li> | |||
<li><b>New in version 3:</b> Device retrieves encrypted key, decrypts it, starts downloading. Device kills session if HMAC does not match. | |||
<pre> | |||
C: GET /a7id HTTP/1.1 | |||
C: If-None-Match: "etag-of-receiver4-message" | |||
</pre> | |||
<li>Device retrieves encrypted credentials | |||
<pre> | <pre> | ||
C: GET /a7id HTTP/1.1 | C: GET /a7id HTTP/1.1 | ||
C: If-None-Match: "etag-of- | C: If-None-Match: "etag-of-receiver4-message" | ||
S: HTTP/1.1 200 OK | S: HTTP/1.1 200 OK | ||
Line 472: | Line 487: | ||
</pre> | </pre> | ||
<p>decrypts Sync credentials and verifies HMAC.</p></li> | <p>decrypts Sync credentials and verifies HMAC.</p></li> | ||
<pre> | <pre> | ||
C: DELETE /a7id HTTP/1.1 | C: DELETE /a7id HTTP/1.1 |