Merge pull request #24 from outis1one/claude/read-repo-wA3y1
fix: cross-browser sync decryption + WebAuthn on extension pages
This commit is contained in:
@@ -374,6 +374,9 @@ const SilentSendCrypto = {
|
|||||||
* Check if WebAuthn is available in this browser.
|
* Check if WebAuthn is available in this browser.
|
||||||
*/
|
*/
|
||||||
isWebAuthnAvailable() {
|
isWebAuthnAvailable() {
|
||||||
|
// WebAuthn doesn't work on extension pages (chrome-extension:// origin)
|
||||||
|
if (typeof location !== 'undefined' && location.protocol === 'chrome-extension:') return false;
|
||||||
|
if (typeof location !== 'undefined' && location.protocol === 'moz-extension:') return false;
|
||||||
return !!(window.PublicKeyCredential && navigator.credentials);
|
return !!(window.PublicKeyCredential && navigator.credentials);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
+27
-8
@@ -464,23 +464,42 @@ const SilentSendSync = {
|
|||||||
async _decryptFromSync(data) {
|
async _decryptFromSync(data) {
|
||||||
if (!data?._ssEncrypted) return { data, decrypted: false };
|
if (!data?._ssEncrypted) return { data, decrypted: false };
|
||||||
|
|
||||||
// If this device has no encryption config yet, bootstrap from the sync envelope
|
// Always use the sync envelope's salt/verificationBlob for decryption,
|
||||||
|
// not the local config. Different devices have different salts, so the
|
||||||
|
// local key won't decrypt data encrypted with another device's salt.
|
||||||
let config = await this._getSyncEncryption();
|
let config = await this._getSyncEncryption();
|
||||||
if (!config?.enabled && data._encConfig) {
|
|
||||||
// Save minimal config so authenticate() can work
|
if (data._encConfig) {
|
||||||
|
// Use the source's salt for this decryption, but don't overwrite
|
||||||
|
// the local config permanently yet — only if decryption succeeds
|
||||||
config = {
|
config = {
|
||||||
|
...(config || {}),
|
||||||
enabled: true,
|
enabled: true,
|
||||||
salt: data._encConfig.salt,
|
salt: data._encConfig.salt,
|
||||||
verificationBlob: data._encConfig.verificationBlob,
|
verificationBlob: data._encConfig.verificationBlob,
|
||||||
authMethod: 'password', // will be updated from _encMeta after decryption
|
|
||||||
ttlDays: 90,
|
|
||||||
webauthn: false,
|
|
||||||
};
|
};
|
||||||
await this._saveSyncEncryption(config);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const keyInfo = await this._getEncryptionKey();
|
if (!config?.enabled) {
|
||||||
|
return { data: null, decrypted: false, needsAuth: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to get a key using the sync envelope's salt
|
||||||
|
// First check if we have a cached key that matches
|
||||||
|
let keyInfo = await SilentSendCrypto.getCachedKey();
|
||||||
|
|
||||||
|
// If the cached key's salt doesn't match the sync data's salt,
|
||||||
|
// we need to re-derive from the password
|
||||||
|
if (keyInfo && data._encConfig && keyInfo.salt !== data._encConfig.salt) {
|
||||||
|
keyInfo = null; // force re-auth with the correct salt
|
||||||
|
}
|
||||||
|
|
||||||
if (!keyInfo) {
|
if (!keyInfo) {
|
||||||
|
// Need the user to enter the password — save the sync salt temporarily
|
||||||
|
// so authenticate() uses it to derive the correct key
|
||||||
|
if (data._encConfig) {
|
||||||
|
await this._saveSyncEncryption(config);
|
||||||
|
}
|
||||||
return { data: null, decrypted: false, needsAuth: true };
|
return { data: null, decrypted: false, needsAuth: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user