Services/Sync/SimplifyCrypto

From MozillaWiki
< Services‎ | Sync
Jump to: navigation, search

Overview

Current situation

Right now we

  1. generate a RSA key pair
  2. generate a symmetric key from the passphrase using PBKDF2 and a random salt and encrypt ("wrap") the private key using that symmetric key
  3. upload public key, wrapped private key + IV + salt to server
  4. for each collection, generate a random symkey, encrypt it using the public key, and upload it to the server.
  5. each encrypted object contains a relative URI pointing to the key that can decrypt it (in 99.99999% percent of the case this is same, except when the WBO IDs contain slashes and clients get very confused).

Problem

We might want to drop the key URIs for encrypted payloads (specify the hard coded path for their key), but that requires another version bump (and a Firefox Home update). If we're doing _that_, then it may be worth the effort of completely dropping key wrapping. We have no intention of doing PKI-based sharing in the future, so the current key wrapping is just legacy cost we don't need. Doing a bunch of key generation makes first syncs much more painful than necessary, and isn't even enabled on Fennec.

Proposal A

  • Everything is encrypted with 1 symmetric key. This key is never uploaded.
  • The symmetric key is generated from the Sync Key using PBKDF2, taking the clientID from the meta/global record as the salt.

Proposal B

Essentially, we drop the public key layer, changing from [AES -> RSA -> AES] to [AES -> AES]:

  • The Sync Key is used to AES-decrypt one or more pairs of AES keys. These can be cached on the client, stored in the same manner as passwords: if you can steal them from there, you can steal the data directly. These AES keys are stored on the server just as bulk keys are now.
  • One of each pair of keys is used for HMAC on stored objects. The other is used to encrypt the data objects.

We don't directly use the Sync Key to encrypt objects (the really simple option) for three or more reasons:

  • We want to use different secrets for HMAC and for encryption. We can't have multiple Sync Keys, so, we need the indirection.
  • We most likely want the option to use different keys for different objects (bookmarks vs. passwords, say). Again, we need indirection.
  • It would be an even bigger code and infrastructure change.

Proposal C

  • 2+ keys on server, all AES
    • One HMAC key to rule them all (keys/hmac)
    • One default bulk key that we use for all crypto (keys/default)
    • Option to have collection-specific keys (keys/<collection>) for cases where a user wants to share a specific set of data, like bookmarks
  • One AES key on the client to decrypt the wrapped keys stored on the server. Users with existing passphrase-based keys will have these converted via PBKDF2 during migration, and we'll use the resulting key. New users will not have an option to enter weak keys, just generate new ones. Because J-PAKE transfers this key, having it be 25 characters instead of 20 is acceptable.

Pros

  1. Doing it before Firefox 4 is a lot less disruptive than doing it later
  2. Removes a bunch of legacy code which adds overhead and system complexity
  3. Eliminates the need to store keys on the server, which means less network traffic (Toby says ~16%)
  4. There isn't a separate key that needs to be cached/updated, the key can always be generated from the passphrase
  5. We are giving up PKI. Which means less complex crypto.

Cons

  1. Requires coordinating another storage bump between four clients on a tight schedule.
  2. Doing it before we drop 3.x support might mean we'd have to make this change to the binary components as well (Philipp believes this may not be the case)
  3. We are giving up PKI. I (st3fan) understand that this was done to share data with groups? Implementing this functionality later when the actual key is in direct user control will probably make this more difficult.

Security Considerations