feat(vault): add get/create assets API in workflow

TODO: update vault.service.ts. Use MNEMONIC workflow to create real private_key_shard and content_inner_encrypted
This commit is contained in:
Ada
2026-02-01 09:19:45 -08:00
parent 536513ab3f
commit f6fa19d0b2
9 changed files with 628 additions and 78 deletions

View File

@@ -0,0 +1,81 @@
/**
* Vault Service: 为 /assets/create 生成 private_key_shard 与 content_inner_encrypted
*
* 流程(与后端 test_scenario / SentinelVault 一致):
* 1. 用 SSS 生成助记词并分片 → 选一个分片作为 private_key_shard存后端继承时返回
* 2. 用助记词派生 AES 密钥,对明文做 AES-GCM 加密 → content_inner_encryptedhex 字符串)
*
* 使用方式:在任意页面调用 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_encryptedAES-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<CreateVaultPayloadResult> {
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<CreateAssetPayloadResult> {
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,
};
}