canmove, Confirmed users
640
edits
(Updates.) |
|||
(5 intermediate revisions by 3 users not shown) | |||
Line 36: | Line 36: | ||
The length of this key is not a big issue: we intend to use J-PAKE for the (infrequent) migration of keys between devices. In any case, 26 is not significantly worse than 20 if typing it does enter the picture, and the use of a nice base32 alphabet makes keyboard entry less error-prone. | The length of this key is not a big issue: we intend to use J-PAKE for the (infrequent) migration of keys between devices. In any case, 26 is not significantly worse than 20 if typing it does enter the picture, and the use of a nice base32 alphabet makes keyboard entry less error-prone. | ||
As before, the | As before, the Sync Key is stored on the client. The encryption and hmac keys are derived from it. | ||
==== Deriving encryption and HMAC keys from the Sync Key ==== | |||
First we base32-decode the syncKey from 26 characters to 16 bytes (128 bits). The base32 alphabet is the one specified in [http://tools.ietf.org/html/rfc4648 RFC 4648] except with '''l''' replaced by '''8''' and '''o''' replaced by '''9''': | |||
prk = decodeKeyBase32(syncKey) | |||
The resulting key is then expanded to an encryption key T(1) and HMAC key T(2) using the algorithm described in [http://tools.ietf.org/html/rfc5869 RFC 5869] | |||
info = "Sync-AES_256_CBC-HMAC256" + username | |||
T(1) = HMAC-SHA256(prk, "" + info + 0x01) | |||
T(2) = HMAC-SHA256(prk, T(1) + info + 0x02) | |||
==== Upgrading existing Sync Keys to the new AES key ==== | |||
Existing users will have their passphrase bootstrapped into an AES key using PBKDF2: | Existing users will have their passphrase bootstrapped into an AES key using PBKDF2: | ||
* Spot old version | * Spot old version | ||
* Get a salt (Services.syncID from the meta/global object. The client will be bumping this…) | * Get a salt ([[Labs/Weave/Developer/StorageFormat#Payload:_meta.2Fglobal|Services.syncID]] from the meta/global object. The client will be bumping this…) | ||
* Apply PBKDF2 to salt and passphrase to yield our new AES key | * Apply PBKDF2 to salt and passphrase to yield our new AES key | ||
* Generate bulk keys, encrypt | * Generate bulk keys, encrypt | ||
* Attempt to store, using appropriate race-avoidance technique in case there are multiple clients attempting to upgrade. | * Attempt to store, using appropriate race-avoidance technique in case there are multiple clients attempting to upgrade. | ||
* Wipe old key data. | * Wipe old key data. | ||
-- Note that we leave key data in pubkey/privkey, because earlier versions of Sync unfortunately check for these prior to checking storage version. We opted to leave the keys there to get better user experience when an upgrade is needed. | |||
So long as the salt is available, other clients can apply PBKDF2 to their stored passphrase and the salt to yield the new key without any re-entry or J-PAKE-style key distribution. | So long as the salt is available, other clients can apply PBKDF2 to their stored passphrase and the salt to yield the new key without any re-entry or [[Services/Sync/SyncKey/J-PAKE|J-PAKE]]-style key distribution. | ||
Note that each major storage change alters the syncID, and thus PBKDF2 will only work for a single such change -- afterwards, one's passphrase is upgraded into a different sync key, and that won't work. | |||
=== Bulk keys === | |||
The server stores one or more bulk keys: one default, and an optional set of keys associated with specific collections. This will allow rudimentary sharing scenarios (provide your bookmarks collection key to a web app, and your passwords remain secure). A default key is simpler than having per-engine/collection keys without an obvious need. | |||
Bulk keys are stored in the single WBO storage/crypto/keys. | |||
Bulk keys are encrypted and HMACed using the sync key outputs, and cached on the client. (Current caching is per-session, but they're stored as identities to make persistence easier to implement.) | Bulk keys are encrypted and HMACed using the sync key outputs, and cached on the client. (Current caching is per-session, but they're stored as identities to make persistence easier to implement.) | ||
The timestamp on the collections record allows clients to invalidate their key cache when a new key is associated with a collection: the ' | The timestamp on the collections record allows clients to invalidate their key cache when a new key is associated with a collection: the 'crypto' collection will appear to have changed. | ||
=== HMAC === | === HMAC === | ||
Line 115: | Line 107: | ||
This change is incompatible with older clients: not only due to reorganizing the storage namespace, but also because existing clients will be unaware of the simpler encryption mechanism. That means a storage version bump (from 3 to 4). | This change is incompatible with older clients: not only due to reorganizing the storage namespace, but also because existing clients will be unaware of the simpler encryption mechanism. That means a storage version bump (from 3 to 4). | ||
An error in the argument order of the PBKDF2 function necessitated another version bump, from 4 to 5. Only a small set of nightly builds and add-ons used version 4; these will all prompt to upgrade on launch if a v5 storage version is found on the server. |