Fix crypto and message duplication

This commit is contained in:
2025-08-30 12:14:36 +03:00
Unverified
parent ebd075136b
commit bd52b3c05a
4 changed files with 55 additions and 29 deletions
+19 -15
View File
@@ -8,30 +8,33 @@ import type { BackupBlob, UploadPublicKeyRequest } from "../core/types";
let currentPublicKey: Uint8Array | null = null;
let currentPrivateKey: Uint8Array | null = null;
async function fetchPublicKey(): Promise<Uint8Array | null> {
const res = await fetch(`${API_BASE_URL}/crypto/public-key`, { method: "GET", headers: getAuthHeaders(true) });
async function fetchPublicKey(token?: string): Promise<Uint8Array | null> {
const headers = token ? { 'Authorization': `Bearer ${token}` } : getAuthHeaders(true);
const res = await fetch(`${API_BASE_URL}/crypto/public-key`, { method: "GET", headers });
if (!res.ok) return null;
const data = await res.json();
if (!data?.publicKey) return null;
return ub64(data.publicKey);
}
async function uploadPublicKey(publicKey: Uint8Array): Promise<void> {
async function uploadPublicKey(publicKey: Uint8Array, token?: string): Promise<void> {
const payload: UploadPublicKeyRequest = {
publicKey: b64(publicKey)
}
const headers = token ? { 'Authorization': `Bearer ${token}` } : getAuthHeaders(true);
await fetch(`${API_BASE_URL}/crypto/public-key`, {
method: "POST",
headers: getAuthHeaders(true),
headers,
body: JSON.stringify(payload)
});
}
async function fetchBackupBlob(): Promise<string | null> {
async function fetchBackupBlob(token?: string): Promise<string | null> {
const headers = token ? { 'Authorization': `Bearer ${token}` } : getAuthHeaders(true);
const res = await fetch(`${API_BASE_URL}/crypto/backup`, {
method: "GET",
headers: getAuthHeaders(true)
headers
});
if (res.ok) {
const response: BackupBlob = await res.json();
@@ -41,12 +44,13 @@ async function fetchBackupBlob(): Promise<string | null> {
}
}
async function uploadBackupBlob(blobJson: string): Promise<void> {
async function uploadBackupBlob(blobJson: string, token?: string): Promise<void> {
const payload: BackupBlob = { blob: blobJson }
const headers = token ? { 'Authorization': `Bearer ${token}` } : getAuthHeaders(true);
await fetch(`${API_BASE_URL}/crypto/backup`, {
method: "POST",
headers: getAuthHeaders(true),
headers,
body: JSON.stringify(payload)
});
}
@@ -61,16 +65,16 @@ export function getCurrentKeys(): UserKeyPairMemory | null {
return null;
}
export async function ensureKeysOnLogin(password: string): Promise<UserKeyPairMemory> {
export async function ensureKeysOnLogin(password: string, token?: string): Promise<UserKeyPairMemory> {
// Try to restore from backup
const blobJson = await fetchBackupBlob();
const blobJson = await fetchBackupBlob(token);
if (blobJson) {
const blob = decodeBlob(blobJson);
const bundle = await decryptBackupWithPassword(password, blob);
currentPrivateKey = bundle.privateKey;
// Ensure public key exists on server; if not, derive from private (not possible via libsafely), so keep previous
// In our simple scheme, we rely on server having the public key or we reupload generated one on first setup
const serverPub = await fetchPublicKey();
const serverPub = await fetchPublicKey(token);
if (serverPub) {
currentPublicKey = serverPub;
} else {
@@ -78,9 +82,9 @@ export async function ensureKeysOnLogin(password: string): Promise<UserKeyPairMe
const pair = generateX25519KeyPair();
currentPublicKey = pair.publicKey;
currentPrivateKey = pair.privateKey;
await uploadPublicKey(currentPublicKey);
await uploadPublicKey(currentPublicKey, token);
const newBlob = await encryptBackupWithPassword(password, { version: 1, privateKey: currentPrivateKey });
await uploadBackupBlob(encodeBlob(newBlob));
await uploadBackupBlob(encodeBlob(newBlob), token);
}
return { publicKey: currentPublicKey!, privateKey: currentPrivateKey! };
}
@@ -89,9 +93,9 @@ export async function ensureKeysOnLogin(password: string): Promise<UserKeyPairMe
const pair = generateX25519KeyPair();
currentPublicKey = pair.publicKey;
currentPrivateKey = pair.privateKey;
await uploadPublicKey(currentPublicKey);
await uploadPublicKey(currentPublicKey, token);
const encBlob = await encryptBackupWithPassword(password, { version: 1, privateKey: currentPrivateKey });
await uploadBackupBlob(encodeBlob(encBlob));
await uploadBackupBlob(encodeBlob(encBlob), token);
return { publicKey: currentPublicKey, privateKey: currentPrivateKey };
}