<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.mozilla.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=MarcusWolschon</id>
	<title>MozillaWiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.mozilla.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=MarcusWolschon"/>
	<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/Special:Contributions/MarcusWolschon"/>
	<updated>2026-08-03T12:19:33Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.10</generator>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Talk:Service/Sync/FxSync/Developer/BrowserObjects&amp;diff=276259</id>
		<title>Talk:Service/Sync/FxSync/Developer/BrowserObjects</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Talk:Service/Sync/FxSync/Developer/BrowserObjects&amp;diff=276259"/>
		<updated>2011-01-07T07:00:03Z</updated>

		<summary type="html">&lt;p&gt;MarcusWolschon: deleted bookmarks&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== deleted bookmarks ==&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;type&amp;quot; value of deleted bookmarks is changed into &amp;quot;item&amp;quot; by at least some Firefox versions.&lt;br /&gt;
I did not test if that happens to folders, livemarks,... too. --[[User:MarcusWolschon|MarcusWolschon]] 23:00, 6 January 2011 (PST)&lt;/div&gt;</summary>
		<author><name>MarcusWolschon</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/SimplifiedCrypto&amp;diff=271835</id>
		<title>Talk:Services/Sync/SimplifiedCrypto</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/SimplifiedCrypto&amp;diff=271835"/>
		<updated>2010-12-04T10:58:41Z</updated>

		<summary type="html">&lt;p&gt;MarcusWolschon: /* Deriving encryption and HMAC keys from the Sync Key */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== sync key representation ==&lt;br /&gt;
