@agentunion/fastaun 0.2.20 → 0.3.0

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.
Files changed (98) hide show
  1. package/CHANGELOG.md +46 -23
  2. package/_packed_docs/CHANGELOG.md +46 -23
  3. package/_packed_docs/protocol/15-/347/246/273/347/272/277/346/216/250/351/200/201/351/200/232/347/237/245/345/215/217/350/256/256.md +419 -0
  4. package/_packed_docs/protocol/index.md +13 -3
  5. package/_packed_docs/python-sdk-v2-only-changelog.md +189 -0
  6. package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +39 -16
  7. package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +90 -39
  8. package/dist/auth.js +24 -7
  9. package/dist/auth.js.map +1 -1
  10. package/dist/client.d.ts +115 -166
  11. package/dist/client.js +2006 -3427
  12. package/dist/client.js.map +1 -1
  13. package/dist/config.d.ts +0 -4
  14. package/dist/config.js +0 -4
  15. package/dist/config.js.map +1 -1
  16. package/dist/e2ee.d.ts +5 -139
  17. package/dist/e2ee.js +4 -1151
  18. package/dist/e2ee.js.map +1 -1
  19. package/dist/errors.d.ts +0 -8
  20. package/dist/errors.js +0 -14
  21. package/dist/errors.js.map +1 -1
  22. package/dist/index.d.ts +9 -5
  23. package/dist/index.js +6 -3
  24. package/dist/index.js.map +1 -1
  25. package/dist/keystore/aid-db.d.ts +12 -61
  26. package/dist/keystore/aid-db.js +41 -539
  27. package/dist/keystore/aid-db.js.map +1 -1
  28. package/dist/keystore/file.d.ts +5 -41
  29. package/dist/keystore/file.js +8 -64
  30. package/dist/keystore/file.js.map +1 -1
  31. package/dist/keystore/index.d.ts +1 -49
  32. package/dist/namespaces/auth.js +4 -2
  33. package/dist/namespaces/auth.js.map +1 -1
  34. package/dist/protected-headers.d.ts +13 -0
  35. package/dist/protected-headers.js +47 -0
  36. package/dist/protected-headers.js.map +1 -0
  37. package/dist/seq-tracker.d.ts +7 -2
  38. package/dist/seq-tracker.js +31 -10
  39. package/dist/seq-tracker.js.map +1 -1
  40. package/dist/types.d.ts +0 -56
  41. package/dist/v2/crypto/aead.d.ts +20 -0
  42. package/dist/v2/crypto/aead.js +59 -0
  43. package/dist/v2/crypto/aead.js.map +1 -0
  44. package/dist/v2/crypto/canonical.d.ts +20 -0
  45. package/dist/v2/crypto/canonical.js +119 -0
  46. package/dist/v2/crypto/canonical.js.map +1 -0
  47. package/dist/v2/crypto/dh-path.d.ts +39 -0
  48. package/dist/v2/crypto/dh-path.js +55 -0
  49. package/dist/v2/crypto/dh-path.js.map +1 -0
  50. package/dist/v2/crypto/ecdh.d.ts +29 -0
  51. package/dist/v2/crypto/ecdh.js +122 -0
  52. package/dist/v2/crypto/ecdh.js.map +1 -0
  53. package/dist/v2/crypto/ecdsa.d.ts +29 -0
  54. package/dist/v2/crypto/ecdsa.js +120 -0
  55. package/dist/v2/crypto/ecdsa.js.map +1 -0
  56. package/dist/v2/crypto/hkdf.d.ts +19 -0
  57. package/dist/v2/crypto/hkdf.js +47 -0
  58. package/dist/v2/crypto/hkdf.js.map +1 -0
  59. package/dist/v2/crypto/index.d.ts +8 -0
  60. package/dist/v2/crypto/index.js +8 -0
  61. package/dist/v2/crypto/index.js.map +1 -0
  62. package/dist/v2/crypto/recipients.d.ts +32 -0
  63. package/dist/v2/crypto/recipients.js +183 -0
  64. package/dist/v2/crypto/recipients.js.map +1 -0
  65. package/dist/v2/e2ee/decrypt.d.ts +29 -0
  66. package/dist/v2/e2ee/decrypt.js +159 -0
  67. package/dist/v2/e2ee/decrypt.js.map +1 -0
  68. package/dist/v2/e2ee/encrypt-group.d.ts +17 -0
  69. package/dist/v2/e2ee/encrypt-group.js +143 -0
  70. package/dist/v2/e2ee/encrypt-group.js.map +1 -0
  71. package/dist/v2/e2ee/encrypt-p2p.d.ts +31 -0
  72. package/dist/v2/e2ee/encrypt-p2p.js +190 -0
  73. package/dist/v2/e2ee/encrypt-p2p.js.map +1 -0
  74. package/dist/v2/e2ee/index.d.ts +9 -0
  75. package/dist/v2/e2ee/index.js +9 -0
  76. package/dist/v2/e2ee/index.js.map +1 -0
  77. package/dist/v2/e2ee/metadata-auth.d.ts +15 -0
  78. package/dist/v2/e2ee/metadata-auth.js +50 -0
  79. package/dist/v2/e2ee/metadata-auth.js.map +1 -0
  80. package/dist/v2/e2ee/types.d.ts +57 -0
  81. package/dist/v2/e2ee/types.js +7 -0
  82. package/dist/v2/e2ee/types.js.map +1 -0
  83. package/dist/v2/session/index.d.ts +4 -0
  84. package/dist/v2/session/index.js +3 -0
  85. package/dist/v2/session/index.js.map +1 -0
  86. package/dist/v2/session/keystore.d.ts +41 -0
  87. package/dist/v2/session/keystore.js +103 -0
  88. package/dist/v2/session/keystore.js.map +1 -0
  89. package/dist/v2/session/session.d.ts +97 -0
  90. package/dist/v2/session/session.js +242 -0
  91. package/dist/v2/session/session.js.map +1 -0
  92. package/dist/v2/state/commitment.d.ts +58 -0
  93. package/dist/v2/state/commitment.js +85 -0
  94. package/dist/v2/state/commitment.js.map +1 -0
  95. package/dist/v2/state/index.d.ts +2 -0
  96. package/dist/v2/state/index.js +2 -0
  97. package/dist/v2/state/index.js.map +1 -0
  98. package/package.json +4 -3
