import { bytes, b64, unb64, sealJson, openJson } from './accountCrypto'; export interface ObjectContext { spaceId: string; channelId: string; domain: 'chat' | 'files'; epoch: number; itemId: string } const label = (c: ObjectContext) => JSON.stringify(['webdrop/object-key/v1', c.spaceId, c.channelId, c.domain, c.epoch, c.itemId]); export const randomDomainKey = () => b64(crypto.getRandomValues(new Uint8Array(32))); async function aes(value: string): Promise { const material = unb64(value); try { if (material.length !== 32) throw new Error('数据域密钥格式无效'); return await crypto.subtle.importKey('raw', bytes(material), 'AES-GCM', false, ['encrypt', 'decrypt']); } finally { material.fill(0); } } export async function newObjectKey(domainKey: string, context: ObjectContext): Promise<{ key: CryptoKey; envelope: string }> { const raw = crypto.getRandomValues(new Uint8Array(32)); try { const key = await crypto.subtle.importKey('raw', bytes(raw), 'AES-GCM', false, ['encrypt', 'decrypt']); return { key, envelope: await sealJson({ key: b64(raw) }, await aes(domainKey), label(context)) }; } finally { raw.fill(0); } } export async function unwrapObjectKey(domainKey: string, envelope: string, context: ObjectContext): Promise { const value = await openJson(envelope, await aes(domainKey), label(context)) as { key?: unknown }; if (typeof value.key !== 'string') throw new Error('对象密钥封装格式无效'); return aes(value.key); }