You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 11ced5a
Browse filesBrowse the repository at this point in the historyBrowse files
fix(crypto): re-sync public key on rotation + explicit key recovery prompt
Two related cross-device key problems:
1. needsKeySync() only checked whether *any* public key existed in the DB
for the user, not whether it matched the local key. After switching
browsers / rotating keys, the DB kept the OLD public key, so the sync was
skipped and everyone kept encrypting to a dead key the new device can't
read. Now it compares the DB key to the local key and re-syncs on mismatch
(the server RPC already upserts via ON CONFLICT DO UPDATE).
2. EncryptionWarning now gives an explicit choice when a device has no keys:
"Upload existing keys" (recommended — routes to Settings import/restore,
preserves history) vs "Generate new keys" (with a confirm that past
messages become unreadable). Previously it silently pointed at Settings,
which let users end up on fresh keys without understanding the cost.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@@ -20,20 +24,72 @@ export default function EncryptionWarning() {
20
24
check();
21
25
},[]);
22
26
27
+
asyncfunctionhandleGenerate(){
28
+
// New keys give you a fresh identity but make every message that was
29
+
// encrypted to your previous key permanently unreadable. Restoring/uploading
30
+
// existing keys is almost always what the user actually wants.
31
+
constok=window.confirm(
32
+
'Generate brand-new keys?\n\nYou will NOT be able to read any past messages or files that were encrypted to your previous keys. If you have a backup or an exported key file, use "Upload existing keys" instead.'
33
+
);
34
+
if(!ok)return;
35
+
setGenerating(true);
36
+
setError('');
37
+
try{
38
+
awaitkeyManager.generateUserKeys();
39
+
setHasKeys(true);
40
+
}catch(err){
41
+
setError(err?.message||'Failed to generate keys');
42
+
}finally{
43
+
setGenerating(false);
44
+
}
45
+
}
46
+
23
47
if(!checked||hasKeys)returnnull;
24
48
25
49
return(
26
50
<divclassName="encryption-warning">
27
51
<divclassName="warning-icon">⚠️</div>
28
52
<divclassName="warning-content">
29
-
<strong>Encryption keys not found</strong>
30
-
<p>Your messages cannot be encrypted. Please go to <ahref="/settings">Settings</a> to generate or restore your encryption keys.</p>
53
+
<strong>No encryption keys on this device</strong>
54
+
<p>
55
+
This browser doesn't have your encryption keys, so messages can't be decrypted or sent
56
+
securely. Upload your existing keys to keep your history, or generate new ones to start fresh.
57
+
</p>
58
+
{error&&<pclassName="warning-error">{error}</p>}
59
+
<divclassName="warning-actions">
60
+
<button
61
+
type="button"
62
+
className="warn-btn warn-btn-primary"
63
+
onClick={()=>router.push('/settings')}
64
+
disabled={generating}
65
+
>
66
+
Upload existing keys
67
+
</button>
68
+
<button
69
+
type="button"
70
+
className="warn-btn warn-btn-secondary"
71
+
onClick={handleGenerate}
72
+
disabled={generating}
73
+
>
74
+
{generating ? 'Generating…' : 'Generate new keys'}
75
+
</button>
76
+
</div>
77
+
<pclassName="warning-hint">
78
+
Switched browsers or devices? Choose <strong>Upload existing keys</strong> — generating new keys
0 commit comments