/** * Vault Service: 为 /assets/create 生成 private_key_shard 与 content_inner_encrypted * * 流程(与后端 test_scenario / SentinelVault 一致): * 1. 用 SSS 生成助记词并分片 → 选一个分片作为 private_key_shard(存后端,继承时返回) * 2. 用助记词派生 AES 密钥,对明文做 AES-GCM 加密 → content_inner_encrypted(hex 字符串) * * 使用方式:在任意页面调用 createVaultPayload(plaintext, wordList),得到可直接传给 assetsService.createAsset 的字段。 */ import { generateVaultKeys, serializeShare, type SSSShare, type VaultKeyData, } from '../utils/sss'; import { deriveKey, encryptDataGCM, bytesToHex } from '../utils/vaultCrypto'; export interface CreateVaultPayloadResult { /** 传给后端的 private_key_shard(存一个 SSS 分片的序列化字符串,如云端分片) */ private_key_shard: string; /** 传给后端的 content_inner_encrypted(AES-GCM 密文的 hex) */ content_inner_encrypted: string; /** 本次生成的助记词(用户需妥善保管,恢复时需任意 2 个分片) */ mnemonic: string[]; /** 三个分片:device / cloud / heir,可与后端返回的 server_shard 组合恢复助记词 */ shares: SSSShare[]; } export interface CreateAssetPayloadResult { title: string; type: string; private_key_shard: string; content_inner_encrypted: string; } /** * 生成金库:助记词 + SSS 分片 + 内层加密内容 * @param plaintext 要加密的明文(如遗产说明、账号密码等) * @param wordList 助记词词表(与 sss 使用的词表一致) * @param shareIndexForServer 哪个分片存后端,0=device, 1=cloud, 2=heir,默认 1(云端) */ export async function createVaultPayload( plaintext: string, wordList: readonly string[], shareIndexForServer: 0 | 1 | 2 = 1 ): Promise { const { mnemonic, shares }: VaultKeyData = generateVaultKeys(wordList, 12); const mnemonicPhrase = mnemonic.join(' '); const key = await deriveKey(mnemonicPhrase); const encrypted = await encryptDataGCM(key, plaintext); const content_inner_encrypted = bytesToHex(encrypted); const shareForServer = shares[shareIndexForServer]; const private_key_shard = serializeShare(shareForServer); return { private_key_shard, content_inner_encrypted, mnemonic, shares, }; } /** * 生成可直接用于 POST /assets/create 的请求体(含 title / type) */ export async function createAssetPayload( title: string, plaintext: string, wordList: readonly string[], assetType: string = 'note', shareIndexForServer: 0 | 1 | 2 = 1 ): Promise { const vault = await createVaultPayload(plaintext, wordList, shareIndexForServer); return { title, type: assetType, private_key_shard: vault.private_key_shard, content_inner_encrypted: vault.content_inner_encrypted, }; }