@agentunion/fastaun-browser 0.2.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +604 -0
- package/dist/auth.d.ts +150 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +1388 -0
- package/dist/auth.js.map +1 -0
- package/dist/certs/root.d.ts +2 -0
- package/dist/certs/root.d.ts.map +1 -0
- package/dist/certs/root.js +16 -0
- package/dist/certs/root.js.map +1 -0
- package/dist/client.d.ts +341 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +4061 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +37 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +85 -0
- package/dist/config.js.map +1 -0
- package/dist/crypto.d.ts +41 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +132 -0
- package/dist/crypto.js.map +1 -0
- package/dist/discovery.d.ts +20 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +75 -0
- package/dist/discovery.js.map +1 -0
- package/dist/e2ee-group.d.ts +221 -0
- package/dist/e2ee-group.d.ts.map +1 -0
- package/dist/e2ee-group.js +1174 -0
- package/dist/e2ee-group.js.map +1 -0
- package/dist/e2ee.d.ts +187 -0
- package/dist/e2ee.d.ts.map +1 -0
- package/dist/e2ee.js +1067 -0
- package/dist/e2ee.js.map +1 -0
- package/dist/errors.d.ts +118 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +250 -0
- package/dist/errors.js.map +1 -0
- package/dist/events.d.ts +33 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +68 -0
- package/dist/events.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -0
- package/dist/keystore/index.d.ts +88 -0
- package/dist/keystore/index.d.ts.map +1 -0
- package/dist/keystore/index.js +3 -0
- package/dist/keystore/index.js.map +1 -0
- package/dist/keystore/indexeddb.d.ts +94 -0
- package/dist/keystore/indexeddb.d.ts.map +1 -0
- package/dist/keystore/indexeddb.js +1434 -0
- package/dist/keystore/indexeddb.js.map +1 -0
- package/dist/namespaces/auth.d.ts +52 -0
- package/dist/namespaces/auth.d.ts.map +1 -0
- package/dist/namespaces/auth.js +237 -0
- package/dist/namespaces/auth.js.map +1 -0
- package/dist/namespaces/custody.d.ts +48 -0
- package/dist/namespaces/custody.d.ts.map +1 -0
- package/dist/namespaces/custody.js +230 -0
- package/dist/namespaces/custody.js.map +1 -0
- package/dist/secret-store/index.d.ts +20 -0
- package/dist/secret-store/index.d.ts.map +1 -0
- package/dist/secret-store/index.js +12 -0
- package/dist/secret-store/index.js.map +1 -0
- package/dist/secret-store/indexeddb-store.d.ts +22 -0
- package/dist/secret-store/indexeddb-store.d.ts.map +1 -0
- package/dist/secret-store/indexeddb-store.js +133 -0
- package/dist/secret-store/indexeddb-store.js.map +1 -0
- package/dist/seq-tracker.d.ts +30 -0
- package/dist/seq-tracker.d.ts.map +1 -0
- package/dist/seq-tracker.js +219 -0
- package/dist/seq-tracker.js.map +1 -0
- package/dist/transport.d.ts +45 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +251 -0
- package/dist/transport.js.map +1 -0
- package/dist/types.d.ts +171 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/package.json +37 -0
package/dist/crypto.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// ── 密码学提供者(浏览器 SubtleCrypto 实现)──────────────
|
|
2
|
+
// 所有操作均为异步(SubtleCrypto API 要求)
|
|
3
|
+
/** Base64 编码(浏览器兼容) */
|
|
4
|
+
function uint8ToBase64(bytes) {
|
|
5
|
+
let binary = '';
|
|
6
|
+
for (let i = 0; i < bytes.byteLength; i++) {
|
|
7
|
+
binary += String.fromCharCode(bytes[i]);
|
|
8
|
+
}
|
|
9
|
+
return btoa(binary);
|
|
10
|
+
}
|
|
11
|
+
/** Base64 解码(浏览器兼容) */
|
|
12
|
+
function base64ToUint8(b64) {
|
|
13
|
+
const binary = atob(b64);
|
|
14
|
+
const bytes = new Uint8Array(binary.length);
|
|
15
|
+
for (let i = 0; i < binary.length; i++) {
|
|
16
|
+
bytes[i] = binary.charCodeAt(i);
|
|
17
|
+
}
|
|
18
|
+
return bytes;
|
|
19
|
+
}
|
|
20
|
+
/** 将 ArrayBuffer 转为 PEM 格式字符串 */
|
|
21
|
+
function arrayBufferToPem(buffer, label) {
|
|
22
|
+
const b64 = uint8ToBase64(new Uint8Array(buffer));
|
|
23
|
+
const lines = [];
|
|
24
|
+
for (let i = 0; i < b64.length; i += 64) {
|
|
25
|
+
lines.push(b64.slice(i, i + 64));
|
|
26
|
+
}
|
|
27
|
+
return `-----BEGIN ${label}-----\n${lines.join('\n')}\n-----END ${label}-----`;
|
|
28
|
+
}
|
|
29
|
+
/** 从 PEM 字符串中提取 DER 数据 */
|
|
30
|
+
function pemToArrayBuffer(pem) {
|
|
31
|
+
const b64 = pem
|
|
32
|
+
.replace(/-----BEGIN [^-]+-----/, '')
|
|
33
|
+
.replace(/-----END [^-]+-----/, '')
|
|
34
|
+
.replace(/\s/g, '');
|
|
35
|
+
const bytes = base64ToUint8(b64);
|
|
36
|
+
return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
37
|
+
}
|
|
38
|
+
function toArrayBuffer(bytes) {
|
|
39
|
+
if (bytes instanceof ArrayBuffer) {
|
|
40
|
+
return bytes.slice(0);
|
|
41
|
+
}
|
|
42
|
+
const cloned = Uint8Array.from(bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes));
|
|
43
|
+
return cloned.buffer.slice(cloned.byteOffset, cloned.byteOffset + cloned.byteLength);
|
|
44
|
+
}
|
|
45
|
+
function toBufferSource(bytes) {
|
|
46
|
+
if (bytes instanceof ArrayBuffer) {
|
|
47
|
+
return bytes.slice(0);
|
|
48
|
+
}
|
|
49
|
+
return Uint8Array.from(bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes));
|
|
50
|
+
}
|
|
51
|
+
/** 密码学提供者 — 使用浏览器 SubtleCrypto 实现 P-256 ECDSA */
|
|
52
|
+
export class CryptoProvider {
|
|
53
|
+
static curveName = 'P-256';
|
|
54
|
+
/**
|
|
55
|
+
* 生成 P-256 ECDSA 密钥对(异步)。
|
|
56
|
+
* 返回 { private_key_pem, public_key_der_b64, curve }
|
|
57
|
+
*/
|
|
58
|
+
async generateIdentity() {
|
|
59
|
+
const keyPair = await crypto.subtle.generateKey({ name: 'ECDSA', namedCurve: 'P-256' }, true, // extractable
|
|
60
|
+
['sign', 'verify']);
|
|
61
|
+
// 导出 PKCS8 私钥
|
|
62
|
+
const pkcs8 = await crypto.subtle.exportKey('pkcs8', keyPair.privateKey);
|
|
63
|
+
const privateKeyPem = arrayBufferToPem(pkcs8, 'PRIVATE KEY');
|
|
64
|
+
// 导出 SPKI 公钥(DER 格式,base64 编码)
|
|
65
|
+
const spki = await crypto.subtle.exportKey('spki', keyPair.publicKey);
|
|
66
|
+
const publicKeyDerB64 = uint8ToBase64(new Uint8Array(spki));
|
|
67
|
+
return {
|
|
68
|
+
private_key_pem: privateKeyPem,
|
|
69
|
+
public_key_der_b64: publicKeyDerB64,
|
|
70
|
+
curve: CryptoProvider.curveName,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* 签名登录 nonce(异步)。
|
|
75
|
+
* 返回 [signatureBase64, clientTime]
|
|
76
|
+
*
|
|
77
|
+
* 签名数据格式: "{nonce}:{clientTime}"
|
|
78
|
+
* 使用 ECDSA + SHA-256
|
|
79
|
+
*/
|
|
80
|
+
async signLoginNonce(privateKeyPem, nonce, clientTime) {
|
|
81
|
+
const usedTime = clientTime ?? String(Math.floor(Date.now() / 1000));
|
|
82
|
+
const signData = new TextEncoder().encode(`${nonce}:${usedTime}`);
|
|
83
|
+
// 导入 PEM 私钥
|
|
84
|
+
const pkcs8 = pemToArrayBuffer(privateKeyPem);
|
|
85
|
+
const cryptoKey = await crypto.subtle.importKey('pkcs8', pkcs8, { name: 'ECDSA', namedCurve: 'P-256' }, false, ['sign']);
|
|
86
|
+
// 签名(SubtleCrypto 返回 IEEE P1363 格式,与 Python cryptography DER 不同)
|
|
87
|
+
const signature = await crypto.subtle.sign({ name: 'ECDSA', hash: 'SHA-256' }, cryptoKey, signData);
|
|
88
|
+
// 将 P1363 格式转为 DER 格式(与 Python SDK 兼容)
|
|
89
|
+
const derSignature = p1363ToDer(new Uint8Array(signature));
|
|
90
|
+
return [uint8ToBase64(derSignature), usedTime];
|
|
91
|
+
}
|
|
92
|
+
/** 生成客户端 nonce(12 字节随机数的 base64 编码) */
|
|
93
|
+
newClientNonce() {
|
|
94
|
+
const bytes = new Uint8Array(12);
|
|
95
|
+
crypto.getRandomValues(bytes);
|
|
96
|
+
return uint8ToBase64(bytes);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// ── 签名格式转换工具 ──────────────────────────────────────
|
|
100
|
+
/**
|
|
101
|
+
* 将 IEEE P1363 格式签名转为 DER 格式。
|
|
102
|
+
* SubtleCrypto 输出 P1363(r || s 固定长度拼接),
|
|
103
|
+
* Python cryptography 使用 DER(ASN.1 编码)。
|
|
104
|
+
*/
|
|
105
|
+
function p1363ToDer(p1363) {
|
|
106
|
+
const halfLen = p1363.length / 2;
|
|
107
|
+
const r = trimLeadingZeros(p1363.slice(0, halfLen));
|
|
108
|
+
const s = trimLeadingZeros(p1363.slice(halfLen));
|
|
109
|
+
// 若最高位为 1 需要前导 0x00(ASN.1 有符号整数)
|
|
110
|
+
const rPadded = r[0] & 0x80 ? new Uint8Array([0, ...r]) : r;
|
|
111
|
+
const sPadded = s[0] & 0x80 ? new Uint8Array([0, ...s]) : s;
|
|
112
|
+
const rTlv = new Uint8Array([0x02, rPadded.length, ...rPadded]);
|
|
113
|
+
const sTlv = new Uint8Array([0x02, sPadded.length, ...sPadded]);
|
|
114
|
+
const sequenceLen = rTlv.length + sTlv.length;
|
|
115
|
+
const der = new Uint8Array(2 + sequenceLen);
|
|
116
|
+
der[0] = 0x30; // SEQUENCE
|
|
117
|
+
der[1] = sequenceLen;
|
|
118
|
+
der.set(rTlv, 2);
|
|
119
|
+
der.set(sTlv, 2 + rTlv.length);
|
|
120
|
+
return der;
|
|
121
|
+
}
|
|
122
|
+
/** 去除前导零字节(保留至少一个字节) */
|
|
123
|
+
function trimLeadingZeros(bytes) {
|
|
124
|
+
let start = 0;
|
|
125
|
+
while (start < bytes.length - 1 && bytes[start] === 0) {
|
|
126
|
+
start++;
|
|
127
|
+
}
|
|
128
|
+
return bytes.slice(start);
|
|
129
|
+
}
|
|
130
|
+
// 导出工具函数,供其他模块使用
|
|
131
|
+
export { uint8ToBase64, base64ToUint8, arrayBufferToPem, pemToArrayBuffer, p1363ToDer, toArrayBuffer, toBufferSource };
|
|
132
|
+
//# sourceMappingURL=crypto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,gCAAgC;AAEhC,uBAAuB;AACvB,SAAS,aAAa,CAAC,KAAiB;IACtC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;AACtB,CAAC;AAED,uBAAuB;AACvB,SAAS,aAAa,CAAC,GAAW;IAChC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IACzB,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,iCAAiC;AACjC,SAAS,gBAAgB,CAAC,MAAmB,EAAE,KAAa;IAC1D,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IAClD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC;QACxC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,cAAc,KAAK,UAAU,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,KAAK,OAAO,CAAC;AACjF,CAAC;AAED,0BAA0B;AAC1B,SAAS,gBAAgB,CAAC,GAAW;IACnC,MAAM,GAAG,GAAG,GAAG;SACZ,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC;SACpC,OAAO,CAAC,qBAAqB,EAAE,EAAE,CAAC;SAClC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACtB,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IACjC,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC,UAAU,CAAgB,CAAC;AAClG,CAAC;AAED,SAAS,aAAa,CAAC,KAAiD;IACtE,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;QACjC,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACxB,CAAC;IACD,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,YAAY,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5F,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAgB,CAAC;AACtG,CAAC;AAED,SAAS,cAAc,CAAC,KAAiD;IACvE,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;QACjC,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,YAAY,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;AACtF,CAAC;AAED,iDAAiD;AACjD,MAAM,OAAO,cAAc;IACzB,MAAM,CAAU,SAAS,GAAG,OAAO,CAAC;IAEpC;;;OAGG;IACH,KAAK,CAAC,gBAAgB;QAKpB,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,WAAW,CAC7C,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,EACtC,IAAI,EAAE,cAAc;QACpB,CAAC,MAAM,EAAE,QAAQ,CAAC,CACnB,CAAC;QAEF,cAAc;QACd,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;QACzE,MAAM,aAAa,GAAG,gBAAgB,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;QAE7D,+BAA+B;QAC/B,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;QACtE,MAAM,eAAe,GAAG,aAAa,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;QAE5D,OAAO;YACL,eAAe,EAAE,aAAa;YAC9B,kBAAkB,EAAE,eAAe;YACnC,KAAK,EAAE,cAAc,CAAC,SAAS;SAChC,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,cAAc,CAClB,aAAqB,EACrB,KAAa,EACb,UAAmB;QAEnB,MAAM,QAAQ,GAAG,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;QACrE,MAAM,QAAQ,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,GAAG,KAAK,IAAI,QAAQ,EAAE,CAAC,CAAC;QAElE,YAAY;QACZ,MAAM,KAAK,GAAG,gBAAgB,CAAC,aAAa,CAAC,CAAC;QAC9C,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAC7C,OAAO,EACP,KAAK,EACL,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,EACtC,KAAK,EACL,CAAC,MAAM,CAAC,CACT,CAAC;QAEF,iEAAiE;QACjE,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CACxC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,EAClC,SAAS,EACT,QAAQ,CACT,CAAC;QAEF,uCAAuC;QACvC,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;QAC3D,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC,CAAC;IACjD,CAAC;IAED,uCAAuC;IACvC,cAAc;QACZ,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;QACjC,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QAC9B,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;;AAGH,qDAAqD;AAErD;;;;GAIG;AACH,SAAS,UAAU,CAAC,KAAiB;IACnC,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IACjC,MAAM,CAAC,GAAG,gBAAgB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;IACpD,MAAM,CAAC,GAAG,gBAAgB,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IAEjD,iCAAiC;IACjC,MAAM,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5D,MAAM,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE5D,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC;IAChE,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC;IAEhE,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAC9C,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC;IAC5C,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,WAAW;IAC1B,GAAG,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC;IACrB,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACjB,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/B,OAAO,GAAG,CAAC;AACb,CAAC;AAED,wBAAwB;AACxB,SAAS,gBAAgB,CAAC,KAAiB;IACzC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,OAAO,KAAK,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACtD,KAAK,EAAE,CAAC;IACV,CAAC;IACD,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC;AAED,iBAAiB;AACjB,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,UAAU,EAAE,aAAa,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gateway 发现服务 — 通过 .well-known 端点发现 Gateway WebSocket URL。
|
|
3
|
+
*
|
|
4
|
+
* 使用浏览器 fetch() API,不依赖任何 Node.js 模块。
|
|
5
|
+
*/
|
|
6
|
+
export declare class GatewayDiscovery {
|
|
7
|
+
private _lastHealthy;
|
|
8
|
+
/** 最近一次 health check 结果,null 表示尚未检查 */
|
|
9
|
+
get lastHealthy(): boolean | null;
|
|
10
|
+
/** 向 gatewayUrl 对应的 /health 端点发送 GET 请求,检查网关可用性。 */
|
|
11
|
+
checkHealth(gatewayUrl: string, timeout?: number): Promise<boolean>;
|
|
12
|
+
/**
|
|
13
|
+
* 从 well-known URL 发现 Gateway WebSocket 地址。
|
|
14
|
+
*
|
|
15
|
+
* 响应格式: { gateways: [{ url: "wss://...", priority: 1 }, ...] }
|
|
16
|
+
* 选择 priority 最小的网关。
|
|
17
|
+
*/
|
|
18
|
+
discover(wellKnownUrl: string, timeout?: number): Promise<string>;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AAKA;;;;GAIG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,YAAY,CAAwB;IAE5C,uCAAuC;IACvC,IAAI,WAAW,IAAI,OAAO,GAAG,IAAI,CAA8B;IAE/D,oDAAoD;IAC9C,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,SAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAmBvE;;;;;OAKG;IACG,QAAQ,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,SAAO,GAAG,OAAO,CAAC,MAAM,CAAC;CA+CtE"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// ── Gateway 发现(浏览器 fetch API)──────────────────────
|
|
2
|
+
import { ConnectionError, ValidationError } from './errors.js';
|
|
3
|
+
import { isJsonObject } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Gateway 发现服务 — 通过 .well-known 端点发现 Gateway WebSocket URL。
|
|
6
|
+
*
|
|
7
|
+
* 使用浏览器 fetch() API,不依赖任何 Node.js 模块。
|
|
8
|
+
*/
|
|
9
|
+
export class GatewayDiscovery {
|
|
10
|
+
_lastHealthy = null;
|
|
11
|
+
/** 最近一次 health check 结果,null 表示尚未检查 */
|
|
12
|
+
get lastHealthy() { return this._lastHealthy; }
|
|
13
|
+
/** 向 gatewayUrl 对应的 /health 端点发送 GET 请求,检查网关可用性。 */
|
|
14
|
+
async checkHealth(gatewayUrl, timeout = 5000) {
|
|
15
|
+
const parsed = new URL(gatewayUrl);
|
|
16
|
+
parsed.protocol = parsed.protocol === 'wss:' ? 'https:' : 'http:';
|
|
17
|
+
parsed.pathname = '/health';
|
|
18
|
+
parsed.search = '';
|
|
19
|
+
parsed.hash = '';
|
|
20
|
+
const healthUrl = parsed.toString();
|
|
21
|
+
try {
|
|
22
|
+
const controller = new AbortController();
|
|
23
|
+
const timer = globalThis.setTimeout(() => controller.abort(), timeout);
|
|
24
|
+
const resp = await fetch(healthUrl, { method: 'GET', signal: controller.signal });
|
|
25
|
+
clearTimeout(timer);
|
|
26
|
+
this._lastHealthy = resp.status === 200;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
this._lastHealthy = false;
|
|
30
|
+
}
|
|
31
|
+
return this._lastHealthy;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* 从 well-known URL 发现 Gateway WebSocket 地址。
|
|
35
|
+
*
|
|
36
|
+
* 响应格式: { gateways: [{ url: "wss://...", priority: 1 }, ...] }
|
|
37
|
+
* 选择 priority 最小的网关。
|
|
38
|
+
*/
|
|
39
|
+
async discover(wellKnownUrl, timeout = 5000) {
|
|
40
|
+
let payload;
|
|
41
|
+
try {
|
|
42
|
+
const controller = new AbortController();
|
|
43
|
+
const timer = globalThis.setTimeout(() => controller.abort(), timeout);
|
|
44
|
+
const response = await fetch(wellKnownUrl, {
|
|
45
|
+
signal: controller.signal,
|
|
46
|
+
});
|
|
47
|
+
clearTimeout(timer);
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
throw new Error(`HTTP ${response.status}`);
|
|
50
|
+
}
|
|
51
|
+
const rawPayload = await response.json();
|
|
52
|
+
if (!isJsonObject(rawPayload)) {
|
|
53
|
+
throw new ValidationError('well-known returned invalid payload');
|
|
54
|
+
}
|
|
55
|
+
payload = rawPayload;
|
|
56
|
+
}
|
|
57
|
+
catch (exc) {
|
|
58
|
+
throw new ConnectionError(`gateway discovery failed for ${wellKnownUrl}: ${exc}`, { retryable: true });
|
|
59
|
+
}
|
|
60
|
+
const gateways = payload.gateways;
|
|
61
|
+
if (!Array.isArray(gateways) || gateways.length === 0) {
|
|
62
|
+
throw new ValidationError('well-known returned empty gateways');
|
|
63
|
+
}
|
|
64
|
+
// 按 priority 排序(低优先级数字 = 高优先级)
|
|
65
|
+
const sorted = [...gateways].sort((a, b) => (Number(a.priority ?? 999)) - (Number(b.priority ?? 999)));
|
|
66
|
+
const url = sorted[0]?.url;
|
|
67
|
+
if (!url) {
|
|
68
|
+
throw new ValidationError('well-known missing gateway url');
|
|
69
|
+
}
|
|
70
|
+
// 发现后异步触发 health check(不阻塞)
|
|
71
|
+
this.checkHealth(String(url), timeout).catch(() => { });
|
|
72
|
+
return String(url);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import type { KeyStore } from './keystore/index.js';
|
|
2
|
+
import { type IdentityRecord, type JsonObject, type Message } from './types.js';
|
|
3
|
+
export interface LoadedGroupSecret {
|
|
4
|
+
epoch: number;
|
|
5
|
+
secret: Uint8Array;
|
|
6
|
+
commitment: string;
|
|
7
|
+
member_aids: string[];
|
|
8
|
+
epoch_chain?: string;
|
|
9
|
+
pending_rotation_id?: string;
|
|
10
|
+
epoch_chain_unverified?: boolean;
|
|
11
|
+
epoch_chain_unverified_reason?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* 计算 Epoch Transcript Chain 哈希(异步,SubtleCrypto SHA-256)。
|
|
15
|
+
* prev_chain=null 时使用 genesis 前缀,否则将 prev_chain hex 解码为字节。
|
|
16
|
+
*/
|
|
17
|
+
export declare function computeEpochChain(prevChain: string | null, epoch: number, commitment: string, rotatorAid: string): Promise<string>;
|
|
18
|
+
/**
|
|
19
|
+
* 验证 Epoch Chain(常量时间比较,防时序攻击)。
|
|
20
|
+
* warn-only:调用方决定是否拒绝;此函数仅返回布尔值。
|
|
21
|
+
*/
|
|
22
|
+
export declare function verifyEpochChain(epochChain: string, prevChain: string | null, epoch: number, commitment: string, rotatorAid: string): Promise<boolean>;
|
|
23
|
+
export declare function signGroupKeyResponse(payload: JsonObject, privateKeyPem: string): Promise<JsonObject>;
|
|
24
|
+
export declare function verifyGroupKeyResponseSignature(payload: JsonObject, responderCertPem: string): Promise<boolean>;
|
|
25
|
+
/** 群组加密模式 */
|
|
26
|
+
export declare const MODE_EPOCH_GROUP_KEY = "epoch_group_key";
|
|
27
|
+
/** AAD 字段定义(群组) */
|
|
28
|
+
export declare const AAD_FIELDS_GROUP: readonly ["group_id", "from", "message_id", "timestamp", "epoch", "encryption_mode", "suite"];
|
|
29
|
+
/** AAD 匹配字段(群组,不含 timestamp) */
|
|
30
|
+
export declare const AAD_MATCH_FIELDS_GROUP: readonly ["group_id", "from", "message_id", "epoch", "encryption_mode", "suite"];
|
|
31
|
+
/** 旧 epoch 默认保留时间(秒) */
|
|
32
|
+
export declare const OLD_EPOCH_RETENTION_SECONDS: number;
|
|
33
|
+
/**
|
|
34
|
+
* 加密群组消息,返回 e2ee.group_encrypted 信封(异步)。
|
|
35
|
+
*
|
|
36
|
+
* senderPrivateKeyPem: 可选,传入时为密文附加发送方 ECDSA 签名(不可否认性)。
|
|
37
|
+
*/
|
|
38
|
+
export declare function encryptGroupMessage(groupId: string, epoch: number, groupSecret: Uint8Array, payload: JsonObject, opts: {
|
|
39
|
+
fromAid: string;
|
|
40
|
+
messageId: string;
|
|
41
|
+
timestamp: number;
|
|
42
|
+
senderPrivateKeyPem?: string | null;
|
|
43
|
+
senderCertPem?: string | null;
|
|
44
|
+
}): Promise<JsonObject>;
|
|
45
|
+
/**
|
|
46
|
+
* 解密群组消息(异步)。
|
|
47
|
+
*
|
|
48
|
+
* groupSecrets: {epoch: groupSecretBytes} 映射。
|
|
49
|
+
* senderCertPem: 发送方证书,用于验证签名。
|
|
50
|
+
* requireSignature: 为 true 时(默认),若消息缺少签名或无证书可验证则拒绝(零信任模式)。
|
|
51
|
+
*/
|
|
52
|
+
export declare function decryptGroupMessage(message: Message, groupSecrets: Map<number, Uint8Array>, senderCertPem?: string | null, opts?: {
|
|
53
|
+
requireSignature?: boolean;
|
|
54
|
+
}): Promise<Message | null>;
|
|
55
|
+
/** 构建 Membership Manifest(未签名) */
|
|
56
|
+
export declare function buildMembershipManifest(groupId: string, epoch: number, prevEpoch: number | null, memberAids: string[], opts?: {
|
|
57
|
+
added?: string[];
|
|
58
|
+
removed?: string[];
|
|
59
|
+
initiatorAid?: string;
|
|
60
|
+
}): JsonObject;
|
|
61
|
+
/** 对 Membership Manifest 签名(异步),返回带 signature 字段的新 manifest */
|
|
62
|
+
export declare function signMembershipManifest(manifest: JsonObject, privateKeyPem: string): Promise<JsonObject>;
|
|
63
|
+
/** 验证 Membership Manifest 签名(异步) */
|
|
64
|
+
export declare function verifyMembershipManifest(manifest: JsonObject, initiatorCertPem: string): Promise<boolean>;
|
|
65
|
+
/** 计算 Membership Commitment(异步,使用 SubtleCrypto SHA-256) */
|
|
66
|
+
export declare function computeMembershipCommitment(memberAids: string[], epoch: number, groupId: string, groupSecret: Uint8Array): Promise<string>;
|
|
67
|
+
/** 验证 Membership Commitment(异步) */
|
|
68
|
+
export declare function verifyMembershipCommitment(commitment: string, memberAids: string[], epoch: number, groupId: string, myAid: string, groupSecret: Uint8Array): Promise<boolean>;
|
|
69
|
+
/** 存储 group_secret 到 keystore metadata(异步) */
|
|
70
|
+
export declare function storeGroupSecret(keystore: KeyStore, aid: string, groupId: string, epoch: number, groupSecret: Uint8Array, commitment: string, memberAids: string[], epochChain?: string, pendingRotationId?: string, epochChainUnverified?: boolean | null, epochChainUnverifiedReason?: string | null): Promise<boolean>;
|
|
71
|
+
/** 保存指定 epoch key;低于 current 时写入 old epoch,不覆盖 current。 */
|
|
72
|
+
export declare function storeGroupSecretEpoch(keystore: KeyStore, aid: string, groupId: string, epoch: number, groupSecret: Uint8Array, commitment: string, memberAids: string[], epochChain?: string, pendingRotationId?: string, epochChainUnverified?: boolean | null, epochChainUnverifiedReason?: string | null): Promise<boolean>;
|
|
73
|
+
/** 读取 group_secret(异步) */
|
|
74
|
+
export declare function loadGroupSecret(keystore: KeyStore, aid: string, groupId: string, epoch?: number | null): Promise<LoadedGroupSecret | null>;
|
|
75
|
+
/** 加载某群组所有 epoch 的 group_secret(异步) */
|
|
76
|
+
export declare function loadAllGroupSecrets(keystore: KeyStore, aid: string, groupId: string): Promise<Map<number, Uint8Array>>;
|
|
77
|
+
/** 清理过期的旧 epoch 记录(异步)。返回清理数量。 */
|
|
78
|
+
export declare function cleanupOldEpochs(keystore: KeyStore, aid: string, groupId: string, retentionSeconds?: number): Promise<number>;
|
|
79
|
+
/** 仅回滚指定 rotation 写入的本地 pending epoch key(异步) */
|
|
80
|
+
export declare function discardPendingGroupSecret(keystore: KeyStore, aid: string, groupId: string, epoch: number, rotationId: string): Promise<boolean>;
|
|
81
|
+
/** 删除群组的所有密钥数据(群组解散时使用,异步) */
|
|
82
|
+
export declare function deleteGroupSecret(keystore: KeyStore, aid: string, groupId: string): Promise<void>;
|
|
83
|
+
/** 生成 32 字节随机 group_secret */
|
|
84
|
+
export declare function generateGroupSecret(): Uint8Array;
|
|
85
|
+
/** 构建 group key 分发消息 payload(异步) */
|
|
86
|
+
export declare function buildKeyDistribution(groupId: string, epoch: number, groupSecret: Uint8Array, memberAids: string[], distributedBy: string, manifest?: JsonObject | null, epochChain?: string): Promise<JsonObject>;
|
|
87
|
+
/** 处理收到的 group key 分发消息(异步) */
|
|
88
|
+
export declare function handleKeyDistribution(message: Message | JsonObject, keystore: KeyStore, aid: string, initiatorCertPem?: string | null): Promise<boolean>;
|
|
89
|
+
/** 构建密钥请求 payload */
|
|
90
|
+
export declare function buildKeyRequest(groupId: string, epoch: number, requesterAid: string, requestId?: string): JsonObject;
|
|
91
|
+
/** 处理收到的密钥请求(异步) */
|
|
92
|
+
export declare function handleKeyRequest(request: Message | JsonObject, keystore: KeyStore, aid: string, currentMembers: string[], privateKeyPem?: string | null): Promise<JsonObject | null>;
|
|
93
|
+
/** 处理收到的密钥响应(异步) */
|
|
94
|
+
export declare function handleKeyResponse(response: Message | JsonObject, keystore: KeyStore, aid: string, opts?: {
|
|
95
|
+
expectedRequest?: JsonObject | null;
|
|
96
|
+
responderCertPem?: string | null;
|
|
97
|
+
currentMembers?: string[];
|
|
98
|
+
strict?: boolean;
|
|
99
|
+
}): Promise<boolean>;
|
|
100
|
+
/** epoch 降级检查 */
|
|
101
|
+
export declare function checkEpochDowngrade(messageEpoch: number, localLatestEpoch: number, opts?: {
|
|
102
|
+
allowOldEpoch?: boolean;
|
|
103
|
+
}): boolean;
|
|
104
|
+
/** 群组消息防重放守卫 */
|
|
105
|
+
export declare class GroupReplayGuard {
|
|
106
|
+
private _seen;
|
|
107
|
+
private _maxSize;
|
|
108
|
+
constructor(maxSize?: number);
|
|
109
|
+
/** 检查并记录。返回 true 表示首次(通过),false 表示重放(拒绝)。 */
|
|
110
|
+
checkAndRecord(groupId: string, senderAid: string, messageId: string): boolean;
|
|
111
|
+
/** 仅检查是否已记录 */
|
|
112
|
+
isSeen(groupId: string, senderAid: string, messageId: string): boolean;
|
|
113
|
+
/** 仅记录 */
|
|
114
|
+
record(groupId: string, senderAid: string, messageId: string): void;
|
|
115
|
+
/** LRU 裁剪(供外部调用) */
|
|
116
|
+
trim(): void;
|
|
117
|
+
get size(): number;
|
|
118
|
+
}
|
|
119
|
+
/** 群组密钥请求/响应频率限制 */
|
|
120
|
+
export declare class GroupKeyRequestThrottle {
|
|
121
|
+
private _last;
|
|
122
|
+
private _cooldown;
|
|
123
|
+
constructor(cooldown?: number);
|
|
124
|
+
/** 检查是否允许操作。返回 true 并记录时间戳,或 false 表示被限制。 */
|
|
125
|
+
allow(key: string): boolean;
|
|
126
|
+
reset(key: string): void;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* 群组端到端加密管理器 — 浏览器 SubtleCrypto 实现。
|
|
130
|
+
*
|
|
131
|
+
* 与 E2EEManager 平行:所有网络操作(P2P 发送、RPC 调用)由调用方负责。
|
|
132
|
+
* 内置防重放、epoch 降级防护、密钥请求频率限制。
|
|
133
|
+
* 所有密码学操作均为异步。
|
|
134
|
+
*/
|
|
135
|
+
export declare class GroupE2EEManager {
|
|
136
|
+
private _identityFn;
|
|
137
|
+
private _keystoreRef;
|
|
138
|
+
private _replayGuard;
|
|
139
|
+
private _requestThrottle;
|
|
140
|
+
private _responseThrottle;
|
|
141
|
+
private _senderCertResolver;
|
|
142
|
+
private _initiatorCertResolver;
|
|
143
|
+
private _pendingKeyRequests;
|
|
144
|
+
constructor(opts: {
|
|
145
|
+
identityFn: () => IdentityRecord;
|
|
146
|
+
keystore: KeyStore;
|
|
147
|
+
requestCooldown?: number;
|
|
148
|
+
responseCooldown?: number;
|
|
149
|
+
senderCertResolver?: ((aid: string) => string | null) | null;
|
|
150
|
+
initiatorCertResolver?: ((aid: string) => string | null) | null;
|
|
151
|
+
});
|
|
152
|
+
/** 用当前身份私钥签名 manifest */
|
|
153
|
+
private _signManifest;
|
|
154
|
+
/** 创建首个 epoch。返回 {epoch, commitment, distributions: [{to, payload}]}。 */
|
|
155
|
+
createEpoch(groupId: string, memberAids: string[]): Promise<JsonObject>;
|
|
156
|
+
/** 轮换 epoch(踢人/退出后调用) */
|
|
157
|
+
rotateEpoch(groupId: string, memberAids: string[]): Promise<JsonObject>;
|
|
158
|
+
/** 指定目标 epoch 号轮换(配合服务端 CAS 使用) */
|
|
159
|
+
rotateEpochTo(groupId: string, targetEpoch: number, memberAids: string[], opts?: {
|
|
160
|
+
rotationId?: string;
|
|
161
|
+
}): Promise<JsonObject>;
|
|
162
|
+
/** 手动存储 group_secret。返回 false 表示 epoch 降级被拒。 */
|
|
163
|
+
storeSecret(groupId: string, epoch: number, groupSecretBytes: Uint8Array, commitment: string, memberAids: string[], epochChain?: string): Promise<boolean>;
|
|
164
|
+
discardPendingSecret(groupId: string, epoch: number, rotationId: string): Promise<boolean>;
|
|
165
|
+
loadSecret(groupId: string, epoch?: number | null): Promise<{
|
|
166
|
+
epoch: number;
|
|
167
|
+
secret: Uint8Array;
|
|
168
|
+
commitment: string;
|
|
169
|
+
member_aids: string[];
|
|
170
|
+
epoch_chain?: string;
|
|
171
|
+
pending_rotation_id?: string;
|
|
172
|
+
} | null>;
|
|
173
|
+
loadAllSecrets(groupId: string): Promise<Map<number, Uint8Array>>;
|
|
174
|
+
cleanup(groupId: string, retentionSeconds?: number): Promise<number>;
|
|
175
|
+
/** 加密群消息(含发送方签名)。无密钥时抛 E2EEGroupSecretMissingError。 */
|
|
176
|
+
encrypt(groupId: string, payload: JsonObject, opts?: {
|
|
177
|
+
messageId?: string;
|
|
178
|
+
timestamp?: number;
|
|
179
|
+
}): Promise<JsonObject>;
|
|
180
|
+
/** 使用指定 epoch 加密群消息。 */
|
|
181
|
+
encryptWithEpoch(groupId: string, epoch: number, payload: JsonObject, opts?: {
|
|
182
|
+
messageId?: string;
|
|
183
|
+
timestamp?: number;
|
|
184
|
+
}): Promise<JsonObject>;
|
|
185
|
+
/**
|
|
186
|
+
* 解密单条群消息(异步)。内置防重放 + 发送方验签 + 外层字段校验。
|
|
187
|
+
*
|
|
188
|
+
* opts.skipReplay: 跳过防重放检查(用于 group.pull 场景)。
|
|
189
|
+
*/
|
|
190
|
+
decrypt(message: Message, opts?: {
|
|
191
|
+
skipReplay?: boolean;
|
|
192
|
+
}): Promise<Message | null>;
|
|
193
|
+
/** 批量解密 */
|
|
194
|
+
decryptBatch(messages: Message[], opts?: {
|
|
195
|
+
skipReplay?: boolean;
|
|
196
|
+
}): Promise<Message[]>;
|
|
197
|
+
/**
|
|
198
|
+
* 处理已解密的 P2P 密钥消息(异步)。
|
|
199
|
+
*
|
|
200
|
+
* 返回 "distribution"/"request"/"response" 表示已成功处理。
|
|
201
|
+
* 返回 "distribution_rejected"/"response_rejected" 表示被拒绝。
|
|
202
|
+
* 返回 null 表示不是密钥消息。
|
|
203
|
+
*/
|
|
204
|
+
handleIncoming(payload: JsonObject): Promise<string | null>;
|
|
205
|
+
/** 构建恢复请求。返回 {to, payload} 或 null(限流/无目标)。 */
|
|
206
|
+
buildRecoveryRequest(groupId: string, epoch: number, opts?: {
|
|
207
|
+
senderAid?: string;
|
|
208
|
+
}): Promise<JsonObject | null>;
|
|
209
|
+
rememberKeyRequest(payload: JsonObject, expectedResponderAid?: string | null): void;
|
|
210
|
+
/** 处理密钥请求(受频率限制 + 成员资格验证) */
|
|
211
|
+
handleKeyRequestMsg(requestPayload: JsonObject, currentMembers: string[]): Promise<JsonObject | null>;
|
|
212
|
+
hasSecret(groupId: string): Promise<boolean>;
|
|
213
|
+
currentEpoch(groupId: string): Promise<number | null>;
|
|
214
|
+
getMemberAids(groupId: string): Promise<string[]>;
|
|
215
|
+
/** 清理过期缓存(replay guard 等),供外部定时调用 */
|
|
216
|
+
cleanExpiredCaches(): void;
|
|
217
|
+
/** 删除群组的所有本地状态(群组解散时使用,异步) */
|
|
218
|
+
removeGroup(groupId: string): Promise<void>;
|
|
219
|
+
private _currentAid;
|
|
220
|
+
}
|
|
221
|
+
//# sourceMappingURL=e2ee-group.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e2ee-group.d.ts","sourceRoot":"","sources":["../src/e2ee-group.ts"],"names":[],"mappings":"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"}
|