Replace logbook backup v1 JSON with v2 ZIP archives.
ZIP .daagbok files use a compact manifest and binary KDAB blobs so large photo, voice, and GPS payloads no longer inflate in a single JSON file. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
import { base64ToBuffer, bufferToBase64 } from '../crypto.js'
|
||||
|
||||
export const ENC_MAGIC = new Uint8Array([0x4b, 0x44, 0x41, 0x42]) // KDAB
|
||||
export const ENC_FORMAT_VERSION = 1
|
||||
export const ENC_HEADER_SIZE = 33 // 4 + 1 + 12 + 16
|
||||
|
||||
export interface DexieEncFields {
|
||||
encryptedData: string
|
||||
iv: string
|
||||
tag: string
|
||||
}
|
||||
|
||||
export function encBytesFromDexieFields(fields: DexieEncFields): Uint8Array {
|
||||
const iv = new Uint8Array(base64ToBuffer(fields.iv))
|
||||
const tag = new Uint8Array(base64ToBuffer(fields.tag))
|
||||
const ciphertext = new Uint8Array(base64ToBuffer(fields.encryptedData))
|
||||
if (iv.length !== 12) throw new Error('BACKUP_INVALID_ENC')
|
||||
if (tag.length !== 16) throw new Error('BACKUP_INVALID_ENC')
|
||||
|
||||
const out = new Uint8Array(ENC_HEADER_SIZE + ciphertext.length)
|
||||
out.set(ENC_MAGIC, 0)
|
||||
out[4] = ENC_FORMAT_VERSION
|
||||
out.set(iv, 5)
|
||||
out.set(tag, 17)
|
||||
out.set(ciphertext, 33)
|
||||
return out
|
||||
}
|
||||
|
||||
export function dexieFieldsFromEncBytes(bytes: Uint8Array): DexieEncFields {
|
||||
if (bytes.length < ENC_HEADER_SIZE) throw new Error('BACKUP_INVALID_ENC')
|
||||
for (let i = 0; i < 4; i++) {
|
||||
if (bytes[i] !== ENC_MAGIC[i]) throw new Error('BACKUP_INVALID_ENC')
|
||||
}
|
||||
if (bytes[4] !== ENC_FORMAT_VERSION) throw new Error('BACKUP_INVALID_ENC')
|
||||
|
||||
const iv = bufferToBase64(bytes.slice(5, 17).buffer)
|
||||
const tag = bufferToBase64(bytes.slice(17, 33).buffer)
|
||||
const ciphertext = bufferToBase64(bytes.slice(33).buffer)
|
||||
return { encryptedData: ciphertext, iv, tag }
|
||||
}
|
||||
|
||||
export function encByteLength(fields: DexieEncFields): number {
|
||||
const ct = base64ToBuffer(fields.encryptedData).byteLength
|
||||
return ENC_HEADER_SIZE + ct
|
||||
}
|
||||
Reference in New Issue
Block a user