@@ -0,0 +1,159 @@
1
+ /**
2
+ * AUN E2EE V2: 统一解密引擎
3
+ *
4
+ * 支持 P2P 和 Group 消息解密(按 envelope.type / 字段结构分流)。
5
+ * 纯计算,无 IO。
6
+ *
7
+ * 与 Python `aun_core.v2.e2ee.decrypt.decrypt_message` 对齐。
8
+ *
9
+ * 流程:
10
+ * 1. 验 sender_signature
11
+ * 2. 找自己的 row(recipients 数组或 per-device recipient + 可选 merkle_proof)
12
+ * 3. 计算 wrap_salt
13
+ * 4. 派生 wrap_key(3DH 或 1DH)
14
+ * 5. 解 master_key
15
+ * 6. 解 body
16
+ * 7. 解析 JSON payload
17
+ */
18
+ import { createHash } from 'node:crypto';
19
+ import { canonicalJson } from '../crypto/canonical.js';
20
+ import { ecdsaVerifyRaw } from '../crypto/ecdsa.js';
21
+ import { ecdhComputeShared } from '../crypto/ecdh.js';
22
+ import { hkdfSha256 } from '../crypto/hkdf.js';
23
+ import { aesGcmDecrypt } from '../crypto/aead.js';
24
+ import { computeLeafHash, computeRecipientsDigest, verifyMerkleProof, } from '../crypto/recipients.js';
25
+ import { SUITE_NAME } from './types.js';
26
+ const TEXT = new TextEncoder();
27
+ const INFO_3DH = TEXT.encode('AUN-V2-3DH');
28
+ const INFO_1DH = TEXT.encode('AUN-V2-1DH');
29
+ /**
30
+ * 解密 V2 加密消息(P2P 或 Group)。
31
+ *
32
+ * @param envelope 完整 envelope(已 JSON.parse 的对象)
33
+ * @param selfAid 接收方 AID
34
+ * @param selfDeviceId 接收方 device_id
35
+ * @param selfIkPriv 接收方 IK 私钥(32B scalar)
36
+ * @param selfSpkPriv 接收方 SPK 私钥(32B scalar);undefined/null 表示无 SPK(1DH)
37
+ * @param senderPubDer 发送方 AID 主公钥(DER),用于验签 + 3DH 接收侧 DH2
38
+ * @returns 解密后的 payload;null 表示在 recipients 中找不到自己的 row
39
+ */
40
+ export function decryptMessage(envelope, selfAid, selfDeviceId, selfIkPriv, selfSpkPriv, senderPubDer) {
41
+ // 1. 验签
42
+ if (!verifySenderSignature(envelope, senderPubDer)) {
43
+ throw new Error('sender_signature verification failed');
44
+ }
45
+ // 2. 找自己的 row
46
+ let row = null;
47
+ if (Array.isArray(envelope.recipients)) {
48
+ const rows = envelope.recipients;
49
+ const expectedDigest = String(envelope.recipients_digest ?? '');
50
+ if (computeRecipientsDigest(rows) !== expectedDigest) {
51
+ throw new Error('recipients_digest mismatch');
52
+ }
53
+ row = findMyRow(rows, selfAid, selfDeviceId);
54
+ if (!row)
55
+ return null;
56
+ }
57
+ else if (envelope.recipient && typeof envelope.recipient === 'object') {
58
+ const r = envelope.recipient;
59
+ row = [
60
+ String(r.aid ?? ''),
61
+ String(r.device_id ?? ''),
62
+ String(r.role ?? ''),
63
+ String(r.key_source ?? ''),
64
+ String(r.fp ?? ''),
65
+ String(r.spk_id ?? ''),
66
+ String(r.wrap_nonce ?? ''),
67
+ String(r.wrapped_key ?? ''),
68
+ ];
69
+ // per-device 形态可能携带 merkle_proof
70
+ const proof = envelope.merkle_proof;
71
+ const expectedRoot = String(envelope.recipients_digest ?? '');
72
+ if (proof && expectedRoot) {
73
+ const leaf = computeLeafHash(row);
74
+ if (!verifyMerkleProof(leaf, proof, expectedRoot)) {
75
+ // 服务端篡改/替换 wrap,拒绝
76
+ return null;
77
+ }
78
+ }
79
+ }
80
+ else {
81
+ return null;
82
+ }
83
+ // 3. wrap_salt
84
+ const senderSessionPkDer = new Uint8Array(Buffer.from(String(envelope.sender_session_pk ?? ''), 'base64'));
85
+ const aad = envelope.aad;
86
+ const aadBytes = canonicalJson(aad);
87
+ const suiteStr = String(envelope.suite ?? SUITE_NAME);
88
+ const wrapSalt = computeWrapSalt(aadBytes, senderSessionPkDer, suiteStr);
89
+ // 4. wrap_key
90
+ const wrapKey = computeWrapKey(row, selfIkPriv, selfSpkPriv, senderSessionPkDer, senderPubDer, wrapSalt);
91
+ // 5. decrypt master_key
92
+ const wrapNonce = new Uint8Array(Buffer.from(row[6], 'base64'));
93
+ const wrappedKey = new Uint8Array(Buffer.from(row[7], 'base64'));
94
+ if (wrappedKey.length < 16) {
95
+ throw new Error('wrapped_key too short');
96
+ }
97
+ const wrappedCt = wrappedKey.subarray(0, wrappedKey.length - 16);
98
+ const wrappedTag = wrappedKey.subarray(wrappedKey.length - 16);
99
+ const masterKey = aesGcmDecrypt(wrapKey, wrapNonce, wrappedCt, wrappedTag, new Uint8Array(0));
100
+ // 6. decrypt body
101
+ const msgNonce = new Uint8Array(Buffer.from(String(envelope.nonce ?? ''), 'base64'));
102
+ const ct = new Uint8Array(Buffer.from(String(envelope.ciphertext ?? ''), 'base64'));
103
+ const tag = new Uint8Array(Buffer.from(String(envelope.tag ?? ''), 'base64'));
104
+ const plaintext = aesGcmDecrypt(masterKey, msgNonce, ct, tag, aadBytes);
105
+ // 7. parse JSON
106
+ return JSON.parse(Buffer.from(plaintext).toString('utf-8'));
107
+ }
108
+ function computeWrapSalt(aadBytes, senderSessionPkDer, suiteStr) {
109
+ const suiteBytes = TEXT.encode(suiteStr);
110
+ const h = createHash('sha256');
111
+ h.update(Buffer.from(aadBytes));
112
+ h.update(Buffer.from(senderSessionPkDer));
113
+ h.update(Buffer.from(suiteBytes));
114
+ return new Uint8Array(h.digest()).subarray(0, 16);
115
+ }
116
+ function computeWrapKey(row, selfIkPriv, selfSpkPriv, senderSessionPkDer, senderMasterPkDer, salt) {
117
+ const spkId = row[5];
118
+ if (spkId && selfSpkPriv) {
119
+ // 3DH 接收方:DH1=ECDH(self_ik, sender_session);DH2=ECDH(self_spk, sender_master);DH3=ECDH(self_spk, sender_session)
120
+ const dh1 = ecdhComputeShared(selfIkPriv, senderSessionPkDer);
121
+ const dh2 = ecdhComputeShared(selfSpkPriv, senderMasterPkDer);
122
+ const dh3 = ecdhComputeShared(selfSpkPriv, senderSessionPkDer);
123
+ const ikm = new Uint8Array(96);
124
+ ikm.set(dh1, 0);
125
+ ikm.set(dh2, 32);
126
+ ikm.set(dh3, 64);
127
+ return hkdfSha256(ikm, salt, INFO_3DH, 32);
128
+ }
129
+ // 1DH 接收方
130
+ const dh1 = ecdhComputeShared(selfIkPriv, senderSessionPkDer);
131
+ return hkdfSha256(dh1, salt, INFO_1DH, 32);
132
+ }
133
+ function findMyRow(rows, aid, deviceId) {
134
+ for (const r of rows) {
135
+ if (r[0] === aid && r[1] === deviceId)
136
+ return r;
137
+ }
138
+ return null;
139
+ }
140
+ function verifySenderSignature(envelope, senderPubDer) {
141
+ const sigStr = envelope.sender_signature;
142
+ const ctStr = envelope.ciphertext;
143
+ const tagStr = envelope.tag;
144
+ const digestHex = envelope.recipients_digest;
145
+ if (typeof sigStr !== 'string' ||
146
+ typeof ctStr !== 'string' ||
147
+ typeof tagStr !== 'string' ||
148
+ typeof digestHex !== 'string') {
149
+ return false;
150
+ }
151
+ const sig = new Uint8Array(Buffer.from(sigStr, 'base64'));
152
+ const ct = Buffer.from(ctStr, 'base64');
153
+ const tag = Buffer.from(tagStr, 'base64');
154
+ const aadBytes = canonicalJson(envelope.aad);
155
+ const digestBytes = Buffer.from(digestHex, 'hex');
156
+ const signInput = new Uint8Array(Buffer.concat([ct, tag, Buffer.from(aadBytes), digestBytes]));
157
+ return ecdsaVerifyRaw(senderPubDer, sig, signInput);
158
+ }
159
+ //# sourceMappingURL=decrypt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decrypt.js","sourceRoot":"","sources":["../../../src/v2/e2ee/decrypt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * AUN E2EE V2: Group 加密引擎
3
+ *
4
+ * 构造完整的 `e2ee.group_encrypted` envelope。纯计算,无 IO。
5
+ *
6
+ * 与 Python `aun_core.v2.e2ee.encrypt_group.encrypt_group_message` 对齐。
7
+ *
8
+ * 与 P2P 同构,AAD 多 group_id / epoch / state_commitment;envelope 顶层多
9
+ * group_id / epoch,无 to / t_supplement。
10
+ */
11
+ import { Sender, Target, EncryptOptions, StateCommitmentAAD } from './types.js';
12
+ /**
13
+ * 构造完整的 V2 Group 加密 envelope。
14
+ *
15
+ * @param stateCommitment 可选;缺省时写入占位(state_version=0)以兼容未启用 state 的群。
16
+ */
17
+ export declare function encryptGroupMessage(sender: Sender, groupId: string, epoch: number, targets: Target[], payload: Record<string, unknown>, opts?: EncryptOptions, stateCommitment?: StateCommitmentAAD | null): Record<string, unknown>;
@@ -0,0 +1,143 @@
1
+ /**
2
+ * AUN E2EE V2: Group 加密引擎
3
+ *
4
+ * 构造完整的 `e2ee.group_encrypted` envelope。纯计算,无 IO。
5
+ *
6
+ * 与 Python `aun_core.v2.e2ee.encrypt_group.encrypt_group_message` 对齐。
7
+ *
8
+ * 与 P2P 同构,AAD 多 group_id / epoch / state_commitment;envelope 顶层多
9
+ * group_id / epoch,无 to / t_supplement。
10
+ */
11
+ import { createHash, randomUUID, randomBytes } from 'node:crypto';
12
+ import { canonicalJson } from '../crypto/canonical.js';
13
+ import { ecdsaSignRaw } from '../crypto/ecdsa.js';
14
+ import { aesGcmEncrypt } from '../crypto/aead.js';
15
+ import { generateP256Keypair } from '../crypto/ecdh.js';
16
+ import { compute3DHWrap, compute1DHWrap } from '../crypto/dh-path.js';
17
+ import { sortRecipients, computeRecipientsDigest } from '../crypto/recipients.js';
18
+ import { SUITE_NAME, } from './types.js';
19
+ import { withMetadataAuth, PROTECTED_HEADERS_DOMAIN, PROTECTED_CONTEXT_DOMAIN } from './metadata-auth.js';
20
+ import { normalizeProtectedHeaders } from './encrypt-p2p.js';
21
+ const TEXT = new TextEncoder();
22
+ /**
23
+ * 构造完整的 V2 Group 加密 envelope。
24
+ *
25
+ * @param stateCommitment 可选;缺省时写入占位(state_version=0)以兼容未启用 state 的群。
26
+ */
27
+ export function encryptGroupMessage(sender, groupId, epoch, targets, payload, opts = {}, stateCommitment) {
28
+ const masterKey = new Uint8Array(randomBytes(32));
29
+ const msgNonce = new Uint8Array(randomBytes(12));
30
+ const messageId = opts.messageId ?? `m-${randomUUID().replace(/-/g, '')}`;
31
+ const timestamp = opts.timestamp ?? Date.now();
32
+ // wrap_protocol_str
33
+ const protocolSet = new Set();
34
+ for (const t of targets) {
35
+ const has3DH = !!t.spkPkDer &&
36
+ (t.keySource === 'peer_device_prekey' || t.keySource === 'group_device_prekey');
37
+ protocolSet.add(has3DH ? '3DH' : '1DH');
38
+ }
39
+ const wrapProtocolStr = protocolSet.size === 0 ? '1DH' : [...protocolSet].sort().join('+');
40
+ // state_commitment(缺省占位)
41
+ const sc = stateCommitment ?? {};
42
+ const stateCommitmentAAD = {
43
+ state_version: Number(sc.state_version ?? 0) || 0,
44
+ state_hash: String(sc.state_hash ?? ''),
45
+ state_chain: String(sc.state_chain ?? ''),
46
+ };
47
+ const aad = {
48
+ from: sender.aid,
49
+ from_device: sender.deviceId,
50
+ group_id: groupId,
51
+ epoch,
52
+ message_id: messageId,
53
+ timestamp,
54
+ suite: SUITE_NAME,
55
+ wrap_protocol: wrapProtocolStr,
56
+ state_commitment: stateCommitmentAAD,
57
+ };
58
+ const plaintextBytes = canonicalJson(payload);
59
+ const aadBytes = canonicalJson(aad);
60
+ const { ciphertext, tag } = aesGcmEncrypt(masterKey, msgNonce, plaintextBytes, aadBytes);
61
+ const [senderSessionPriv, senderSessionPubDer] = generateP256Keypair();
62
+ // wrap_salt = SHA256(canonical_aad || sender_session_pk_der || suite)[:16]
63
+ const wrapSalt = computeWrapSalt(aadBytes, senderSessionPubDer);
64
+ const recipientsRows = [];
65
+ for (const target of targets) {
66
+ recipientsRows.push(wrapForRecipient(target, masterKey, senderSessionPriv, sender.ikPriv, wrapSalt));
67
+ }
68
+ const sortedRows = sortRecipients(recipientsRows);
69
+ const digestHex = computeRecipientsDigest(sortedRows);
70
+ const digestBytes = Buffer.from(digestHex, 'hex');
71
+ const signInput = Buffer.concat([
72
+ Buffer.from(ciphertext),
73
+ Buffer.from(tag),
74
+ Buffer.from(aadBytes),
75
+ digestBytes,
76
+ ]);
77
+ const senderSig = ecdsaSignRaw(sender.ikPriv, new Uint8Array(signInput));
78
+ const certFpHash = createHash('sha256').update(Buffer.from(sender.ikPubDer)).digest('hex');
79
+ const certFp = `sha256:${certFpHash.substring(0, 16)}`;
80
+ const envelope = {
81
+ type: 'e2ee.group_encrypted',
82
+ version: 'v2',
83
+ suite: SUITE_NAME,
84
+ msg_type: 'original',
85
+ group_id: groupId,
86
+ epoch,
87
+ t_send: timestamp,
88
+ t_server: null,
89
+ nonce: Buffer.from(msgNonce).toString('base64'),
90
+ ciphertext: Buffer.from(ciphertext).toString('base64'),
91
+ tag: Buffer.from(tag).toString('base64'),
92
+ sender_signature: Buffer.from(senderSig).toString('base64'),
93
+ sender_cert_fingerprint: certFp,
94
+ sender_session_pk: Buffer.from(senderSessionPubDer).toString('base64'),
95
+ recipients_digest: digestHex,
96
+ recipients: sortedRows,
97
+ aad,
98
+ };
99
+ // protected_headers / context:HMAC 签名,不进 AAD。
100
+ // payload_type 自动注入 + value 转 string(与 Python _normalize_headers 对齐)
101
+ const normalizedHeaders = normalizeProtectedHeaders(opts.protectedHeaders, payload);
102
+ if (Object.keys(normalizedHeaders).length > 0) {
103
+ envelope.protected_headers = withMetadataAuth(normalizedHeaders, masterKey, PROTECTED_HEADERS_DOMAIN);
104
+ }
105
+ if (opts.context && typeof opts.context === 'object' && !Array.isArray(opts.context) && Object.keys(opts.context).length > 0) {
106
+ envelope.context = withMetadataAuth(opts.context, masterKey, PROTECTED_CONTEXT_DOMAIN);
107
+ }
108
+ return envelope;
109
+ }
110
+ function computeWrapSalt(aadBytes, senderSessionPubDer) {
111
+ const suiteBytes = TEXT.encode(SUITE_NAME);
112
+ const h = createHash('sha256');
113
+ h.update(Buffer.from(aadBytes));
114
+ h.update(Buffer.from(senderSessionPubDer));
115
+ h.update(Buffer.from(suiteBytes));
116
+ return new Uint8Array(h.digest()).subarray(0, 16);
117
+ }
118
+ function wrapForRecipient(target, masterKey, senderSessionPriv, senderMasterPriv, wrapSalt) {
119
+ const fpHash = createHash('sha256').update(Buffer.from(target.ikPkDer)).digest('hex');
120
+ const fp = `sha256:${fpHash.substring(0, 16)}`;
121
+ const wrapNonce = new Uint8Array(randomBytes(12));
122
+ let wrapKey;
123
+ if (target.spkPkDer &&
124
+ (target.keySource === 'peer_device_prekey' || target.keySource === 'group_device_prekey')) {
125
+ wrapKey = compute3DHWrap(senderSessionPriv, senderMasterPriv, target.ikPkDer, target.spkPkDer, wrapSalt);
126
+ }
127
+ else {
128
+ wrapKey = compute1DHWrap(senderSessionPriv, target.ikPkDer, wrapSalt);
129
+ }
130
+ const { ciphertext: wrappedCt, tag: wrappedTag } = aesGcmEncrypt(wrapKey, wrapNonce, masterKey, new Uint8Array(0));
131
+ const wrappedKey = Buffer.concat([Buffer.from(wrappedCt), Buffer.from(wrappedTag)]);
132
+ return [
133
+ target.aid,
134
+ target.deviceId,
135
+ target.role,
136
+ target.keySource,
137
+ fp,
138
+ target.spkId ?? '',
139
+ Buffer.from(wrapNonce).toString('base64'),
140
+ wrappedKey.toString('base64'),
141
+ ];
142
+ }
143
+ //# sourceMappingURL=encrypt-group.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encrypt-group.js","sourceRoot":"","sources":["../../../src/v2/e2ee/encrypt-group.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * AUN E2EE V2: P2P 加密引擎
3
+ *
4
+ * 构造完整的 `e2ee.p2p_encrypted` envelope。纯计算,无 IO。
5
+ *
6
+ * 与 Python `aun_core.v2.e2ee.encrypt_p2p.encrypt_p2p_message` 对齐。
7
+ *
8
+ * 步骤:
9
+ * 1. 生成 master_key + msg_nonce
10
+ * 2. 构造 message_id / timestamp
11
+ * 3. 推导 peer_aid 与 wrap_protocol_str
12
+ * 4. 构造 AAD 并加密 payload
13
+ * 5. 生成 sender_session keypair
14
+ * 6. 计算 wrap_salt
15
+ * 7. 为每个 target wrap master_key
16
+ * 8. 排序 recipients + 计算 digest
17
+ * 9. 计算 sender_signature
18
+ * 10. 计算 sender_cert_fingerprint
19
+ * 11. 组装 envelope
20
+ */
21
+ import { type ProtectedHeadersInput } from '../../protected-headers.js';
22
+ import { Sender, TargetSet, EncryptOptions } from './types.js';
23
+ /**
24
+ * 构造完整的 V2 P2P 加密 envelope。
25
+ */
26
+ export declare function encryptP2PMessage(sender: Sender, targetSet: TargetSet, payload: Record<string, unknown>, opts?: EncryptOptions): Record<string, unknown>;
27
+ /**
28
+ * 规范化 protected_headers:value 转 string + 自动注入 payload_type。
29
+ * 与 Python `_normalize_headers` 对齐。
30
+ */
31
+ export declare function normalizeProtectedHeaders(headers: ProtectedHeadersInput, payload: Record<string, unknown>): Record<string, string>;
@@ -0,0 +1,190 @@
1
+ /**
2
+ * AUN E2EE V2: P2P 加密引擎
3
+ *
4
+ * 构造完整的 `e2ee.p2p_encrypted` envelope。纯计算,无 IO。
5
+ *
6
+ * 与 Python `aun_core.v2.e2ee.encrypt_p2p.encrypt_p2p_message` 对齐。
7
+ *
8
+ * 步骤:
9
+ * 1. 生成 master_key + msg_nonce
10
+ * 2. 构造 message_id / timestamp
11
+ * 3. 推导 peer_aid 与 wrap_protocol_str
12
+ * 4. 构造 AAD 并加密 payload
13
+ * 5. 生成 sender_session keypair
14
+ * 6. 计算 wrap_salt
15
+ * 7. 为每个 target wrap master_key
16
+ * 8. 排序 recipients + 计算 digest
17
+ * 9. 计算 sender_signature
18
+ * 10. 计算 sender_cert_fingerprint
19
+ * 11. 组装 envelope
20
+ */
21
+ import { createHash, randomUUID, randomBytes } from 'node:crypto';
22
+ import { canonicalJson } from '../crypto/canonical.js';
23
+ import { ecdsaSignRaw } from '../crypto/ecdsa.js';
24
+ import { aesGcmEncrypt } from '../crypto/aead.js';
25
+ import { generateP256Keypair } from '../crypto/ecdh.js';
26
+ import { compute3DHWrap, compute1DHWrap } from '../crypto/dh-path.js';
27
+ import { sortRecipients, computeRecipientsDigest } from '../crypto/recipients.js';
28
+ import { ProtectedHeaders } from '../../protected-headers.js';
29
+ import { SUITE_NAME, } from './types.js';
30
+ import { withMetadataAuth, PROTECTED_HEADERS_DOMAIN, PROTECTED_CONTEXT_DOMAIN } from './metadata-auth.js';
31
+ const TEXT = new TextEncoder();
32
+ /**
33
+ * 构造完整的 V2 P2P 加密 envelope。
34
+ */
35
+ export function encryptP2PMessage(sender, targetSet, payload, opts = {}) {
36
+ // 1. master_key + msg_nonce
37
+ const masterKey = new Uint8Array(randomBytes(32));
38
+ const msgNonce = new Uint8Array(randomBytes(12));
39
+ // 2. message_id + timestamp
40
+ const messageId = opts.messageId ?? `m-${randomUUID().replace(/-/g, '')}`;
41
+ const timestamp = opts.timestamp ?? Date.now();
42
+ // 3. peer_aid(首个非 audit 的 target.aid;与 Python 一致)
43
+ let peerAid = '';
44
+ for (const t of targetSet.targets) {
45
+ if (t.role !== 'audit') {
46
+ peerAid = t.aid;
47
+ break;
48
+ }
49
+ }
50
+ // 4. wrap_protocol_str
51
+ const allTargets = [
52
+ ...targetSet.targets,
53
+ ...(targetSet.auditRecipients ?? []),
54
+ ];
55
+ const protocolSet = new Set();
56
+ for (const t of allTargets) {
57
+ const has3DH = !!t.spkPkDer &&
58
+ (t.keySource === 'peer_device_prekey' || t.keySource === 'group_device_prekey');
59
+ protocolSet.add(has3DH ? '3DH' : '1DH');
60
+ }
61
+ const wrapProtocolStr = protocolSet.size === 0 ? '1DH' : [...protocolSet].sort().join('+');
62
+ // 5. AAD(顺序在 canonical_json 时由键名排序统一,这里只是构造对象)
63
+ const aad = {
64
+ from: sender.aid,
65
+ from_device: sender.deviceId,
66
+ to: peerAid,
67
+ message_id: messageId,
68
+ timestamp,
69
+ suite: SUITE_NAME,
70
+ wrap_protocol: wrapProtocolStr,
71
+ };
72
+ // 6. encrypt body
73
+ const plaintextBytes = canonicalJson(payload);
74
+ const aadBytes = canonicalJson(aad);
75
+ const { ciphertext, tag } = aesGcmEncrypt(masterKey, msgNonce, plaintextBytes, aadBytes);
76
+ // 7. sender_session keypair
77
+ const [senderSessionPriv, senderSessionPubDer] = generateP256Keypair();
78
+ // 8. wrap_salt = SHA256(canonical_aad || sender_session_pk_der || suite)[:16]
79
+ const wrapSalt = computeWrapSalt(aadBytes, senderSessionPubDer);
80
+ // 9. wrap recipients
81
+ const recipientsRows = [];
82
+ for (const target of allTargets) {
83
+ recipientsRows.push(wrapForRecipient(target, masterKey, senderSessionPriv, sender.ikPriv, wrapSalt));
84
+ }
85
+ // 10. sort + digest
86
+ const sortedRows = sortRecipients(recipientsRows);
87
+ const digestHex = computeRecipientsDigest(sortedRows);
88
+ // 11. sender_signature
89
+ const digestBytes = Buffer.from(digestHex, 'hex');
90
+ const signInput = Buffer.concat([
91
+ Buffer.from(ciphertext),
92
+ Buffer.from(tag),
93
+ Buffer.from(aadBytes),
94
+ digestBytes,
95
+ ]);
96
+ const senderSig = ecdsaSignRaw(sender.ikPriv, new Uint8Array(signInput));
97
+ // 12. cert_fingerprint
98
+ const certFpHash = createHash('sha256').update(Buffer.from(sender.ikPubDer)).digest('hex');
99
+ const certFp = `sha256:${certFpHash.substring(0, 16)}`;
100
+ const envelope = {
101
+ type: 'e2ee.p2p_encrypted',
102
+ version: 'v2',
103
+ suite: SUITE_NAME,
104
+ msg_type: 'original',
105
+ t_send: timestamp,
106
+ t_supplement: null,
107
+ t_server: null,
108
+ nonce: Buffer.from(msgNonce).toString('base64'),
109
+ ciphertext: Buffer.from(ciphertext).toString('base64'),
110
+ tag: Buffer.from(tag).toString('base64'),
111
+ sender_signature: Buffer.from(senderSig).toString('base64'),
112
+ sender_cert_fingerprint: certFp,
113
+ sender_session_pk: Buffer.from(senderSessionPubDer).toString('base64'),
114
+ recipients_digest: digestHex,
115
+ recipients: sortedRows,
116
+ aad,
117
+ };
118
+ // protected_headers / context:HMAC 签名,不进 AAD。
119
+ // payload_type 自动注入 + value 转 string(与 Python _normalize_headers 对齐)
120
+ const normalizedHeaders = normalizeProtectedHeaders(opts.protectedHeaders, payload);
121
+ if (Object.keys(normalizedHeaders).length > 0) {
122
+ envelope.protected_headers = withMetadataAuth(normalizedHeaders, masterKey, PROTECTED_HEADERS_DOMAIN);
123
+ }
124
+ if (isPlainObject(opts.context) && Object.keys(opts.context).length > 0) {
125
+ // context 过滤 _auth 字段(withMetadataAuth 内部已处理)
126
+ envelope.context = withMetadataAuth(opts.context, masterKey, PROTECTED_CONTEXT_DOMAIN);
127
+ }
128
+ return envelope;
129
+ }
130
+ /**
131
+ * 规范化 protected_headers:value 转 string + 自动注入 payload_type。
132
+ * 与 Python `_normalize_headers` 对齐。
133
+ */
134
+ export function normalizeProtectedHeaders(headers, payload) {
135
+ const normalized = {};
136
+ if (headers instanceof ProtectedHeaders) {
137
+ Object.assign(normalized, headers.toObject());
138
+ }
139
+ else if (isPlainObject(headers)) {
140
+ Object.assign(normalized, ProtectedHeaders.from(headers).toObject());
141
+ }
142
+ // payload_type 自动注入(与 Python 对齐:即使未显式传 protected_headers 也会注入)
143
+ const payloadType = typeof payload?.type === 'string' ? payload.type : '';
144
+ if (payloadType && !('payload_type' in normalized)) {
145
+ normalized['payload_type'] = payloadType;
146
+ }
147
+ return normalized;
148
+ }
149
+ function isPlainObject(value) {
150
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
151
+ return false;
152
+ }
153
+ const proto = Object.getPrototypeOf(value);
154
+ return proto === Object.prototype || proto === null;
155
+ }
156
+ function computeWrapSalt(aadBytes, senderSessionPubDer) {
157
+ const suiteBytes = TEXT.encode(SUITE_NAME);
158
+ const h = createHash('sha256');
159
+ h.update(Buffer.from(aadBytes));
160
+ h.update(Buffer.from(senderSessionPubDer));
161
+ h.update(Buffer.from(suiteBytes));
162
+ return new Uint8Array(h.digest()).subarray(0, 16);
163
+ }
164
+ function wrapForRecipient(target, masterKey, senderSessionPriv, senderMasterPriv, wrapSalt) {
165
+ const fpHash = createHash('sha256').update(Buffer.from(target.ikPkDer)).digest('hex');
166
+ const fp = `sha256:${fpHash.substring(0, 16)}`;
167
+ const wrapNonce = new Uint8Array(randomBytes(12));
168
+ let wrapKey;
169
+ if (target.spkPkDer &&
170
+ (target.keySource === 'peer_device_prekey' || target.keySource === 'group_device_prekey')) {
171
+ wrapKey = compute3DHWrap(senderSessionPriv, senderMasterPriv, target.ikPkDer, target.spkPkDer, wrapSalt);
172
+ }
173
+ else {
174
+ wrapKey = compute1DHWrap(senderSessionPriv, target.ikPkDer, wrapSalt);
175
+ }
176
+ // AES-GCM wrap master_key(无 AAD)
177
+ const { ciphertext: wrappedCt, tag: wrappedTag } = aesGcmEncrypt(wrapKey, wrapNonce, masterKey, new Uint8Array(0));
178
+ const wrappedKey = Buffer.concat([Buffer.from(wrappedCt), Buffer.from(wrappedTag)]);
179
+ return [
180
+ target.aid,
181
+ target.deviceId,
182
+ target.role,
183
+ target.keySource,
184
+ fp,
185
+ target.spkId ?? '',
186
+ Buffer.from(wrapNonce).toString('base64'),
187
+ wrappedKey.toString('base64'),
188
+ ];
189
+ }
190
+ //# sourceMappingURL=encrypt-p2p.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encrypt-p2p.js","sourceRoot":"","sources":["../../../src/v2/e2ee/encrypt-p2p.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * AUN E2EE V2: 加解密引擎导出。
3
+ */
4
+ export { encryptP2PMessage } from './encrypt-p2p.js';
5
+ export { encryptGroupMessage } from './encrypt-group.js';
6
+ export { decryptMessage } from './decrypt.js';
7
+ export { withMetadataAuth, PROTECTED_HEADERS_DOMAIN, PROTECTED_CONTEXT_DOMAIN, METADATA_KEY_DOMAIN } from './metadata-auth.js';
8
+ export type { Sender, Target, TargetSet, EncryptOptions, StateCommitmentAAD } from './types.js';
9
+ export { SUITE_NAME } from './types.js';
@@ -0,0 +1,9 @@
1
+ /**
2
+ * AUN E2EE V2: 加解密引擎导出。
3
+ */
4
+ export { encryptP2PMessage } from './encrypt-p2p.js';
5
+ export { encryptGroupMessage } from './encrypt-group.js';
6
+ export { decryptMessage } from './decrypt.js';
7
+ export { withMetadataAuth, PROTECTED_HEADERS_DOMAIN, PROTECTED_CONTEXT_DOMAIN, METADATA_KEY_DOMAIN } from './metadata-auth.js';
8
+ export { SUITE_NAME } from './types.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/v2/e2ee/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE/H,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * AUN E2EE V2: protected_headers / context HMAC 签名
3
+ *
4
+ * 与 Python `aun_core.v2.e2ee.encrypt_p2p._with_metadata_auth` 对齐。
5
+ * 用 master_key 派生 HMAC key,对 metadata body 做签名,生成 `_auth` 字段。
6
+ */
7
+ export declare const METADATA_KEY_DOMAIN: Buffer<ArrayBuffer>;
8
+ export declare const PROTECTED_HEADERS_DOMAIN: Buffer<ArrayBuffer>;
9
+ export declare const PROTECTED_CONTEXT_DOMAIN: Buffer<ArrayBuffer>;
10
+ /**
11
+ * 为 metadata 对象添加 HMAC 签名(_auth 字段)。
12
+ *
13
+ * 如果 body(去除 _auth 后)为空,返回空对象。
14
+ */
15
+ export declare function withMetadataAuth(metadata: Record<string, unknown>, key: Uint8Array, domain: Buffer): Record<string, unknown>;