Sync exchange v2: Fix password deriation mismatch#9014
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
931b74c to
994d6c4
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 994d6c4. Configure here.
994d6c4 to
3264782
Compare
3264782 to
db6a0bf
Compare
CrisBarreiro
left a comment
There was a problem hiding this comment.
Other than not seeing "sync now"dialog when pairing 2 Android devices, it works as expected
|
@CrisBarreiro , re #9014 (review) since writing the testing steps the remote flag for I'll do a final round of testing to check it all works before merging this. |
Merge activity
|
Task/Issue URL: https://app.asana.com/1/137249556945/project/1203822806345703/task/1216036247181808?focus=true Tech Design URL (if applicable): ### Description Drop the direct `POST /sync/keys/.../set-if-absent` call from the 3party credential creation flow which previously existed as its own distinct step. Removing this also means we can remove some now-redundant dev tooling for it. ### Steps to test this PR - Exact same as #9014 <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes the sync v2 crypto path for first-time `ai_chats` keys and 3party credential setup; mistakes could break scoped login or key consistency, though behavior is localized to the 3party credential flow behind the v2 feature flag. > > **Overview** > **3party credential creation** no longer calls `POST /sync/keys/.../set-if-absent` or uses `ProtectedKeyManager`. When the account has no ddg-wrapped `ai_chats` key, the client mints an RSA keypair via **`mintDdgWrappedProtectedKey`** and includes **both** ddg and 3party `ProtectedKeyEntry` rows (same `kid`) in the **`POST /access-credentials/3party`** `keys[]` payload, alongside re-wrapped existing ddg keys. > > The **`setProtectedKeyIfAbsent`** Retrofit/API surface, **`SyncAccountRepository.createProtectedKey`**, **`ProtectedKeyManager`**, and related tests/dev UI (“Create Protected Key”) are removed. **`ThirdPartyCredentialManager`** adds bounded retries on **`concurrent_modification`** 409s for that credential POST and broadens 409 handling messaging before the adopt-existing-credential path. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit b0288d5. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->


Task/Issue URL: https://app.asana.com/1/137249556945/task/1216049977533939?focus=true
Tech Design URL (if applicable):
Description
Fixes a password derivation mismatch in the native 3party → ddg upgrade flow (joinAccountFromThirdPartyRecoveryCode).
When minting the new DDG credential on
POST /access-credentials/ddg,credentialHashedPasswordnow usesnewDdgKeys.passwordHash(libsodium/Argon2, same as signup) instead of anHKDF-derivedhash from the new primary key. That keeps server-side stored hashes aligned with whatperformLoginsends viaprepareForLogin.Steps to test this PR
Note
internalbuild from this branchSync screenI meanSettings -> Sync & BackupNative to native pairing
Sync screenand chooseSync With Another DeviceSync NowSynced Deviceslist (might take a few seconds)Adding in 3rd party browser
Settings & More(bottom left) thenSettingsand tapTurn On Sync & Backup->Sync With Another DeviceSync screenand tapSync With Another DeviceSync NowImportant
Log out of sync on all devices (e.g.,
Sync screen->Turn Off Sync & Backup...3rd party code first
Settings & More,Settingsand tapTurn On Sync & Backup->Sync With Another DeviceSync screenthenSync with Another DeviceSync NowSync with Another DeviceSync with Another DevicetooSync Nowon both devices when promptedNote
High Risk
Changes authentication hashing and the post-upgrade login/commit path for joining sync accounts; a regression could block 3party upgrades or leave credentials in a bad state until TTL expiry.
Overview
Fixes a password derivation mismatch in the native 3party → ddg upgrade flow (
joinAccountFromThirdPartyRecoveryCode).When minting the new DDG credential on
POST /access-credentials/ddg,credentialHashedPasswordnow usesnewDdgKeys.passwordHash(libsodium/Argon2, same as signup) instead of an HKDF-derived hash from the new primary key. That keeps server-side stored hashes aligned with whatperformLoginsends viaprepareForLogin.Step 7 no longer uses the removed
performDdgLoginForUpgradeplus a manualSyncStorewrite. It callsperformLogin(with retries), so committing the credential, persisting the unrestricted ddg token, decryptingprotected_encryption_key, settingcredentialId, scoped password handling, and post-login sync all follow the normal login path.Interface/docs now describe three network steps, with the third unscoped
/sync/logingoing throughperformLogin. Tests mockprepareForLogin, decrypt, and returnprotected_encryption_keyon the post-upgrade login response.Reviewed by Cursor Bugbot for commit 994d6c4. Configure here.