diff --git a/src/handlers/import.ts b/src/handlers/import.ts index c6a08fa..358d68e 100644 --- a/src/handlers/import.ts +++ b/src/handlers/import.ts @@ -19,7 +19,7 @@ interface CiphersImportRequest { sshKey?: any | null; key?: string | null; login?: { - uris?: Array<{ uri: string | null; match?: number | null }> | null; + uris?: Array<{ uri: string | null; uriChecksum?: string | null; match?: number | null }> | null; username?: string | null; password?: string | null; totp?: string | null; @@ -195,7 +195,7 @@ export async function handleCiphersImport(request: Request, env: Env, userId: st uris: login.uris?.map((u: any) => ({ ...u, uri: u.uri ?? null, - uriChecksum: null, + uriChecksum: u.uriChecksum ?? null, match: u.match ?? null, })) || null, totp: login.totp ?? null, diff --git a/webapp/src/lib/api/vault.ts b/webapp/src/lib/api/vault.ts index 27c371c..fbc2a45 100644 --- a/webapp/src/lib/api/vault.ts +++ b/webapp/src/lib/api/vault.ts @@ -1,4 +1,4 @@ -import { base64ToBytes, decryptBw, decryptBwFileData, decryptStr, encryptBw, encryptBwFileData } from '../crypto'; +import { base64ToBytes, decryptBw, decryptBwFileData, decryptStr, encryptBw, encryptBwFileData, sha256Base64 } from '../crypto'; import type { Cipher, CipherPasswordHistoryEntry, @@ -574,12 +574,18 @@ async function encryptUris( entry?.extra && typeof entry.extra === 'object' ? { ...entry.extra } : {}; - if (String(entry?.originalUri || '').trim() !== trimmed) { + const canReuseChecksum = String(entry?.originalUri || '').trim() === trimmed; + if (!canReuseChecksum) { delete preservedExtra.uriChecksum; } + const preservedChecksum = typeof preservedExtra.uriChecksum === 'string' && looksLikeCipherString(preservedExtra.uriChecksum) + ? preservedExtra.uriChecksum + : null; + const uriChecksum = preservedChecksum || await encryptTextValue(await sha256Base64(trimmed), enc, mac); out.push({ ...preservedExtra, uri: await encryptTextValue(trimmed, enc, mac), + uriChecksum, match: typeof entry?.match === 'number' && Number.isFinite(entry.match) ? entry.match : null, }); } diff --git a/webapp/src/lib/crypto.ts b/webapp/src/lib/crypto.ts index 4a60e8c..9bb2f1f 100644 --- a/webapp/src/lib/crypto.ts +++ b/webapp/src/lib/crypto.ts @@ -22,6 +22,12 @@ export function toBufferSource(bytes: Uint8Array): ArrayBuffer { return new Uint8Array(bytes).buffer; } +export async function sha256Base64(value: string): Promise { + const bytes = new TextEncoder().encode(value); + const hash = await crypto.subtle.digest('SHA-256', toBufferSource(bytes)); + return bytesToBase64(new Uint8Array(hash)); +} + const hmacSha256KeyCache = new WeakMap>(); const aesCbcEncryptKeyCache = new WeakMap>(); const aesCbcDecryptKeyCache = new WeakMap>();