&lt;br /&gt;
The sync key is represented to the user as:&lt;br /&gt;
&lt;br /&gt;
X-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX&lt;br /&gt;
&lt;br /&gt;
== Deriving encryption and HMAC keys from the Sync Key  ==&lt;br /&gt;
&lt;br /&gt;
The hmac used is an SHA-256 HMAC.&amp;lt;br/&amp;gt;&lt;br /&gt;
* Sourcecode of [http://hg.mozilla.org/services/fx-sync/file/12189166cd01/services/sync/modules/util.js#l571 Utils.makeHMACKey()] Sorry, it&#039;s a native method.&lt;br /&gt;
&lt;br /&gt;
* What is the value of HMAC_INPUT?&lt;br /&gt;
** [http://hg.mozilla.org/services/fx-sync/file/37150bc0bf62/services/sync/modules/constants.js source]&lt;br /&gt;
** it is the string &amp;quot;Sync-AES_256_CBC-HMAC256&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* what is enc + HMAC_INPUT + u + &amp;quot;\x02&amp;quot;? (enc is a byte array, the others are strings)&lt;br /&gt;
* \x?? = &amp;quot;The Latin-1 character specified by the two hexadecimal digits dd between 00 and FF.  ie, copyright symbol is \xA9.&amp;quot;&lt;br /&gt;
** \x01 = SOH = \u0001 in unicode&lt;br /&gt;
&lt;br /&gt;
== Upgrading existing Sync Keys to the new AES key  ==&lt;br /&gt;
PBKDF2 iteration count it 4096, key length 128 bit.&amp;lt;br/&amp;gt;&lt;br /&gt;
Keep in mind that while everywhere else Base64 is used, this is Base32.&lt;br /&gt;
&lt;br /&gt;
Example (Java):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	/**&lt;br /&gt;
	 * See https://wiki.mozilla.org/Services/Sync/SimplifiedCrypto#Upgrading_existing_Sync_Keys_to_the_new_AES_key&lt;br /&gt;
	 * for details on the algorithm.&lt;br /&gt;
	 * @param aV3Passphrase&lt;br /&gt;
	 * @return the v4 syncKey (serves the same purpose as the passphrase before)&lt;br /&gt;
	 * @throws Exception see {@link #passwordToSymmetricKey(char[], byte[])}&lt;br /&gt;
	 * @throws UnsupportedEncodingException should not happen (ASCII) &lt;br /&gt;
	 */&lt;br /&gt;
	public String upgradeV3PassphraseToV4SyncKey(final String aV3Passphrase) throws UnsupportedEncodingException, Exception {&lt;br /&gt;
		String salt = mSyncID;&lt;br /&gt;
		KeySpec ks = new PBEKeySpec(aV3Passphrase.toCharArray(), salt.getBytes(&amp;quot;ASCII&amp;quot;), 4096, 128);&lt;br /&gt;
		PBKDF2HmacSHA1Factory f = new PBKDF2HmacSHA1Factory();&lt;br /&gt;
		SecretKey s = f.engineGenerateSecret(ks);&lt;br /&gt;
        &lt;br /&gt;
		String base32 = biz.wolschon.android.codec.binary.Base32.encode(s.getEncoded()).toLowerCase();&lt;br /&gt;
		String syncKey = base32.replace(&#039;l&#039;, &#039;8&#039;).replace(&#039;o&#039;, &#039;9&#039;);&lt;br /&gt;
&lt;br /&gt;
		syncKey = syncKey.charAt(0)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(1, 6)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(6, 11)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(11, 16)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(16, 21)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(21, 26);&lt;br /&gt;
		Log.d(LOG_TAG, &amp;quot;upgraded passphrase to syncKey \&amp;quot;&amp;quot; + syncKey + &amp;quot;\&amp;quot;&amp;quot;);&lt;br /&gt;
		return syncKey;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>MarcusWolschon</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/SimplifiedCrypto&amp;diff=271834</id>
		<title>Talk:Services/Sync/SimplifiedCrypto</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/SimplifiedCrypto&amp;diff=271834"/>
		<updated>2010-12-04T10:54:39Z</updated>

		<summary type="html">&lt;p&gt;MarcusWolschon: /* Deriving encryption and HMAC keys from the Sync Key */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== sync key representation ==&lt;br /&gt;
&lt;br /&gt;
The sync key is represented to the user as:&lt;br /&gt;
&lt;br /&gt;
X-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX&lt;br /&gt;
&lt;br /&gt;
== Deriving encryption and HMAC keys from the Sync Key  ==&lt;br /&gt;
&lt;br /&gt;
The hmac used is an SHA-256 HMAC.&amp;lt;br/&amp;gt;&lt;br /&gt;
* Sourcecode of [http://hg.mozilla.org/services/fx-sync/file/12189166cd01/services/sync/modules/util.js#l571 Utils.makeHMACKey()] Sorry, it&#039;s a native method.&lt;br /&gt;
&lt;br /&gt;
* What is the value of HMAC_INPUT?&lt;br /&gt;
** [http://hg.mozilla.org/services/fx-sync/file/37150bc0bf62/services/sync/modules/constants.js source]&lt;br /&gt;
** it is the string &amp;quot;Sync-AES_256_CBC-HMAC256&amp;quot;&lt;br /&gt;
* what is enc + HMAC_INPUT + u + &amp;quot;\x02&amp;quot;? (enc is a byte array, the others are strings)&lt;br /&gt;
* \x?? = &amp;quot;The Latin-1 character specified by the two hexadecimal digits dd between 00 and FF.  ie, copyright symbol is \xA9.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Upgrading existing Sync Keys to the new AES key  ==&lt;br /&gt;
PBKDF2 iteration count it 4096, key length 128 bit.&amp;lt;br/&amp;gt;&lt;br /&gt;
Keep in mind that while everywhere else Base64 is used, this is Base32.&lt;br /&gt;
&lt;br /&gt;
Example (Java):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	/**&lt;br /&gt;
	 * See https://wiki.mozilla.org/Services/Sync/SimplifiedCrypto#Upgrading_existing_Sync_Keys_to_the_new_AES_key&lt;br /&gt;
	 * for details on the algorithm.&lt;br /&gt;
	 * @param aV3Passphrase&lt;br /&gt;
	 * @return the v4 syncKey (serves the same purpose as the passphrase before)&lt;br /&gt;
	 * @throws Exception see {@link #passwordToSymmetricKey(char[], byte[])}&lt;br /&gt;
	 * @throws UnsupportedEncodingException should not happen (ASCII) &lt;br /&gt;
	 */&lt;br /&gt;
	public String upgradeV3PassphraseToV4SyncKey(final String aV3Passphrase) throws UnsupportedEncodingException, Exception {&lt;br /&gt;
		String salt = mSyncID;&lt;br /&gt;
		KeySpec ks = new PBEKeySpec(aV3Passphrase.toCharArray(), salt.getBytes(&amp;quot;ASCII&amp;quot;), 4096, 128);&lt;br /&gt;
		PBKDF2HmacSHA1Factory f = new PBKDF2HmacSHA1Factory();&lt;br /&gt;
		SecretKey s = f.engineGenerateSecret(ks);&lt;br /&gt;
        &lt;br /&gt;
		String base32 = biz.wolschon.android.codec.binary.Base32.encode(s.getEncoded()).toLowerCase();&lt;br /&gt;
		String syncKey = base32.replace(&#039;l&#039;, &#039;8&#039;).replace(&#039;o&#039;, &#039;9&#039;);&lt;br /&gt;
&lt;br /&gt;
		syncKey = syncKey.charAt(0)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(1, 6)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(6, 11)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(11, 16)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(16, 21)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(21, 26);&lt;br /&gt;
		Log.d(LOG_TAG, &amp;quot;upgraded passphrase to syncKey \&amp;quot;&amp;quot; + syncKey + &amp;quot;\&amp;quot;&amp;quot;);&lt;br /&gt;
		return syncKey;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>MarcusWolschon</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Services/Sync/SimplifiedCrypto&amp;diff=271833</id>
		<title>Services/Sync/SimplifiedCrypto</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Services/Sync/SimplifiedCrypto&amp;diff=271833"/>
		<updated>2010-12-04T10:49:12Z</updated>

		<summary type="html">&lt;p&gt;MarcusWolschon: /* Deriving encryption and HMAC keys from the Sync Key */ added missing value for HMAC_INPUT&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== The current state of Sync crypto ==&lt;br /&gt;
&lt;br /&gt;
See [[Labs/Weave/Developer/Crypto]] for thorough details.&lt;br /&gt;
&lt;br /&gt;
In short:&lt;br /&gt;
&lt;br /&gt;
* Generate a RSA key pair&lt;br /&gt;
* Generate a symmetric key from the passphrase, using PBKDF2 and a random salt, and encrypt (&amp;quot;wrap&amp;quot;) the private key using that symmetric key&lt;br /&gt;
* Upload public key, wrapped private key + IV + salt to server&lt;br /&gt;
* For each collection, generate a random symkey, encrypt it using the public key, and upload it to the server.&lt;br /&gt;
* 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).&lt;br /&gt;
* Fetching a decrypted object involves:&lt;br /&gt;
** Fetching the encrypted object from the server&lt;br /&gt;
** Looking at the key URI in that JSON blob to find the symkey URI&lt;br /&gt;
** Fetching (if necessary) from the server and RSA-decrypting the symkey&lt;br /&gt;
** Using the symkey to AES-decrypt the object.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Goal and motivation ==&lt;br /&gt;
&lt;br /&gt;
We want to drop the PKI layer. We don&#039;t use it (for the original speculative sharing scenarios), and it costs client computation, server storage, and network bandwidth (~ 16% of our API transactions are key fetches).&lt;br /&gt;
&lt;br /&gt;
== Proposal ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tl;dr&#039;&#039;&#039;: replace the passphrase with an AES key, which will be schlepped around using J-PAKE (so typing it is likely unnecessary). Use this key to indirectly encrypt the &#039;bulk&#039; symkeys. No RSA involved.&lt;br /&gt;
&lt;br /&gt;
Existing passphrases will be upgraded to this scheme using PBKDF2.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Passphrase / Sync Key ===&lt;br /&gt;
&lt;br /&gt;
Rather than have a user enter a passphrase (which will likely be weak), we have already transitioned to having them generate a &amp;quot;sync key&amp;quot; (which they can replace if they so choose). This is 20 alphanumeric characters.&lt;br /&gt;
&lt;br /&gt;
We propose to expand this to 26 characters, enough for a base32-encoded 128-bit AES key. This avoids the use of PBKDF2 to routinely bootstrap the sync key into an AES key. Remove the ability for users to enter a key; it&#039;s always generated (giving us more confidence in the amount of entropy), and can be regenerated if desired.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
As before, the Sync Key is stored on the client. The encryption and hmac keys are derived from it.&lt;br /&gt;
&lt;br /&gt;
==== Deriving encryption and HMAC keys from the Sync Key ====&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;l&#039;&#039;&#039; replaced by &#039;&#039;&#039;8&#039;&#039;&#039; and &#039;&#039;&#039;o&#039;&#039;&#039; replaced by &#039;&#039;&#039;9&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
      let m = Utils.decodeKeyBase32(syncKey);&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
      &lt;br /&gt;
      // Our extra input to SHA256-HMAC in generateEntry &lt;br /&gt;
      // This includes the full crypto spec; change this when our algo changes.&lt;br /&gt;
      HMAC_INPUT: &amp;quot;Sync-AES_256_CBC-HMAC256&amp;quot;,&lt;br /&gt;
 &lt;br /&gt;
      // Reuse the hasher.&lt;br /&gt;
      let h = Utils.makeHMACHasher();&lt;br /&gt;
      &lt;br /&gt;
      // First key.&lt;br /&gt;
      let u = this.username; &lt;br /&gt;
      let k1 = Utils.makeHMACKey(&amp;quot;&amp;quot; + HMAC_INPUT + u + &amp;quot;\x01&amp;quot;);&lt;br /&gt;
      let enc = Utils.sha256HMACBytes(m, k1, h);&lt;br /&gt;
      &lt;br /&gt;
      // Second key: depends on the output of the first run.&lt;br /&gt;
      let k2 = Utils.makeHMACKey(enc + HMAC_INPUT + u + &amp;quot;\x02&amp;quot;);&lt;br /&gt;
      let hmac = Utils.sha256HMACBytes(m, k2, h);&lt;br /&gt;
&lt;br /&gt;
enc and hmac are the 256 bit encryption and HMAC keys, respectively.&lt;br /&gt;
&lt;br /&gt;
==== Upgrading existing Sync Keys to the new AES key ====&lt;br /&gt;
&lt;br /&gt;
Existing users will have their passphrase bootstrapped into an AES key using PBKDF2:&lt;br /&gt;
&lt;br /&gt;
* Spot old version&lt;br /&gt;
* Get a salt ([[Labs/Weave/Developer/StorageFormat#Payload:_meta.2Fglobal|Services.syncID]] from the meta/global object. The client will be bumping this…)&lt;br /&gt;
* Apply PBKDF2 to salt and passphrase to yield our new AES key&lt;br /&gt;
* Generate bulk keys, encrypt&lt;br /&gt;
* Attempt to store, using appropriate race-avoidance technique in case there are multiple clients attempting to upgrade.&lt;br /&gt;
* Wipe old key data.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
=== Bulk keys ===&lt;br /&gt;
&lt;br /&gt;
The server stores one or more bulk keys: one default (&amp;quot;keys/default&amp;quot;), 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.&lt;br /&gt;
&lt;br /&gt;
Bulk keys are encrypted and HMACed using the sync key outputs, and cached on the client. (Current caching is per-session, but they&#039;re stored as identities to make persistence easier to implement.)&lt;br /&gt;
&lt;br /&gt;
The timestamp on the collections record allows clients to invalidate their key cache when a new key is associated with a collection: the &#039;keys&#039; collection will appear to have changed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Discussion topic&#039;&#039;&#039;: do we need to preserve (add?) the ability to do per-object encryption? Brian Warner suggested:&lt;br /&gt;
&lt;br /&gt;
:: While not really interesting here, this one-way property is really useful in other situations, like if you derived per-object encryption keys from a parent folder&#039;s key. You could then share the whole thing with someone by giving them the parent&#039;s key, or share just one object and *not* give them the ability to get at anything else in that folder. But the sharing discussion is for another day..&lt;br /&gt;
&lt;br /&gt;
=== HMAC ===&lt;br /&gt;
&lt;br /&gt;
It&#039;s a good practice to use separate keys for HMAC and for encryption. Bulk keys are really pairs of keys, each of which is randomly generated.&lt;br /&gt;
&lt;br /&gt;
This approach was selected over having a single HMAC key because of the convenience for implementing some sharing-like scenarios.&lt;br /&gt;
&lt;br /&gt;
== Proposed flows ==&lt;br /&gt;
&lt;br /&gt;
=== New user ===&lt;br /&gt;
&lt;br /&gt;
* Generate a 128-bit Sync key (25 characters in base36). Store it as an Identity (as we do now.)&lt;br /&gt;
* Generate a random default key and HMAC. Encrypt it with the sync key, upload it to the server. Store it as an Identity.&lt;br /&gt;
* Encrypt and upload collections in the obvious way.&lt;br /&gt;
&lt;br /&gt;
=== Existing user ===&lt;br /&gt;
&lt;br /&gt;
(See above.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Fetching objects ===&lt;br /&gt;
&lt;br /&gt;
* (On startup: invalidate/refresh key cache if keys collection has changed. I believe we make this fetch anyway...)&lt;br /&gt;
* Retrieve object from collection.&lt;br /&gt;
* Look up key for collection name (defaulting to &amp;quot;keys/default&amp;quot;). Fetch if necessary.&lt;br /&gt;
* Verify HMAC using appropriate per-collection or default key. On failure, check for changed keys.&lt;br /&gt;
* Decrypt object.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Version bump ==&lt;br /&gt;
&lt;br /&gt;
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).&lt;/div&gt;</summary>
		<author><name>MarcusWolschon</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/SimplifiedCrypto&amp;diff=271832</id>
		<title>Talk:Services/Sync/SimplifiedCrypto</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/SimplifiedCrypto&amp;diff=271832"/>
		<updated>2010-12-04T10:47:29Z</updated>

		<summary type="html">&lt;p&gt;MarcusWolschon: /* Deriving encryption and HMAC keys from the Sync Key */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== sync key representation ==&lt;br /&gt;
&lt;br /&gt;
The sync key is represented to the user as:&lt;br /&gt;
&lt;br /&gt;
X-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX&lt;br /&gt;
&lt;br /&gt;
== Deriving encryption and HMAC keys from the Sync Key  ==&lt;br /&gt;
&lt;br /&gt;
The hmac used is an SHA-256 HMAC.&amp;lt;br/&amp;gt;&lt;br /&gt;
* Sourcecode of [http://hg.mozilla.org/services/fx-sync/file/12189166cd01/services/sync/modules/util.js#l571 Utils.makeHMACKey()] Sorry, it&#039;s a native method.&lt;br /&gt;
&lt;br /&gt;
* What is the value of HMAC_INPUT?&lt;br /&gt;
** [http://hg.mozilla.org/services/fx-sync/file/37150bc0bf62/services/sync/modules/constants.js source]&lt;br /&gt;
** it is the string &amp;quot;Sync-AES_256_CBC-HMAC256&amp;quot;&lt;br /&gt;
* what is enc + HMAC_INPUT + u + &amp;quot;\x02&amp;quot;? (enc is a byte array, the others are strings)&lt;br /&gt;
&lt;br /&gt;
== Upgrading existing Sync Keys to the new AES key  ==&lt;br /&gt;
PBKDF2 iteration count it 4096, key length 128 bit.&amp;lt;br/&amp;gt;&lt;br /&gt;
Keep in mind that while everywhere else Base64 is used, this is Base32.&lt;br /&gt;
&lt;br /&gt;
Example (Java):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	/**&lt;br /&gt;
	 * See https://wiki.mozilla.org/Services/Sync/SimplifiedCrypto#Upgrading_existing_Sync_Keys_to_the_new_AES_key&lt;br /&gt;
	 * for details on the algorithm.&lt;br /&gt;
	 * @param aV3Passphrase&lt;br /&gt;
	 * @return the v4 syncKey (serves the same purpose as the passphrase before)&lt;br /&gt;
	 * @throws Exception see {@link #passwordToSymmetricKey(char[], byte[])}&lt;br /&gt;
	 * @throws UnsupportedEncodingException should not happen (ASCII) &lt;br /&gt;
	 */&lt;br /&gt;
	public String upgradeV3PassphraseToV4SyncKey(final String aV3Passphrase) throws UnsupportedEncodingException, Exception {&lt;br /&gt;
		String salt = mSyncID;&lt;br /&gt;
		KeySpec ks = new PBEKeySpec(aV3Passphrase.toCharArray(), salt.getBytes(&amp;quot;ASCII&amp;quot;), 4096, 128);&lt;br /&gt;
		PBKDF2HmacSHA1Factory f = new PBKDF2HmacSHA1Factory();&lt;br /&gt;
		SecretKey s = f.engineGenerateSecret(ks);&lt;br /&gt;
        &lt;br /&gt;
		String base32 = biz.wolschon.android.codec.binary.Base32.encode(s.getEncoded()).toLowerCase();&lt;br /&gt;
		String syncKey = base32.replace(&#039;l&#039;, &#039;8&#039;).replace(&#039;o&#039;, &#039;9&#039;);&lt;br /&gt;
&lt;br /&gt;
		syncKey = syncKey.charAt(0)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(1, 6)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(6, 11)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(11, 16)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(16, 21)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(21, 26);&lt;br /&gt;
		Log.d(LOG_TAG, &amp;quot;upgraded passphrase to syncKey \&amp;quot;&amp;quot; + syncKey + &amp;quot;\&amp;quot;&amp;quot;);&lt;br /&gt;
		return syncKey;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>MarcusWolschon</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/SimplifiedCrypto&amp;diff=271831</id>
		<title>Talk:Services/Sync/SimplifiedCrypto</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/SimplifiedCrypto&amp;diff=271831"/>
		<updated>2010-12-04T10:32:36Z</updated>

		<summary type="html">&lt;p&gt;MarcusWolschon: /* Deriving encryption and HMAC keys from the Sync Key */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== sync key representation ==&lt;br /&gt;
&lt;br /&gt;
The sync key is represented to the user as:&lt;br /&gt;
&lt;br /&gt;
X-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX&lt;br /&gt;
&lt;br /&gt;
== Deriving encryption and HMAC keys from the Sync Key  ==&lt;br /&gt;
&lt;br /&gt;
The hmac used is an SHA-256 HMAC.&amp;lt;br/&amp;gt;&lt;br /&gt;
* Sourcecode of [http://hg.mozilla.org/services/fx-sync/file/12189166cd01/services/sync/modules/util.js#l571 Utils.makeHMACKey()] Sorry, it&#039;s a native method.&lt;br /&gt;
&lt;br /&gt;
* What is the value of HMAC_INPUT?&lt;br /&gt;
* what is enc + HMAC_INPUT + u + &amp;quot;\x02&amp;quot;? (enc is a byte array, the others are strings)&lt;br /&gt;
&lt;br /&gt;
== Upgrading existing Sync Keys to the new AES key  ==&lt;br /&gt;
PBKDF2 iteration count it 4096, key length 128 bit.&amp;lt;br/&amp;gt;&lt;br /&gt;
Keep in mind that while everywhere else Base64 is used, this is Base32.&lt;br /&gt;
&lt;br /&gt;
Example (Java):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	/**&lt;br /&gt;
	 * See https://wiki.mozilla.org/Services/Sync/SimplifiedCrypto#Upgrading_existing_Sync_Keys_to_the_new_AES_key&lt;br /&gt;
	 * for details on the algorithm.&lt;br /&gt;
	 * @param aV3Passphrase&lt;br /&gt;
	 * @return the v4 syncKey (serves the same purpose as the passphrase before)&lt;br /&gt;
	 * @throws Exception see {@link #passwordToSymmetricKey(char[], byte[])}&lt;br /&gt;
	 * @throws UnsupportedEncodingException should not happen (ASCII) &lt;br /&gt;
	 */&lt;br /&gt;
	public String upgradeV3PassphraseToV4SyncKey(final String aV3Passphrase) throws UnsupportedEncodingException, Exception {&lt;br /&gt;
		String salt = mSyncID;&lt;br /&gt;
		KeySpec ks = new PBEKeySpec(aV3Passphrase.toCharArray(), salt.getBytes(&amp;quot;ASCII&amp;quot;), 4096, 128);&lt;br /&gt;
		PBKDF2HmacSHA1Factory f = new PBKDF2HmacSHA1Factory();&lt;br /&gt;
		SecretKey s = f.engineGenerateSecret(ks);&lt;br /&gt;
        &lt;br /&gt;
		String base32 = biz.wolschon.android.codec.binary.Base32.encode(s.getEncoded()).toLowerCase();&lt;br /&gt;
		String syncKey = base32.replace(&#039;l&#039;, &#039;8&#039;).replace(&#039;o&#039;, &#039;9&#039;);&lt;br /&gt;
&lt;br /&gt;
		syncKey = syncKey.charAt(0)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(1, 6)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(6, 11)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(11, 16)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(16, 21)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(21, 26);&lt;br /&gt;
		Log.d(LOG_TAG, &amp;quot;upgraded passphrase to syncKey \&amp;quot;&amp;quot; + syncKey + &amp;quot;\&amp;quot;&amp;quot;);&lt;br /&gt;
		return syncKey;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>MarcusWolschon</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/SimplifiedCrypto&amp;diff=271825</id>
		<title>Talk:Services/Sync/SimplifiedCrypto</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/SimplifiedCrypto&amp;diff=271825"/>
		<updated>2010-12-04T08:29:08Z</updated>

		<summary type="html">&lt;p&gt;MarcusWolschon: /* Upgrading existing Sync Keys to the new AES key */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== sync key representation ==&lt;br /&gt;
&lt;br /&gt;
The sync key is represented to the user as:&lt;br /&gt;
&lt;br /&gt;
X-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX&lt;br /&gt;
&lt;br /&gt;
== Deriving encryption and HMAC keys from the Sync Key  ==&lt;br /&gt;
&lt;br /&gt;
The hmac used is an SHA-256 HMAC.&lt;br /&gt;
&lt;br /&gt;
(A deep link to Utils.makeHMACKey() would be helpful here.)&lt;br /&gt;
&lt;br /&gt;
== Upgrading existing Sync Keys to the new AES key  ==&lt;br /&gt;
PBKDF2 iteration count it 4096, key length 128 bit.&amp;lt;br/&amp;gt;&lt;br /&gt;
Keep in mind that while everywhere else Base64 is used, this is Base32.&lt;br /&gt;
&lt;br /&gt;
Example (Java):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	/**&lt;br /&gt;
	 * See https://wiki.mozilla.org/Services/Sync/SimplifiedCrypto#Upgrading_existing_Sync_Keys_to_the_new_AES_key&lt;br /&gt;
	 * for details on the algorithm.&lt;br /&gt;
	 * @param aV3Passphrase&lt;br /&gt;
	 * @return the v4 syncKey (serves the same purpose as the passphrase before)&lt;br /&gt;
	 * @throws Exception see {@link #passwordToSymmetricKey(char[], byte[])}&lt;br /&gt;
	 * @throws UnsupportedEncodingException should not happen (ASCII) &lt;br /&gt;
	 */&lt;br /&gt;
	public String upgradeV3PassphraseToV4SyncKey(final String aV3Passphrase) throws UnsupportedEncodingException, Exception {&lt;br /&gt;
		String salt = mSyncID;&lt;br /&gt;
		KeySpec ks = new PBEKeySpec(aV3Passphrase.toCharArray(), salt.getBytes(&amp;quot;ASCII&amp;quot;), 4096, 128);&lt;br /&gt;
		PBKDF2HmacSHA1Factory f = new PBKDF2HmacSHA1Factory();&lt;br /&gt;
		SecretKey s = f.engineGenerateSecret(ks);&lt;br /&gt;
        &lt;br /&gt;
		String base32 = biz.wolschon.android.codec.binary.Base32.encode(s.getEncoded()).toLowerCase();&lt;br /&gt;
		String syncKey = base32.replace(&#039;l&#039;, &#039;8&#039;).replace(&#039;o&#039;, &#039;9&#039;);&lt;br /&gt;
&lt;br /&gt;
		syncKey = syncKey.charAt(0)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(1, 6)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(6, 11)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(11, 16)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(16, 21)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(21, 26);&lt;br /&gt;
		Log.d(LOG_TAG, &amp;quot;upgraded passphrase to syncKey \&amp;quot;&amp;quot; + syncKey + &amp;quot;\&amp;quot;&amp;quot;);&lt;br /&gt;
		return syncKey;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>MarcusWolschon</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/SimplifiedCrypto&amp;diff=271824</id>
		<title>Talk:Services/Sync/SimplifiedCrypto</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/SimplifiedCrypto&amp;diff=271824"/>
		<updated>2010-12-04T08:28:34Z</updated>

		<summary type="html">&lt;p&gt;MarcusWolschon: /* Upgrading existing Sync Keys to the new AES key */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== sync key representation ==&lt;br /&gt;
&lt;br /&gt;
The sync key is represented to the user as:&lt;br /&gt;
&lt;br /&gt;
X-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX&lt;br /&gt;
&lt;br /&gt;
== Deriving encryption and HMAC keys from the Sync Key  ==&lt;br /&gt;
&lt;br /&gt;
The hmac used is an SHA-256 HMAC.&lt;br /&gt;
&lt;br /&gt;
(A deep link to Utils.makeHMACKey() would be helpful here.)&lt;br /&gt;
&lt;br /&gt;
== Upgrading existing Sync Keys to the new AES key  ==&lt;br /&gt;
PBKDF2 iteration count it 4096, key length 128 bit.&lt;br /&gt;
&lt;br /&gt;
Example (Java):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	/**&lt;br /&gt;
	 * See https://wiki.mozilla.org/Services/Sync/SimplifiedCrypto#Upgrading_existing_Sync_Keys_to_the_new_AES_key&lt;br /&gt;
	 * for details on the algorithm.&lt;br /&gt;
	 * @param aV3Passphrase&lt;br /&gt;
	 * @return the v4 syncKey (serves the same purpose as the passphrase before)&lt;br /&gt;
	 * @throws Exception see {@link #passwordToSymmetricKey(char[], byte[])}&lt;br /&gt;
	 * @throws UnsupportedEncodingException should not happen (ASCII) &lt;br /&gt;
	 */&lt;br /&gt;
	public String upgradeV3PassphraseToV4SyncKey(final String aV3Passphrase) throws UnsupportedEncodingException, Exception {&lt;br /&gt;
		String salt = mSyncID;&lt;br /&gt;
		KeySpec ks = new PBEKeySpec(aV3Passphrase.toCharArray(), salt.getBytes(&amp;quot;ASCII&amp;quot;), 4096, 128);&lt;br /&gt;
		PBKDF2HmacSHA1Factory f = new PBKDF2HmacSHA1Factory();&lt;br /&gt;
		SecretKey s = f.engineGenerateSecret(ks);&lt;br /&gt;
        &lt;br /&gt;
		String base32 = biz.wolschon.android.codec.binary.Base32.encode(s.getEncoded()).toLowerCase();&lt;br /&gt;
		String syncKey = base32.replace(&#039;l&#039;, &#039;8&#039;).replace(&#039;o&#039;, &#039;9&#039;);&lt;br /&gt;
&lt;br /&gt;
		syncKey = syncKey.charAt(0)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(1, 6)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(6, 11)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(11, 16)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(16, 21)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(21, 26);&lt;br /&gt;
		Log.d(LOG_TAG, &amp;quot;upgraded passphrase to syncKey \&amp;quot;&amp;quot; + syncKey + &amp;quot;\&amp;quot;&amp;quot;);&lt;br /&gt;
		return syncKey;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>MarcusWolschon</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/SimplifiedCrypto&amp;diff=271823</id>
		<title>Talk:Services/Sync/SimplifiedCrypto</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/SimplifiedCrypto&amp;diff=271823"/>
		<updated>2010-12-04T08:26:49Z</updated>

		<summary type="html">&lt;p&gt;MarcusWolschon: /* Deriving encryption and HMAC keys from the Sync Key */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== sync key representation ==&lt;br /&gt;
&lt;br /&gt;
The sync key is represented to the user as:&lt;br /&gt;
&lt;br /&gt;
X-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX&lt;br /&gt;
&lt;br /&gt;
== Deriving encryption and HMAC keys from the Sync Key  ==&lt;br /&gt;
&lt;br /&gt;
The hmac used is an SHA-256 HMAC.&lt;br /&gt;
&lt;br /&gt;
(A deep link to Utils.makeHMACKey() would be helpful here.)&lt;br /&gt;
&lt;br /&gt;
== Upgrading existing Sync Keys to the new AES key  ==&lt;br /&gt;
&lt;br /&gt;
example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	/**&lt;br /&gt;
	 * See https://wiki.mozilla.org/Services/Sync/SimplifiedCrypto#Upgrading_existing_Sync_Keys_to_the_new_AES_key&lt;br /&gt;
	 * for details on the algorithm.&lt;br /&gt;
	 * @param aV3Passphrase&lt;br /&gt;
	 * @return the v4 syncKey (serves the same purpose as the passphrase before)&lt;br /&gt;
	 * @throws Exception see {@link #passwordToSymmetricKey(char[], byte[])}&lt;br /&gt;
	 * @throws UnsupportedEncodingException should not happen (ASCII) &lt;br /&gt;
	 */&lt;br /&gt;
	public String upgradeV3PassphraseToV4SyncKey(final String aV3Passphrase) throws UnsupportedEncodingException, Exception {&lt;br /&gt;
		String salt = mSyncID;&lt;br /&gt;
		KeySpec ks = new PBEKeySpec(aV3Passphrase.toCharArray(), salt.getBytes(&amp;quot;ASCII&amp;quot;), 4096, 128);&lt;br /&gt;
		PBKDF2HmacSHA1Factory f = new PBKDF2HmacSHA1Factory();&lt;br /&gt;
		SecretKey s = f.engineGenerateSecret(ks);&lt;br /&gt;
        &lt;br /&gt;
		String base32 = biz.wolschon.android.codec.binary.Base32.encode(s.getEncoded()).toLowerCase();&lt;br /&gt;
		String syncKey = base32.replace(&#039;l&#039;, &#039;8&#039;).replace(&#039;o&#039;, &#039;9&#039;);&lt;br /&gt;
&lt;br /&gt;
		syncKey = syncKey.charAt(0)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(1, 6)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(6, 11)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(11, 16)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(16, 21)&lt;br /&gt;
		+ &amp;quot;-&amp;quot; + syncKey.substring(21, 26);&lt;br /&gt;
		Log.d(LOG_TAG, &amp;quot;upgraded passphrase to syncKey \&amp;quot;&amp;quot; + syncKey + &amp;quot;\&amp;quot;&amp;quot;);&lt;br /&gt;
		return syncKey;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>MarcusWolschon</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/SimplifiedCrypto&amp;diff=271822</id>
		<title>Talk:Services/Sync/SimplifiedCrypto</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/SimplifiedCrypto&amp;diff=271822"/>
		<updated>2010-12-04T07:42:18Z</updated>

		<summary type="html">&lt;p&gt;MarcusWolschon: /* Deriving encryption and HMAC keys from the Sync Key */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== sync key representation ==&lt;br /&gt;
&lt;br /&gt;
The sync key is represented to the user as:&lt;br /&gt;
&lt;br /&gt;
X-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX&lt;br /&gt;
&lt;br /&gt;
== Deriving encryption and HMAC keys from the Sync Key  ==&lt;br /&gt;
&lt;br /&gt;
The hmac used is an SHA-256 HMAC.&lt;br /&gt;
&lt;br /&gt;
(A deep link to Utils.makeHMACKey() would be helpful here.)&lt;/div&gt;</summary>
		<author><name>MarcusWolschon</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/SimplifiedCrypto&amp;diff=271819</id>
		<title>Talk:Services/Sync/SimplifiedCrypto</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/SimplifiedCrypto&amp;diff=271819"/>
		<updated>2010-12-04T07:18:47Z</updated>

		<summary type="html">&lt;p&gt;MarcusWolschon: Created page with &amp;quot;== Deriving encryption and HMAC keys from the Sync Key  ==  The hmac used is an SHA-256 HMAC.  (A deep link to Utils.makeHMACKey() would be helpful here.)&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Deriving encryption and HMAC keys from the Sync Key  ==&lt;br /&gt;
&lt;br /&gt;
The hmac used is an SHA-256 HMAC.&lt;br /&gt;
&lt;br /&gt;
(A deep link to Utils.makeHMACKey() would be helpful here.)&lt;/div&gt;</summary>
		<author><name>MarcusWolschon</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Services/Sync/SimplifiedCrypto&amp;diff=271818</id>
		<title>Services/Sync/SimplifiedCrypto</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Services/Sync/SimplifiedCrypto&amp;diff=271818"/>
		<updated>2010-12-04T06:52:32Z</updated>

		<summary type="html">&lt;p&gt;MarcusWolschon: /* Upgrading existing Sync Keys to the new AES key */ Added links to J-PAKE and SyncID in this Wiki for navigating the referenced specifications&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== The current state of Sync crypto ==&lt;br /&gt;
&lt;br /&gt;
See [[Labs/Weave/Developer/Crypto]] for thorough details.&lt;br /&gt;
&lt;br /&gt;
In short:&lt;br /&gt;
&lt;br /&gt;
* Generate a RSA key pair&lt;br /&gt;
* Generate a symmetric key from the passphrase, using PBKDF2 and a random salt, and encrypt (&amp;quot;wrap&amp;quot;) the private key using that symmetric key&lt;br /&gt;
* Upload public key, wrapped private key + IV + salt to server&lt;br /&gt;
* For each collection, generate a random symkey, encrypt it using the public key, and upload it to the server.&lt;br /&gt;
* 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).&lt;br /&gt;
* Fetching a decrypted object involves:&lt;br /&gt;
** Fetching the encrypted object from the server&lt;br /&gt;
** Looking at the key URI in that JSON blob to find the symkey URI&lt;br /&gt;
** Fetching (if necessary) from the server and RSA-decrypting the symkey&lt;br /&gt;
** Using the symkey to AES-decrypt the object.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Goal and motivation ==&lt;br /&gt;
&lt;br /&gt;
We want to drop the PKI layer. We don&#039;t use it (for the original speculative sharing scenarios), and it costs client computation, server storage, and network bandwidth (~ 16% of our API transactions are key fetches).&lt;br /&gt;
&lt;br /&gt;
== Proposal ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tl;dr&#039;&#039;&#039;: replace the passphrase with an AES key, which will be schlepped around using J-PAKE (so typing it is likely unnecessary). Use this key to indirectly encrypt the &#039;bulk&#039; symkeys. No RSA involved.&lt;br /&gt;
&lt;br /&gt;
Existing passphrases will be upgraded to this scheme using PBKDF2.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Passphrase / Sync Key ===&lt;br /&gt;
&lt;br /&gt;
Rather than have a user enter a passphrase (which will likely be weak), we have already transitioned to having them generate a &amp;quot;sync key&amp;quot; (which they can replace if they so choose). This is 20 alphanumeric characters.&lt;br /&gt;
&lt;br /&gt;
We propose to expand this to 26 characters, enough for a base32-encoded 128-bit AES key. This avoids the use of PBKDF2 to routinely bootstrap the sync key into an AES key. Remove the ability for users to enter a key; it&#039;s always generated (giving us more confidence in the amount of entropy), and can be regenerated if desired.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
As before, the Sync Key is stored on the client. The encryption and hmac keys are derived from it.&lt;br /&gt;
&lt;br /&gt;
==== Deriving encryption and HMAC keys from the Sync Key ====&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;l&#039;&#039;&#039; replaced by &#039;&#039;&#039;8&#039;&#039;&#039; and &#039;&#039;&#039;o&#039;&#039;&#039; replaced by &#039;&#039;&#039;9&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
      let m = Utils.decodeKeyBase32(syncKey);&lt;br /&gt;
&lt;br /&gt;
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]&lt;br /&gt;
      &lt;br /&gt;
      // Reuse the hasher.&lt;br /&gt;
      let h = Utils.makeHMACHasher();&lt;br /&gt;
      &lt;br /&gt;
      // First key.&lt;br /&gt;
      let u = this.username; &lt;br /&gt;
      let k1 = Utils.makeHMACKey(&amp;quot;&amp;quot; + HMAC_INPUT + u + &amp;quot;\x01&amp;quot;);&lt;br /&gt;
      let enc = Utils.sha256HMACBytes(m, k1, h);&lt;br /&gt;
      &lt;br /&gt;
      // Second key: depends on the output of the first run.&lt;br /&gt;
      let k2 = Utils.makeHMACKey(enc + HMAC_INPUT + u + &amp;quot;\x02&amp;quot;);&lt;br /&gt;
      let hmac = Utils.sha256HMACBytes(m, k2, h);&lt;br /&gt;
&lt;br /&gt;
enc and hmac are the 256 bit encryption and HMAC keys, respectively.&lt;br /&gt;
&lt;br /&gt;
==== Upgrading existing Sync Keys to the new AES key ====&lt;br /&gt;
&lt;br /&gt;
Existing users will have their passphrase bootstrapped into an AES key using PBKDF2:&lt;br /&gt;
&lt;br /&gt;
* Spot old version&lt;br /&gt;
* Get a salt ([[Labs/Weave/Developer/StorageFormat#Payload:_meta.2Fglobal|Services.syncID]] from the meta/global object. The client will be bumping this…)&lt;br /&gt;
* Apply PBKDF2 to salt and passphrase to yield our new AES key&lt;br /&gt;
* Generate bulk keys, encrypt&lt;br /&gt;
* Attempt to store, using appropriate race-avoidance technique in case there are multiple clients attempting to upgrade.&lt;br /&gt;
* Wipe old key data.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
=== Bulk keys ===&lt;br /&gt;
&lt;br /&gt;
The server stores one or more bulk keys: one default (&amp;quot;keys/default&amp;quot;), 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.&lt;br /&gt;
&lt;br /&gt;
Bulk keys are encrypted and HMACed using the sync key outputs, and cached on the client. (Current caching is per-session, but they&#039;re stored as identities to make persistence easier to implement.)&lt;br /&gt;
&lt;br /&gt;
The timestamp on the collections record allows clients to invalidate their key cache when a new key is associated with a collection: the &#039;keys&#039; collection will appear to have changed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Discussion topic&#039;&#039;&#039;: do we need to preserve (add?) the ability to do per-object encryption? Brian Warner suggested:&lt;br /&gt;
&lt;br /&gt;
:: While not really interesting here, this one-way property is really useful in other situations, like if you derived per-object encryption keys from a parent folder&#039;s key. You could then share the whole thing with someone by giving them the parent&#039;s key, or share just one object and *not* give them the ability to get at anything else in that folder. But the sharing discussion is for another day..&lt;br /&gt;
&lt;br /&gt;
=== HMAC ===&lt;br /&gt;
&lt;br /&gt;
It&#039;s a good practice to use separate keys for HMAC and for encryption. Bulk keys are really pairs of keys, each of which is randomly generated.&lt;br /&gt;
&lt;br /&gt;
This approach was selected over having a single HMAC key because of the convenience for implementing some sharing-like scenarios.&lt;br /&gt;
&lt;br /&gt;
== Proposed flows ==&lt;br /&gt;
&lt;br /&gt;
=== New user ===&lt;br /&gt;
&lt;br /&gt;
* Generate a 128-bit Sync key (25 characters in base36). Store it as an Identity (as we do now.)&lt;br /&gt;
* Generate a random default key and HMAC. Encrypt it with the sync key, upload it to the server. Store it as an Identity.&lt;br /&gt;
* Encrypt and upload collections in the obvious way.&lt;br /&gt;
&lt;br /&gt;
=== Existing user ===&lt;br /&gt;
&lt;br /&gt;
(See above.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Fetching objects ===&lt;br /&gt;
&lt;br /&gt;
* (On startup: invalidate/refresh key cache if keys collection has changed. I believe we make this fetch anyway...)&lt;br /&gt;
* Retrieve object from collection.&lt;br /&gt;
* Look up key for collection name (defaulting to &amp;quot;keys/default&amp;quot;). Fetch if necessary.&lt;br /&gt;
* Verify HMAC using appropriate per-collection or default key. On failure, check for changed keys.&lt;br /&gt;
* Decrypt object.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Version bump ==&lt;br /&gt;
&lt;br /&gt;
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).&lt;/div&gt;</summary>
		<author><name>MarcusWolschon</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Talk:CloudServices/Sync&amp;diff=271817</id>
		<title>Talk:CloudServices/Sync</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Talk:CloudServices/Sync&amp;diff=271817"/>
		<updated>2010-12-04T06:32:45Z</updated>

		<summary type="html">&lt;p&gt;MarcusWolschon: /* more links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== more links ==&lt;br /&gt;
[[Services/Sync/Experimental Clients|Experimental Clients]]&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Services/Sync/SimplifiedCrypto|Simplified Crypto]] (used with storage format 4)&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://wiki.mozilla.org/Labs/Weave/Developer/Crypto Crypto]] (used with storage format 1-3)&lt;/div&gt;</summary>
		<author><name>MarcusWolschon</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Talk:CloudServices/Sync&amp;diff=271816</id>
		<title>Talk:CloudServices/Sync</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Talk:CloudServices/Sync&amp;diff=271816"/>
		<updated>2010-12-04T06:31:44Z</updated>

		<summary type="html">&lt;p&gt;MarcusWolschon: /* more links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== more links ==&lt;br /&gt;
[[Services/Sync/Experimental Clients|Experimental Clients]]&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Services/Sync/SimplifiedCrypto|Simplified Crypto]] (used with storage format 4)&amp;lt;br/&amp;gt;&lt;br /&gt;
[[/Labs/Weave/Developer/Crypto|Crypto]] (used with storage format 1-3)&lt;/div&gt;</summary>
		<author><name>MarcusWolschon</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Talk:CloudServices/Sync&amp;diff=271815</id>
		<title>Talk:CloudServices/Sync</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Talk:CloudServices/Sync&amp;diff=271815"/>
		<updated>2010-12-04T06:30:38Z</updated>

		<summary type="html">&lt;p&gt;MarcusWolschon: /* more links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== more links ==&lt;br /&gt;
[[Services/Sync/Experimental Clients|Experimental Clients]]&lt;br /&gt;
[[Services/Sync/SimplifiedCrypto|Simplified Crypto]] (used with storage format 4)&lt;br /&gt;
[[Services/Sync/Crypto|Crypto]] (used with storage format 1-3)&lt;/div&gt;</summary>
		<author><name>MarcusWolschon</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Talk:CloudServices/Sync&amp;diff=271814</id>
		<title>Talk:CloudServices/Sync</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Talk:CloudServices/Sync&amp;diff=271814"/>
		<updated>2010-12-04T06:30:04Z</updated>

		<summary type="html">&lt;p&gt;MarcusWolschon: /* more links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== more links ==&lt;br /&gt;
[[Services/Sync/Experimental Clients|Experimental Clients]]&lt;br /&gt;
[[SimplifiedCrypto]] (used with storage format 4)&lt;br /&gt;
[[Crypto]] (used with storage format 1-3)&lt;/div&gt;</summary>
		<author><name>MarcusWolschon</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/Experimental_Clients/iPhone&amp;diff=271813</id>
		<title>Talk:Services/Sync/Experimental Clients/iPhone</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/Experimental_Clients/iPhone&amp;diff=271813"/>
		<updated>2010-12-04T06:29:02Z</updated>

		<summary type="html">&lt;p&gt;MarcusWolschon: Created page with &amp;quot;== 404 == &amp;quot;Not found: weaveclient-iphone &amp;quot;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== 404 ==&lt;br /&gt;
&amp;quot;Not found: weaveclient-iphone &amp;quot;&lt;/div&gt;</summary>
		<author><name>MarcusWolschon</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Talk:CloudServices/Sync&amp;diff=271812</id>
		<title>Talk:CloudServices/Sync</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Talk:CloudServices/Sync&amp;diff=271812"/>
		<updated>2010-12-04T06:27:31Z</updated>

		<summary type="html">&lt;p&gt;MarcusWolschon: Created page with &amp;quot;== more links == Experimental Clients&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== more links ==&lt;br /&gt;
[[Services/Sync/Experimental Clients|Experimental Clients]]&lt;/div&gt;</summary>
		<author><name>MarcusWolschon</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Services/Sync/Experimental_Clients&amp;diff=271811</id>
		<title>Services/Sync/Experimental Clients</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Services/Sync/Experimental_Clients&amp;diff=271811"/>
		<updated>2010-12-04T06:26:16Z</updated>

		<summary type="html">&lt;p&gt;MarcusWolschon: /* Experimental Clients */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;onlyinclude&amp;gt;&lt;br /&gt;
= Experimental Clients =&lt;br /&gt;
&lt;br /&gt;
* [[Weave/Experimental_Clients/Web|Web based data viewer]]&lt;br /&gt;
* [[Weave/Experimental_Clients/iPhone|iPhone data viewer]]&lt;br /&gt;
* [[Weave/Experimental_Clients/WebOS|WebOS data viewer]]&lt;br /&gt;
* [[Weave/Experimental_Clients/Python|Python based command line data viewer]]&lt;br /&gt;
* [http://sourceforge.net/userapps/mediawiki/marcuswolschon/index.php?title=Projects/AndroidDolphinHDFirefoxSyncPlugin Weave for DolphinHD on Android]&lt;br /&gt;
&amp;lt;/onlyinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>MarcusWolschon</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/Server/API/Storage/1.1&amp;diff=271810</id>
		<title>Talk:Services/Sync/Server/API/Storage/1.1</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/Server/API/Storage/1.1&amp;diff=271810"/>
		<updated>2010-12-04T06:22:40Z</updated>

		<summary type="html">&lt;p&gt;MarcusWolschon: Created page with &amp;quot;== WBOs==  See [https://wiki.mozilla.org/Labs/Weave/Developer/StorageFormat StorageFormat] for the actual payloads stored in WBOs and their meaning.  == current version ==  See [...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== WBOs==&lt;br /&gt;
&lt;br /&gt;
See [https://wiki.mozilla.org/Labs/Weave/Developer/StorageFormat StorageFormat] for the actual payloads stored in WBOs and their meaning.&lt;br /&gt;
&lt;br /&gt;
== current version ==&lt;br /&gt;
&lt;br /&gt;
See [https://wiki.mozilla.org/Labs/Weave/Sync/1.0/API 1.0] for the version of this specification that is currently in use.&lt;/div&gt;</summary>
		<author><name>MarcusWolschon</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/Server/API/Storage/1.0&amp;diff=271809</id>
		<title>Talk:Services/Sync/Server/API/Storage/1.0</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/Server/API/Storage/1.0&amp;diff=271809"/>
		<updated>2010-12-04T06:22:08Z</updated>

		<summary type="html">&lt;p&gt;MarcusWolschon: /* WBOs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== WBOs==&lt;br /&gt;
&lt;br /&gt;
See [https://wiki.mozilla.org/Labs/Weave/Developer/StorageFormat StorageFormat] for the actual payloads stored in WBOs and their meaning.&lt;br /&gt;
&lt;br /&gt;
== new version ==&lt;br /&gt;
&lt;br /&gt;
See [https://wiki.mozilla.org/Labs/Weave/Sync/1.1/API 1.1] for the next version of this specification.&lt;/div&gt;</summary>
		<author><name>MarcusWolschon</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/Server/API/Storage/1.0&amp;diff=271808</id>
		<title>Talk:Services/Sync/Server/API/Storage/1.0</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/Server/API/Storage/1.0&amp;diff=271808"/>
		<updated>2010-12-04T06:21:03Z</updated>

		<summary type="html">&lt;p&gt;MarcusWolschon: Created page with &amp;quot;== WBOs==  See [https://wiki.mozilla.org/Labs/Weave/Developer/StorageFormat StorageFormat] for the actual payloads stored in WBOs and their meaning.&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== WBOs==&lt;br /&gt;
&lt;br /&gt;
See [https://wiki.mozilla.org/Labs/Weave/Developer/StorageFormat StorageFormat] for the actual payloads stored in WBOs and their meaning.&lt;/div&gt;</summary>
		<author><name>MarcusWolschon</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/Developer/StorageFormat&amp;diff=271807</id>
		<title>Talk:Services/Sync/Developer/StorageFormat</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/Developer/StorageFormat&amp;diff=271807"/>
		<updated>2010-12-04T06:19:56Z</updated>

		<summary type="html">&lt;p&gt;MarcusWolschon: /* WBO */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== WBO ==&lt;br /&gt;
The elements described here are stored as [https://wiki.mozilla.org/Labs/Weave/Sync/1.0/API#Weave_Basic_Object_.28WBO.29 WBO]=Weave Basic Objects.&lt;br /&gt;
&lt;br /&gt;
Regarding the stored cryptographic keys, see [https://wiki.mozilla.org/Labs/Weave/Developer/Crypto here(V1-V3)] and [https://wiki.mozilla.org/Services/Sync/SimplifiedCrypto here(V4)] for how they are ultimately derived from the user&#039;s password.&lt;br /&gt;
&lt;br /&gt;
== Version 4 ==&lt;br /&gt;
The latest desktop-mozilla uses vesion 4.&lt;br /&gt;
The changes include at least a very different login and crypto (see [https://wiki.mozilla.org/Services/Sync/SimplifiedCrypto here]).&lt;/div&gt;</summary>
		<author><name>MarcusWolschon</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/Developer/StorageFormat&amp;diff=271806</id>
		<title>Talk:Services/Sync/Developer/StorageFormat</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Talk:Services/Sync/Developer/StorageFormat&amp;diff=271806"/>
		<updated>2010-12-04T06:17:18Z</updated>

		<summary type="html">&lt;p&gt;MarcusWolschon: Created page with &amp;quot;== WBO == The elements described here are stored as WBO=Weave Basic Objects. See [https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects BrowserObjects] for more details.  ...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== WBO ==&lt;br /&gt;
The elements described here are stored as WBO=Weave Basic Objects.&lt;br /&gt;
See [https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects BrowserObjects] for more details.&lt;br /&gt;
&lt;br /&gt;
Regarding the stored cryptographic keys, see [https://wiki.mozilla.org/Labs/Weave/Developer/Crypto here(V1-V3)] and [https://wiki.mozilla.org/Services/Sync/SimplifiedCrypto here(V4)] for how they are ultimately derived from the user&#039;s password.&lt;br /&gt;
&lt;br /&gt;
== Version 4 ==&lt;br /&gt;
The latest desktop-mozilla uses vesion 4.&lt;br /&gt;
The changes include at least a very different login and crypto (see [https://wiki.mozilla.org/Services/Sync/SimplifiedCrypto here]).&lt;/div&gt;</summary>
		<author><name>MarcusWolschon</name></author>
	</entry>
</feed>