Services/Sync/SimplifiedCrypto: Difference between revisions

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 sync key is stored on the client.
As before, the Sync Key is stored on the client. The encryption and hmac keys are derived from it.


Existing users will have their passphrase bootstrapped into an AES key using PBKDF2:
==== Deriving encryption and HMAC keys from the Sync Key ====
 
* Spot old version
* Get a salt (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
* Generate bulk keys, encrypt
* Attempt to store, using appropriate race-avoidance technique in case there are multiple clients attempting to upgrade.
* Wipe old key data.
 
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.


A known fixed string (which includes encryption algo details) and the username are used as input to SHA256-HMAC. The hash operations are chained.
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''':


       let m = Utils.decodeKeyBase32(syncKey);
       let m = Utils.decodeKeyBase32(syncKey);
The resulting key is then expanded to an encryption and HMAC key using the algorithm described in [http://tools.ietf.org/html/rfc5869 RFC 5869]
        
        
       // Reuse the hasher.
       // Reuse the hasher.
Line 64: Line 57:
       let k2 = Utils.makeHMACKey(enc + HMAC_INPUT + u + "\x02");
       let k2 = Utils.makeHMACKey(enc + HMAC_INPUT + u + "\x02");
       let hmac = Utils.sha256HMACBytes(m, k2, h);
       let hmac = Utils.sha256HMACBytes(m, k2, h);
     
      // Save them.
      this._encrypt = btoa(enc);    // WeaveCrypto expects base64
      this._hmac    = hmac;


enc and hmac are the 256 bit encryption and HMAC keys, respectively.
==== Upgrading existing Sync Keys to the new AES key ====
Existing users will have their passphrase bootstrapped into an AES key using PBKDF2:


The outputs are then used during the key encryption process.
* Spot old version
* Get a salt (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
* Generate bulk keys, encrypt
* Attempt to store, using appropriate race-avoidance technique in case there are multiple clients attempting to upgrade.
* Wipe old key data.
 
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.


=== Bulk keys ===
=== Bulk keys ===
canmove, Confirmed users
725

edits