@agentunion/fastaun 0.2.19 → 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 (162) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/_packed_docs/CHANGELOG.md +46 -0
  3. package/_packed_docs/agent.md/SCHEMA.md +173 -0
  4. package/_packed_docs/agent.md/examples/codeagent-claudecode.md +61 -0
  5. package/_packed_docs/agent.md/examples/human-developer.md +60 -0
  6. package/_packed_docs/agent.md/examples/openclaw-lobster.md +52 -0
  7. package/_packed_docs/agent.md/examples/signed-openclaw-lobster.md +43 -0
  8. package/_packed_docs/protocol/00-/346/200/273/350/247/210/344/270/216/345/210/206/345/261/202.md +205 -0
  9. package/_packed_docs/protocol/00A-/350/256/276/350/256/241/345/216/237/345/210/231-/344/270/272Agent/350/200/214/347/224/237.md +197 -0
  10. package/_packed_docs/protocol/01-/350/272/253/344/273/275/344/270/216/345/207/255/350/257/201/345/215/217/350/256/256-auth.md +549 -0
  11. package/_packed_docs/protocol/02-/350/257/201/344/271/246/344/270/216/344/277/241/344/273/273/344/275/223/347/263/273.md +810 -0
  12. package/_packed_docs/protocol/03-Gateway-/350/277/236/346/216/245/346/250/241/345/274/217.md +262 -0
  13. package/_packed_docs/protocol/04-Peer-/345/255/220/345/215/217/350/256/256.md +180 -0
  14. package/_packed_docs/protocol/05-Relay-/345/255/220/345/215/217/350/256/256.md +164 -0
  15. package/_packed_docs/protocol/06-/346/234/215/345/212/241/345/215/217/350/256/256.md +1135 -0
  16. package/_packed_docs/protocol/07-/351/224/231/350/257/257/347/240/201/344/270/216/347/212/266/346/200/201/346/234/272.md +234 -0
  17. package/_packed_docs/protocol/08-AUN-E2EE-Group.md +900 -0
  18. package/_packed_docs/protocol/08-AUN-E2EE.md +413 -0
  19. package/_packed_docs/protocol/09-/345/256/211/345/205/250/350/200/203/350/231/221.md +316 -0
  20. package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +804 -0
  21. package/_packed_docs/protocol/11-Storage-/345/255/220/345/215/217/350/256/256.md +271 -0
  22. package/_packed_docs/protocol/12-Stream-/345/255/220/345/215/217/350/256/256.md +329 -0
  23. package/_packed_docs/protocol/13-Agent/350/241/214/344/270/272/350/247/204/350/214/203.md +141 -0
  24. package/_packed_docs/protocol/14-/344/272/244/344/272/222/346/234/272/345/210/266-/345/223/215/345/272/224/346/250/241/345/274/217/344/270/216/350/207/252/344/270/273/346/250/241/345/274/217.md +170 -0
  25. 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
  26. package/_packed_docs/protocol/README.md +71 -0
  27. package/_packed_docs/protocol/agent.md/SCHEMA.md +118 -0
  28. package/_packed_docs/protocol/agent.md/examples/codeagent-claudecode.md +61 -0
  29. package/_packed_docs/protocol/agent.md/examples/human-developer.md +60 -0
  30. package/_packed_docs/protocol/agent.md/examples/openclaw-lobster.md +52 -0
  31. package/_packed_docs/protocol/aun-docs-guide.md +49 -0
  32. package/_packed_docs/protocol/index.md +124 -0
  33. package/_packed_docs/protocol//350/215/211/346/241/210-agent.md/347/255/276/345/220/215/345/215/217/350/256/256.md +205 -0
  34. package/_packed_docs/protocol//350/215/211/346/241/210-/346/213/222/347/273/235/344/277/241/345/217/267/345/215/217/350/256/256.md +249 -0
  35. package/_packed_docs/protocol//351/231/204/345/275/225A-/346/234/257/350/257/255/350/241/250.md +337 -0
  36. package/_packed_docs/protocol//351/231/204/345/275/225B-/346/211/251/345/261/225/346/200/247/346/214/207/345/215/227.md +80 -0
  37. package/_packed_docs/protocol//351/231/204/345/275/225C-/347/247/201/351/222/245/347/256/241/347/220/206/344/270/216/350/272/253/344/273/275/346/201/242/345/244/215.md +704 -0
  38. package/_packed_docs/protocol//351/231/204/345/275/225D-Root_CA_/346/262/273/347/220/206/346/234/272/345/210/266.md +620 -0
  39. package/_packed_docs/protocol//351/231/204/345/275/225E-Root_CA_/345/207/206/345/205/245/346/265/201/347/250/213.md +605 -0
  40. package/_packed_docs/protocol//351/231/204/345/275/225F-Issuer_CA_/347/224/263/350/257/267/346/265/201/347/250/213.md +548 -0
  41. package/_packed_docs/protocol//351/231/204/345/275/225G-AID_/345/255/244/345/204/277/351/242/204/351/230/262/344/270/216/346/225/221/346/217/264/346/234/272/345/210/266.md +513 -0
  42. package/_packed_docs/protocol//351/231/204/345/275/225H-Identity/346/234/215/345/212/241/345/256/236/347/216/260/346/214/207/345/215/227.md +619 -0
  43. package/_packed_docs/protocol//351/231/204/345/275/225I-/350/267/250/345/237/237/346/266/210/346/201/257/350/267/257/347/224/261/345/256/236/347/216/260/346/214/207/345/215/227.md +492 -0
  44. package/_packed_docs/protocol//351/231/204/345/275/225J-/345/256/242/346/210/267/347/253/257/346/216/245/345/205/245/347/244/272/344/276/213.md +402 -0
  45. package/_packed_docs/protocol//351/231/204/345/275/225K-Agent_Web/345/217/221/347/216/260/345/215/217/350/256/256.md +130 -0
  46. package/_packed_docs/protocol//351/231/204/345/275/225L-E2EE/345/256/236/347/216/260/346/214/207/345/215/227.md +267 -0
  47. package/_packed_docs/protocol//351/231/204/345/275/225M-JWT/350/256/244/350/257/201/345/256/236/347/216/260/346/214/207/345/215/227.md +367 -0
  48. package/_packed_docs/python-sdk-v2-only-changelog.md +189 -0
  49. package/_packed_docs/sdk/01-/345/277/253/351/200/237/345/274/200/345/247/213.md +223 -0
  50. package/_packed_docs/sdk/02-WebSocket/345/215/217/350/256/256.md +354 -0
  51. package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +172 -0
  52. package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +396 -0
  53. package/_packed_docs/sdk/05-E2EE/345/212/240/345/257/206/351/200/232/344/277/241.md +611 -0
  54. package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +1203 -0
  55. package/_packed_docs/sdk/07-/351/224/231/350/257/257/345/244/204/347/220/206.md +150 -0
  56. package/_packed_docs/sdk/08-/346/234/200/344/275/263/345/256/236/350/267/265.md +89 -0
  57. package/_packed_docs/sdk/09-custody-api-manual.md +445 -0
  58. package/_packed_docs/sdk/09-group-rpc-manual.md +1895 -0
  59. package/_packed_docs/sdk/09-message-rpc-manual.md +597 -0
  60. package/_packed_docs/sdk/09-meta-rpc-manual.md +142 -0
  61. package/_packed_docs/sdk/09-payload-reference.md +702 -0
  62. package/_packed_docs/sdk/09-storage-rpc-manual.md +408 -0
  63. package/_packed_docs/sdk/09-stream-rpc-manual.md +275 -0
  64. package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +72 -0
  65. package/_packed_docs/sdk/INDEX.md +131 -0
  66. package/_packed_docs/sdk/README.md +307 -0
  67. package/dist/auth.d.ts +2 -1
  68. package/dist/auth.js +37 -18
  69. package/dist/auth.js.map +1 -1
  70. package/dist/client.d.ts +147 -171
  71. package/dist/client.js +2583 -3916
  72. package/dist/client.js.map +1 -1
  73. package/dist/config.d.ts +0 -4
  74. package/dist/config.js +0 -4
  75. package/dist/config.js.map +1 -1
  76. package/dist/e2ee.d.ts +5 -139
  77. package/dist/e2ee.js +4 -1151
  78. package/dist/e2ee.js.map +1 -1
  79. package/dist/errors.d.ts +0 -8
  80. package/dist/errors.js +0 -14
  81. package/dist/errors.js.map +1 -1
  82. package/dist/index.d.ts +9 -5
  83. package/dist/index.js +6 -3
  84. package/dist/index.js.map +1 -1
  85. package/dist/keystore/aid-db.d.ts +12 -61
  86. package/dist/keystore/aid-db.js +41 -539
  87. package/dist/keystore/aid-db.js.map +1 -1
  88. package/dist/keystore/file.d.ts +5 -41
  89. package/dist/keystore/file.js +8 -64
  90. package/dist/keystore/file.js.map +1 -1
  91. package/dist/keystore/index.d.ts +1 -49
  92. package/dist/namespaces/auth.d.ts +1 -0
  93. package/dist/namespaces/auth.js +22 -6
  94. package/dist/namespaces/auth.js.map +1 -1
  95. package/dist/protected-headers.d.ts +13 -0
  96. package/dist/protected-headers.js +47 -0
  97. package/dist/protected-headers.js.map +1 -0
  98. package/dist/seq-tracker.d.ts +7 -2
  99. package/dist/seq-tracker.js +31 -10
  100. package/dist/seq-tracker.js.map +1 -1
  101. package/dist/transport.d.ts +10 -0
  102. package/dist/transport.js +24 -0
  103. package/dist/transport.js.map +1 -1
  104. package/dist/types.d.ts +0 -56
  105. package/dist/v2/crypto/aead.d.ts +20 -0
  106. package/dist/v2/crypto/aead.js +59 -0
  107. package/dist/v2/crypto/aead.js.map +1 -0
  108. package/dist/v2/crypto/canonical.d.ts +20 -0
  109. package/dist/v2/crypto/canonical.js +119 -0
  110. package/dist/v2/crypto/canonical.js.map +1 -0
  111. package/dist/v2/crypto/dh-path.d.ts +39 -0
  112. package/dist/v2/crypto/dh-path.js +55 -0
  113. package/dist/v2/crypto/dh-path.js.map +1 -0
  114. package/dist/v2/crypto/ecdh.d.ts +29 -0
  115. package/dist/v2/crypto/ecdh.js +122 -0
  116. package/dist/v2/crypto/ecdh.js.map +1 -0
  117. package/dist/v2/crypto/ecdsa.d.ts +29 -0
  118. package/dist/v2/crypto/ecdsa.js +120 -0
  119. package/dist/v2/crypto/ecdsa.js.map +1 -0
  120. package/dist/v2/crypto/hkdf.d.ts +19 -0
  121. package/dist/v2/crypto/hkdf.js +47 -0
  122. package/dist/v2/crypto/hkdf.js.map +1 -0
  123. package/dist/v2/crypto/index.d.ts +8 -0
  124. package/dist/v2/crypto/index.js +8 -0
  125. package/dist/v2/crypto/index.js.map +1 -0
  126. package/dist/v2/crypto/recipients.d.ts +32 -0
  127. package/dist/v2/crypto/recipients.js +183 -0
  128. package/dist/v2/crypto/recipients.js.map +1 -0
  129. package/dist/v2/e2ee/decrypt.d.ts +29 -0
  130. package/dist/v2/e2ee/decrypt.js +159 -0
  131. package/dist/v2/e2ee/decrypt.js.map +1 -0
  132. package/dist/v2/e2ee/encrypt-group.d.ts +17 -0
  133. package/dist/v2/e2ee/encrypt-group.js +143 -0
  134. package/dist/v2/e2ee/encrypt-group.js.map +1 -0
  135. package/dist/v2/e2ee/encrypt-p2p.d.ts +31 -0
  136. package/dist/v2/e2ee/encrypt-p2p.js +190 -0
  137. package/dist/v2/e2ee/encrypt-p2p.js.map +1 -0
  138. package/dist/v2/e2ee/index.d.ts +9 -0
  139. package/dist/v2/e2ee/index.js +9 -0
  140. package/dist/v2/e2ee/index.js.map +1 -0
  141. package/dist/v2/e2ee/metadata-auth.d.ts +15 -0
  142. package/dist/v2/e2ee/metadata-auth.js +50 -0
  143. package/dist/v2/e2ee/metadata-auth.js.map +1 -0
  144. package/dist/v2/e2ee/types.d.ts +57 -0
  145. package/dist/v2/e2ee/types.js +7 -0
  146. package/dist/v2/e2ee/types.js.map +1 -0
  147. package/dist/v2/session/index.d.ts +4 -0
  148. package/dist/v2/session/index.js +3 -0
  149. package/dist/v2/session/index.js.map +1 -0
  150. package/dist/v2/session/keystore.d.ts +41 -0
  151. package/dist/v2/session/keystore.js +103 -0
  152. package/dist/v2/session/keystore.js.map +1 -0
  153. package/dist/v2/session/session.d.ts +97 -0
  154. package/dist/v2/session/session.js +242 -0
  155. package/dist/v2/session/session.js.map +1 -0
  156. package/dist/v2/state/commitment.d.ts +58 -0
  157. package/dist/v2/state/commitment.js +85 -0
  158. package/dist/v2/state/commitment.js.map +1 -0
  159. package/dist/v2/state/index.d.ts +2 -0
  160. package/dist/v2/state/index.js +2 -0
  161. package/dist/v2/state/index.js.map +1 -0
  162. package/package.json +46 -42
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical.js","sourceRoot":"","sources":["../../../src/v2/crypto/canonical.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * AUN E2EE V2: 1DH / 3DH wrap_key 派生
3
+ *
4
+ * 规范引用:§4.x
5
+ *
6
+ * 3DH(活跃会话):
7
+ * DH1 = ECDH(senderSessionPriv, recvIKPub)
8
+ * DH2 = ECDH(senderMasterPriv, recvSPKPub)
9
+ * DH3 = ECDH(senderSessionPriv, recvSPKPub)
10
+ * ikm = DH1 || DH2 || DH3
11
+ * wrap_key = HKDF-SHA256(ikm, salt, info="AUN-V2-3DH", 32)
12
+ *
13
+ * 1DH(无 SPK 的回退路径):
14
+ * DH = ECDH(senderSessionPriv, recvIKPub)
15
+ * wrap_key = HKDF-SHA256(DH, salt, info="AUN-V2-1DH", 32)
16
+ */
17
+ export declare const INFO_3DH: Uint8Array;
18
+ export declare const INFO_1DH: Uint8Array;
19
+ export declare const WRAP_KEY_LENGTH = 32;
20
+ /**
21
+ * 计算 3DH wrap_key。
22
+ *
23
+ * @param senderSessionPriv 发送方会话私钥(32B 标量)
24
+ * @param senderMasterPriv 发送方 AID 长期主私钥(32B 标量)
25
+ * @param recvIKPub 接收方身份公钥 IK(DER SPKI)
26
+ * @param recvSPKPub 接收方 Signed PreKey 公钥 SPK(DER SPKI)
27
+ * @param salt HKDF salt
28
+ * @returns 32 字节 wrap_key
29
+ */
30
+ export declare function compute3DHWrap(senderSessionPriv: Uint8Array, senderMasterPriv: Uint8Array, recvIKPub: Uint8Array, recvSPKPub: Uint8Array, salt: Uint8Array): Uint8Array;
31
+ /**
32
+ * 计算 1DH wrap_key(fallback)。
33
+ *
34
+ * @param senderSessionPriv 发送方会话私钥(32B 标量)
35
+ * @param recvIKPub 接收方身份公钥 IK(DER SPKI)
36
+ * @param salt HKDF salt
37
+ * @returns 32 字节 wrap_key
38
+ */
39
+ export declare function compute1DHWrap(senderSessionPriv: Uint8Array, recvIKPub: Uint8Array, salt: Uint8Array): Uint8Array;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * AUN E2EE V2: 1DH / 3DH wrap_key 派生
3
+ *
4
+ * 规范引用:§4.x
5
+ *
6
+ * 3DH(活跃会话):
7
+ * DH1 = ECDH(senderSessionPriv, recvIKPub)
8
+ * DH2 = ECDH(senderMasterPriv, recvSPKPub)
9
+ * DH3 = ECDH(senderSessionPriv, recvSPKPub)
10
+ * ikm = DH1 || DH2 || DH3
11
+ * wrap_key = HKDF-SHA256(ikm, salt, info="AUN-V2-3DH", 32)
12
+ *
13
+ * 1DH(无 SPK 的回退路径):
14
+ * DH = ECDH(senderSessionPriv, recvIKPub)
15
+ * wrap_key = HKDF-SHA256(DH, salt, info="AUN-V2-1DH", 32)
16
+ */
17
+ import { ecdhComputeShared } from './ecdh.js';
18
+ import { hkdfSha256 } from './hkdf.js';
19
+ const TEXT = new TextEncoder();
20
+ export const INFO_3DH = TEXT.encode('AUN-V2-3DH');
21
+ export const INFO_1DH = TEXT.encode('AUN-V2-1DH');
22
+ export const WRAP_KEY_LENGTH = 32;
23
+ /**
24
+ * 计算 3DH wrap_key。
25
+ *
26
+ * @param senderSessionPriv 发送方会话私钥(32B 标量)
27
+ * @param senderMasterPriv 发送方 AID 长期主私钥(32B 标量)
28
+ * @param recvIKPub 接收方身份公钥 IK(DER SPKI)
29
+ * @param recvSPKPub 接收方 Signed PreKey 公钥 SPK(DER SPKI)
30
+ * @param salt HKDF salt
31
+ * @returns 32 字节 wrap_key
32
+ */
33
+ export function compute3DHWrap(senderSessionPriv, senderMasterPriv, recvIKPub, recvSPKPub, salt) {
34
+ const dh1 = ecdhComputeShared(senderSessionPriv, recvIKPub);
35
+ const dh2 = ecdhComputeShared(senderMasterPriv, recvSPKPub);
36
+ const dh3 = ecdhComputeShared(senderSessionPriv, recvSPKPub);
37
+ const ikm = new Uint8Array(96);
38
+ ikm.set(dh1, 0);
39
+ ikm.set(dh2, 32);
40
+ ikm.set(dh3, 64);
41
+ return hkdfSha256(ikm, salt, INFO_3DH, WRAP_KEY_LENGTH);
42
+ }
43
+ /**
44
+ * 计算 1DH wrap_key(fallback)。
45
+ *
46
+ * @param senderSessionPriv 发送方会话私钥(32B 标量)
47
+ * @param recvIKPub 接收方身份公钥 IK(DER SPKI)
48
+ * @param salt HKDF salt
49
+ * @returns 32 字节 wrap_key
50
+ */
51
+ export function compute1DHWrap(senderSessionPriv, recvIKPub, salt) {
52
+ const dh = ecdhComputeShared(senderSessionPriv, recvIKPub);
53
+ return hkdfSha256(dh, salt, INFO_1DH, WRAP_KEY_LENGTH);
54
+ }
55
+ //# sourceMappingURL=dh-path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dh-path.js","sourceRoot":"","sources":["../../../src/v2/crypto/dh-path.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,MAAM,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC;AAC/B,MAAM,CAAC,MAAM,QAAQ,GAAe,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;AAC9D,MAAM,CAAC,MAAM,QAAQ,GAAe,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;AAC9D,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAC;AAElC;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAC5B,iBAA6B,EAC7B,gBAA4B,EAC5B,SAAqB,EACrB,UAAsB,EACtB,IAAgB;IAEhB,MAAM,GAAG,GAAG,iBAAiB,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC;IAC5D,MAAM,GAAG,GAAG,iBAAiB,CAAC,gBAAgB,EAAE,UAAU,CAAC,CAAC;IAC5D,MAAM,GAAG,GAAG,iBAAiB,CAAC,iBAAiB,EAAE,UAAU,CAAC,CAAC;IAC7D,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IAC/B,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IAChB,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACjB,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACjB,OAAO,UAAU,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;AAC1D,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAC5B,iBAA6B,EAC7B,SAAqB,EACrB,IAAgB;IAEhB,MAAM,EAAE,GAAG,iBAAiB,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC;IAC3D,OAAO,UAAU,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;AACzD,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * ECDH P-256 — AUN E2EE V2 协议要求所有 SDK 的 ECDH 输出字节级一致。
3
+ *
4
+ * 共享秘密为 P-256 曲线点乘后的 X 坐标(32 字节,big-endian)。
5
+ *
6
+ * 实现选型:
7
+ * - 使用 Node `crypto` 模块(非 WebCrypto,TS SDK 目标为 Node 环境)
8
+ * - `createECDH('prime256v1')` 计算 X 坐标
9
+ * - 公钥使用 DER SubjectPublicKeyInfo 编码(与 Python/Go SDK 对齐)
10
+ * - 通过 JWK 中转完成 DER ↔ 未压缩点(0x04 || X || Y)的转换
11
+ */
12
+ /**
13
+ * 计算 ECDH 共享秘密(P-256 X 坐标,32 字节)。
14
+ *
15
+ * @param privateKeyScalar 32 字节 P-256 私钥标量(big-endian)
16
+ * @param peerPublicKeyDer DER SubjectPublicKeyInfo 编码的对端公钥
17
+ * @returns 32 字节共享秘密(X 坐标 big-endian)
18
+ */
19
+ export declare function ecdhComputeShared(privateKeyScalar: Uint8Array, peerPublicKeyDer: Uint8Array): Uint8Array;
20
+ /**
21
+ * 生成 P-256 密钥对。
22
+ *
23
+ * @returns [privateKeyScalar 32B, publicKeyDer SPKI]
24
+ */
25
+ export declare function generateP256Keypair(): [Uint8Array, Uint8Array];
26
+ /**
27
+ * 从私钥标量导出公钥 DER(SPKI 编码)。
28
+ */
29
+ export declare function privateToPublicDer(privateKeyScalar: Uint8Array): Uint8Array;
@@ -0,0 +1,122 @@
1
+ /**
2
+ * ECDH P-256 — AUN E2EE V2 协议要求所有 SDK 的 ECDH 输出字节级一致。
3
+ *
4
+ * 共享秘密为 P-256 曲线点乘后的 X 坐标(32 字节,big-endian)。
5
+ *
6
+ * 实现选型:
7
+ * - 使用 Node `crypto` 模块(非 WebCrypto,TS SDK 目标为 Node 环境)
8
+ * - `createECDH('prime256v1')` 计算 X 坐标
9
+ * - 公钥使用 DER SubjectPublicKeyInfo 编码(与 Python/Go SDK 对齐)
10
+ * - 通过 JWK 中转完成 DER ↔ 未压缩点(0x04 || X || Y)的转换
11
+ */
12
+ import { createECDH, createPublicKey } from 'node:crypto';
13
+ /**
14
+ * 把 base64url 字符串解码为 32 字节大端序无前导零填充的字节数组。
15
+ * 解决 JWK x/y 可能因高位为 0 而被截短的问题。
16
+ */
17
+ function b64uToFixed32(b64url) {
18
+ const buf = Buffer.from(b64url, 'base64url');
19
+ if (buf.length === 32)
20
+ return buf;
21
+ if (buf.length < 32) {
22
+ const padded = Buffer.alloc(32);
23
+ buf.copy(padded, 32 - buf.length);
24
+ return padded;
25
+ }
26
+ // 长度 > 32:去掉前导 0x00 填充
27
+ const start = buf.length - 32;
28
+ for (let i = 0; i < start; i++) {
29
+ if (buf[i] !== 0) {
30
+ throw new Error(`invalid EC coordinate: length=${buf.length}, leading non-zero byte`);
31
+ }
32
+ }
33
+ return buf.subarray(start, buf.length);
34
+ }
35
+ /**
36
+ * 把未压缩点(0x04 || X(32) || Y(32))的 X/Y 坐标转换为 SPKI DER 公钥。
37
+ */
38
+ function uncompressedPointToDer(uncompressed) {
39
+ if (uncompressed.length !== 65 || uncompressed[0] !== 0x04) {
40
+ throw new Error('invalid uncompressed P-256 point');
41
+ }
42
+ const x = uncompressed.subarray(1, 33);
43
+ const y = uncompressed.subarray(33, 65);
44
+ const pubKey = createPublicKey({
45
+ key: {
46
+ kty: 'EC',
47
+ crv: 'P-256',
48
+ x: x.toString('base64url'),
49
+ y: y.toString('base64url'),
50
+ },
51
+ format: 'jwk',
52
+ });
53
+ return pubKey.export({ format: 'der', type: 'spki' });
54
+ }
55
+ /**
56
+ * 计算 ECDH 共享秘密(P-256 X 坐标,32 字节)。
57
+ *
58
+ * @param privateKeyScalar 32 字节 P-256 私钥标量(big-endian)
59
+ * @param peerPublicKeyDer DER SubjectPublicKeyInfo 编码的对端公钥
60
+ * @returns 32 字节共享秘密(X 坐标 big-endian)
61
+ */
62
+ export function ecdhComputeShared(privateKeyScalar, peerPublicKeyDer) {
63
+ if (privateKeyScalar.length !== 32) {
64
+ throw new Error(`expected 32-byte P-256 private scalar, got ${privateKeyScalar.length}`);
65
+ }
66
+ const ecdh = createECDH('prime256v1');
67
+ ecdh.setPrivateKey(Buffer.from(privateKeyScalar));
68
+ // 解析 DER SPKI 公钥 → 提取未压缩点(0x04 || X || Y)
69
+ const peerPubKey = createPublicKey({
70
+ key: Buffer.from(peerPublicKeyDer),
71
+ format: 'der',
72
+ type: 'spki',
73
+ });
74
+ const jwk = peerPubKey.export({ format: 'jwk' });
75
+ if (jwk.kty !== 'EC' || jwk.crv !== 'P-256' || !jwk.x || !jwk.y) {
76
+ throw new Error('peer public key is not a P-256 EC key');
77
+ }
78
+ const x = b64uToFixed32(jwk.x);
79
+ const y = b64uToFixed32(jwk.y);
80
+ const uncompressed = Buffer.concat([Buffer.from([0x04]), x, y]);
81
+ // ECDH.computeSecret 默认返回 X 坐标(32 字节大端序)
82
+ const shared = ecdh.computeSecret(uncompressed);
83
+ return new Uint8Array(shared);
84
+ }
85
+ /**
86
+ * 生成 P-256 密钥对。
87
+ *
88
+ * @returns [privateKeyScalar 32B, publicKeyDer SPKI]
89
+ */
90
+ export function generateP256Keypair() {
91
+ const ecdh = createECDH('prime256v1');
92
+ const pubUncompressed = ecdh.generateKeys();
93
+ const priv = ecdh.getPrivateKey();
94
+ // setPrivateKey/generateKeys 返回的 priv 可能少于 32 字节(高位为 0),左零填充
95
+ let privPadded;
96
+ if (priv.length === 32) {
97
+ privPadded = priv;
98
+ }
99
+ else if (priv.length < 32) {
100
+ privPadded = Buffer.alloc(32);
101
+ priv.copy(privPadded, 32 - priv.length);
102
+ }
103
+ else {
104
+ throw new Error(`unexpected P-256 private key length: ${priv.length}`);
105
+ }
106
+ const pubDer = uncompressedPointToDer(pubUncompressed);
107
+ return [new Uint8Array(privPadded), new Uint8Array(pubDer)];
108
+ }
109
+ /**
110
+ * 从私钥标量导出公钥 DER(SPKI 编码)。
111
+ */
112
+ export function privateToPublicDer(privateKeyScalar) {
113
+ if (privateKeyScalar.length !== 32) {
114
+ throw new Error(`expected 32-byte P-256 private scalar, got ${privateKeyScalar.length}`);
115
+ }
116
+ const ecdh = createECDH('prime256v1');
117
+ ecdh.setPrivateKey(Buffer.from(privateKeyScalar));
118
+ const pubUncompressed = ecdh.getPublicKey();
119
+ const pubDer = uncompressedPointToDer(pubUncompressed);
120
+ return new Uint8Array(pubDer);
121
+ }
122
+ //# sourceMappingURL=ecdh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ecdh.js","sourceRoot":"","sources":["../../../src/v2/crypto/ecdh.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE1D;;;GAGG;AACH,SAAS,aAAa,CAAC,MAAc;IACnC,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC7C,IAAI,GAAG,CAAC,MAAM,KAAK,EAAE;QAAE,OAAO,GAAG,CAAC;IAClC,IAAI,GAAG,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAChC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;QAClC,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,uBAAuB;IACvB,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC;IAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,iCAAiC,GAAG,CAAC,MAAM,yBAAyB,CAAC,CAAC;QACxF,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,SAAS,sBAAsB,CAAC,YAAoB;IAClD,IAAI,YAAY,CAAC,MAAM,KAAK,EAAE,IAAI,YAAY,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACtD,CAAC;IACD,MAAM,CAAC,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACvC,MAAM,CAAC,GAAG,YAAY,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,eAAe,CAAC;QAC7B,GAAG,EAAE;YACH,GAAG,EAAE,IAAI;YACT,GAAG,EAAE,OAAO;YACZ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC;YAC1B,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC;SAC3B;QACD,MAAM,EAAE,KAAK;KACd,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;AACxD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,gBAA4B,EAC5B,gBAA4B;IAE5B,IAAI,gBAAgB,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,8CAA8C,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3F,CAAC;IAED,MAAM,IAAI,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;IACtC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAElD,0CAA0C;IAC1C,MAAM,UAAU,GAAG,eAAe,CAAC;QACjC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC;QAClC,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,MAAM;KACb,CAAC,CAAC;IACH,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACjD,IAAI,GAAG,CAAC,GAAG,KAAK,IAAI,IAAI,GAAG,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QAChE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IACD,MAAM,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC/B,MAAM,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC/B,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAEhE,yCAAyC;IACzC,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;IAChD,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB;IACjC,MAAM,IAAI,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;IACtC,MAAM,eAAe,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;IAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;IAElC,6DAA6D;IAC7D,IAAI,UAAkB,CAAC;IACvB,IAAI,IAAI,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QACvB,UAAU,GAAG,IAAI,CAAC;IACpB,CAAC;SAAM,IAAI,IAAI,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QAC5B,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,KAAK,CAAC,wCAAwC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,MAAM,GAAG,sBAAsB,CAAC,eAAe,CAAC,CAAC;IACvD,OAAO,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,gBAA4B;IAC7D,IAAI,gBAAgB,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,8CAA8C,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3F,CAAC;IACD,MAAM,IAAI,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;IACtC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAClD,MAAM,eAAe,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;IAC5C,MAAM,MAAM,GAAG,sBAAsB,CAAC,eAAe,CAAC,CAAC;IACvD,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * AUN E2EE V2: ECDSA-SHA256 RAW(RFC 6979 deterministic)
3
+ *
4
+ * 规范引用:§3.1
5
+ * - 曲线 P-256
6
+ * - RFC 6979 deterministic nonce(必须)
7
+ * - 输出 RAW 编码 r(32B)||s(32B)
8
+ *
9
+ * 实现选型:
10
+ * - 使用 @noble/curves/nist 提供 deterministic ECDSA
11
+ * - 公钥使用 DER SubjectPublicKeyInfo(与 Python/Go 对齐)
12
+ * 通过 Node createPublicKey 提取未压缩点(0x04||X||Y)后传给 noble
13
+ */
14
+ /**
15
+ * ECDSA-SHA256 签名(RFC 6979 deterministic),输出 RAW 编码 r||s(64 字节)。
16
+ *
17
+ * @param privateKeyScalar P-256 私钥标量(32 字节 big-endian)
18
+ * @param message 待签名消息原文
19
+ * @returns 64 字节签名
20
+ */
21
+ export declare function ecdsaSignRaw(privateKeyScalar: Uint8Array, message: Uint8Array): Uint8Array;
22
+ /**
23
+ * ECDSA-SHA256 验签(RAW 64 字节签名)。
24
+ */
25
+ export declare function ecdsaVerifyRaw(publicKeyDer: Uint8Array, signatureRaw: Uint8Array, message: Uint8Array): boolean;
26
+ /**
27
+ * 仅用于本地校验:根据 P-256 私钥派生公钥的 DER SPKI 编码。
28
+ */
29
+ export declare function privateScalarToPublicDer(privateKeyScalar: Uint8Array): Uint8Array;
@@ -0,0 +1,120 @@
1
+ /**
2
+ * AUN E2EE V2: ECDSA-SHA256 RAW(RFC 6979 deterministic)
3
+ *
4
+ * 规范引用:§3.1
5
+ * - 曲线 P-256
6
+ * - RFC 6979 deterministic nonce(必须)
7
+ * - 输出 RAW 编码 r(32B)||s(32B)
8
+ *
9
+ * 实现选型:
10
+ * - 使用 @noble/curves/nist 提供 deterministic ECDSA
11
+ * - 公钥使用 DER SubjectPublicKeyInfo(与 Python/Go 对齐)
12
+ * 通过 Node createPublicKey 提取未压缩点(0x04||X||Y)后传给 noble
13
+ */
14
+ import { p256 } from '@noble/curves/nist.js';
15
+ import { createPublicKey } from 'node:crypto';
16
+ /**
17
+ * 把 base64url 字符串解码为 32 字节大端序无前导零填充的字节数组。
18
+ */
19
+ function b64uToFixed32(b64url) {
20
+ const buf = Buffer.from(b64url, 'base64url');
21
+ if (buf.length === 32)
22
+ return buf;
23
+ if (buf.length < 32) {
24
+ const padded = Buffer.alloc(32);
25
+ buf.copy(padded, 32 - buf.length);
26
+ return padded;
27
+ }
28
+ const start = buf.length - 32;
29
+ for (let i = 0; i < start; i++) {
30
+ if (buf[i] !== 0) {
31
+ throw new Error(`invalid EC coordinate: length=${buf.length}, leading non-zero byte`);
32
+ }
33
+ }
34
+ return buf.subarray(start, buf.length);
35
+ }
36
+ /**
37
+ * 从 DER SPKI 编码公钥提取未压缩点(0x04||X||Y),共 65 字节。
38
+ */
39
+ function derSpkiToUncompressed(publicKeyDer) {
40
+ const pub = createPublicKey({
41
+ key: Buffer.from(publicKeyDer),
42
+ format: 'der',
43
+ type: 'spki',
44
+ });
45
+ const jwk = pub.export({ format: 'jwk' });
46
+ if (jwk.kty !== 'EC' || jwk.crv !== 'P-256' || !jwk.x || !jwk.y) {
47
+ throw new Error('public key is not a P-256 EC key');
48
+ }
49
+ const x = b64uToFixed32(jwk.x);
50
+ const y = b64uToFixed32(jwk.y);
51
+ return Buffer.concat([Buffer.from([0x04]), x, y]);
52
+ }
53
+ /**
54
+ * ECDSA-SHA256 签名(RFC 6979 deterministic),输出 RAW 编码 r||s(64 字节)。
55
+ *
56
+ * @param privateKeyScalar P-256 私钥标量(32 字节 big-endian)
57
+ * @param message 待签名消息原文
58
+ * @returns 64 字节签名
59
+ */
60
+ export function ecdsaSignRaw(privateKeyScalar, message) {
61
+ if (privateKeyScalar.length !== 32) {
62
+ throw new Error(`expected 32-byte P-256 private scalar, got ${privateKeyScalar.length}`);
63
+ }
64
+ // 显式 prehash=true(默认值),noble 会用 SHA-256 摘要。
65
+ // lowS=false 与 Python/Go SDK 行为对齐(不强制低 S)。
66
+ // format='compact' 是默认值,输出 64B = r||s。
67
+ const sig = p256.sign(message, privateKeyScalar, {
68
+ prehash: true,
69
+ lowS: false,
70
+ format: 'compact',
71
+ });
72
+ if (sig.length !== 64) {
73
+ throw new Error(`unexpected signature length: ${sig.length}`);
74
+ }
75
+ return sig;
76
+ }
77
+ /**
78
+ * ECDSA-SHA256 验签(RAW 64 字节签名)。
79
+ */
80
+ export function ecdsaVerifyRaw(publicKeyDer, signatureRaw, message) {
81
+ if (signatureRaw.length !== 64)
82
+ return false;
83
+ try {
84
+ const uncompressed = derSpkiToUncompressed(publicKeyDer);
85
+ return p256.verify(signatureRaw, message, uncompressed, {
86
+ prehash: true,
87
+ lowS: false,
88
+ format: 'compact',
89
+ });
90
+ }
91
+ catch {
92
+ return false;
93
+ }
94
+ }
95
+ /**
96
+ * 仅用于本地校验:根据 P-256 私钥派生公钥的 DER SPKI 编码。
97
+ */
98
+ export function privateScalarToPublicDer(privateKeyScalar) {
99
+ if (privateKeyScalar.length !== 32) {
100
+ throw new Error(`expected 32-byte P-256 private scalar, got ${privateKeyScalar.length}`);
101
+ }
102
+ // noble 返回未压缩 65 字节
103
+ const uncompressed = p256.getPublicKey(privateKeyScalar, false);
104
+ if (uncompressed.length !== 65 || uncompressed[0] !== 0x04) {
105
+ throw new Error('failed to derive uncompressed P-256 public key');
106
+ }
107
+ const x = uncompressed.subarray(1, 33);
108
+ const y = uncompressed.subarray(33, 65);
109
+ const pubKey = createPublicKey({
110
+ key: {
111
+ kty: 'EC',
112
+ crv: 'P-256',
113
+ x: Buffer.from(x).toString('base64url'),
114
+ y: Buffer.from(y).toString('base64url'),
115
+ },
116
+ format: 'jwk',
117
+ });
118
+ return new Uint8Array(pubKey.export({ format: 'der', type: 'spki' }));
119
+ }
120
+ //# sourceMappingURL=ecdsa.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ecdsa.js","sourceRoot":"","sources":["../../../src/v2/crypto/ecdsa.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * AUN E2EE V2: HKDF-SHA256(RFC 5869)
3
+ *
4
+ * 规范引用:用于 1DH/3DH wrap_key 派生(info 分别为 "AUN-V2-1DH" 和 "AUN-V2-3DH")。
5
+ *
6
+ * 实现选型:
7
+ * - Node `crypto` 模块 HMAC-SHA256
8
+ * - 空 salt 视为 32 字节零(HashLen)
9
+ */
10
+ /**
11
+ * HKDF-SHA256(RFC 5869)。
12
+ *
13
+ * @param ikm Input keying material
14
+ * @param salt Salt(可为空,空时按规范用 HashLen 字节零填充)
15
+ * @param info Optional context and application specific information
16
+ * @param length 期望输出字节长度(不能超过 255 * HashLen)
17
+ * @returns OKM(output keying material)
18
+ */
19
+ export declare function hkdfSha256(ikm: Uint8Array, salt: Uint8Array, info: Uint8Array, length: number): Uint8Array;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * AUN E2EE V2: HKDF-SHA256(RFC 5869)
3
+ *
4
+ * 规范引用:用于 1DH/3DH wrap_key 派生(info 分别为 "AUN-V2-1DH" 和 "AUN-V2-3DH")。
5
+ *
6
+ * 实现选型:
7
+ * - Node `crypto` 模块 HMAC-SHA256
8
+ * - 空 salt 视为 32 字节零(HashLen)
9
+ */
10
+ import { createHmac } from 'node:crypto';
11
+ const HASH_LEN = 32; // SHA-256 输出长度
12
+ /**
13
+ * HKDF-SHA256(RFC 5869)。
14
+ *
15
+ * @param ikm Input keying material
16
+ * @param salt Salt(可为空,空时按规范用 HashLen 字节零填充)
17
+ * @param info Optional context and application specific information
18
+ * @param length 期望输出字节长度(不能超过 255 * HashLen)
19
+ * @returns OKM(output keying material)
20
+ */
21
+ export function hkdfSha256(ikm, salt, info, length) {
22
+ if (length < 0 || length > 255 * HASH_LEN) {
23
+ throw new Error(`HKDF length out of range: ${length}`);
24
+ }
25
+ // RFC 5869 §2.2: salt 为空时使用 HashLen 字节零
26
+ const realSalt = salt.length === 0 ? new Uint8Array(HASH_LEN) : salt;
27
+ // Extract: PRK = HMAC-SHA256(salt, IKM)
28
+ const prk = createHmac('sha256', realSalt).update(ikm).digest();
29
+ // Expand: T(i) = HMAC-SHA256(PRK, T(i-1) || info || i)
30
+ const out = new Uint8Array(length);
31
+ let t = new Uint8Array(0);
32
+ let pos = 0;
33
+ let counter = 1;
34
+ while (pos < length) {
35
+ const hmac = createHmac('sha256', prk);
36
+ hmac.update(t);
37
+ hmac.update(info);
38
+ hmac.update(Uint8Array.of(counter));
39
+ t = hmac.digest();
40
+ const remaining = length - pos;
41
+ out.set(t.subarray(0, Math.min(remaining, t.length)), pos);
42
+ pos += t.length;
43
+ counter++;
44
+ }
45
+ return out;
46
+ }
47
+ //# sourceMappingURL=hkdf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hkdf.js","sourceRoot":"","sources":["../../../src/v2/crypto/hkdf.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,QAAQ,GAAG,EAAE,CAAC,CAAC,eAAe;AAEpC;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CACxB,GAAe,EACf,IAAgB,EAChB,IAAgB,EAChB,MAAc;IAEd,IAAI,MAAM,GAAG,CAAC,IAAI,MAAM,GAAG,GAAG,GAAG,QAAQ,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,6BAA6B,MAAM,EAAE,CAAC,CAAC;IACzD,CAAC;IACD,wCAAwC;IACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAErE,wCAAwC;IACxC,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC;IAEhE,uDAAuD;IACvD,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IACnC,IAAI,CAAC,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;IAC1B,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,OAAO,GAAG,GAAG,MAAM,EAAE,CAAC;QACpB,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACvC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACf,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAClB,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;QACpC,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAClB,MAAM,SAAS,GAAG,MAAM,GAAG,GAAG,CAAC;QAC/B,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC3D,GAAG,IAAI,CAAC,CAAC,MAAM,CAAC;QAChB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,8 @@
1
+ export { canonicalJson, canonicalStringify } from './canonical.js';
2
+ export { ecdhComputeShared, generateP256Keypair, privateToPublicDer } from './ecdh.js';
3
+ export { hkdfSha256 } from './hkdf.js';
4
+ export { aesGcmEncrypt, aesGcmDecrypt } from './aead.js';
5
+ export { ecdsaSignRaw, ecdsaVerifyRaw, privateScalarToPublicDer } from './ecdsa.js';
6
+ export { compute1DHWrap, compute3DHWrap, INFO_1DH, INFO_3DH, WRAP_KEY_LENGTH, } from './dh-path.js';
7
+ export { sortRecipients, computeLeafHash, computeMerkleRoot, computeMerkleProof, verifyMerkleProof, computeRecipientsDigest, } from './recipients.js';
8
+ export type { ProofStep } from './recipients.js';
@@ -0,0 +1,8 @@
1
+ export { canonicalJson, canonicalStringify } from './canonical.js';
2
+ export { ecdhComputeShared, generateP256Keypair, privateToPublicDer } from './ecdh.js';
3
+ export { hkdfSha256 } from './hkdf.js';
4
+ export { aesGcmEncrypt, aesGcmDecrypt } from './aead.js';
5
+ export { ecdsaSignRaw, ecdsaVerifyRaw, privateScalarToPublicDer } from './ecdsa.js';
6
+ export { compute1DHWrap, compute3DHWrap, INFO_1DH, INFO_3DH, WRAP_KEY_LENGTH, } from './dh-path.js';
7
+ export { sortRecipients, computeLeafHash, computeMerkleRoot, computeMerkleProof, verifyMerkleProof, computeRecipientsDigest, } from './recipients.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/v2/crypto/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AACvF,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AACpF,OAAO,EACL,cAAc,EACd,cAAc,EACd,QAAQ,EACR,QAAQ,EACR,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * AUN E2EE V2: Recipients 排序与 Merkle Digest
3
+ *
4
+ * 规范引用:§5.3 / §10.3
5
+ *
6
+ * - 行排序:(aid asc, device_id asc, role asc) 字典序
7
+ * - 每行固定 8 字段:[aid, device_id, role, key_source, fp, spk_id, wrap_nonce, wrapped_key]
8
+ * - Digest = Merkle root(leaf/inner 各有独立前缀)
9
+ * - 奇数节点复制最后一个
10
+ */
11
+ export interface ProofStep {
12
+ sibling: string;
13
+ position: 'L' | 'R';
14
+ }
15
+ /** 按 (aid, device_id, role) 字典序稳定排序 recipients。 */
16
+ export declare function sortRecipients(rows: string[][]): string[][];
17
+ /** 计算单个 recipient 行的 leaf hash(32 字节)。 */
18
+ export declare function computeLeafHash(row: string[]): Uint8Array;
19
+ /**
20
+ * 计算 recipients 的 Merkle root(hex)。空列表返回空字符串(与 Python 一致)。
21
+ */
22
+ export declare function computeMerkleRoot(rows: string[][]): string;
23
+ /** 兼容入口,等价 computeMerkleRoot。调用方应先调 sortRecipients。 */
24
+ export declare function computeRecipientsDigest(rows: string[][]): string;
25
+ /**
26
+ * 为 targetIndex 行生成 Merkle proof(log N 步)。
27
+ */
28
+ export declare function computeMerkleProof(rows: string[][], targetIndex: number): ProofStep[];
29
+ /**
30
+ * 验证 leaf + proof 重建出的 root 与期望值一致。
31
+ */
32
+ export declare function verifyMerkleProof(leaf: Uint8Array, proof: ProofStep[], expectedRootHex: string): boolean;