@agentunion/fastaun-browser 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.
- package/CHANGELOG.md +50 -26
- package/_packed_docs/CHANGELOG.md +50 -26
- 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
- package/_packed_docs/protocol/index.md +13 -3
- package/_packed_docs/python-sdk-v2-only-changelog.md +189 -0
- package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +39 -16
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +90 -39
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +20 -3
- package/dist/auth.js.map +1 -1
- package/dist/bundle.js +14300 -0
- package/dist/client.d.ts +179 -187
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +3007 -4012
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +0 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +0 -4
- package/dist/config.js.map +1 -1
- package/dist/crypto.d.ts +8 -1
- package/dist/crypto.d.ts.map +1 -1
- package/dist/crypto.js +114 -1
- package/dist/crypto.js.map +1 -1
- package/dist/e2ee.d.ts +5 -210
- package/dist/e2ee.d.ts.map +1 -1
- package/dist/e2ee.js +4 -1379
- package/dist/e2ee.js.map +1 -1
- package/dist/index.d.ts +7 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/dist/namespaces/auth.d.ts.map +1 -1
- package/dist/namespaces/auth.js +5 -4
- package/dist/namespaces/auth.js.map +1 -1
- package/dist/protected-headers.d.ts +14 -0
- package/dist/protected-headers.d.ts.map +1 -0
- package/dist/protected-headers.js +47 -0
- package/dist/protected-headers.js.map +1 -0
- package/dist/seq-tracker.d.ts +7 -2
- package/dist/seq-tracker.d.ts.map +1 -1
- package/dist/seq-tracker.js +31 -10
- package/dist/seq-tracker.js.map +1 -1
- package/dist/v2/crypto/aead.d.ts +26 -0
- package/dist/v2/crypto/aead.d.ts.map +1 -0
- package/dist/v2/crypto/aead.js +63 -0
- package/dist/v2/crypto/aead.js.map +1 -0
- package/dist/v2/crypto/canonical.d.ts +21 -0
- package/dist/v2/crypto/canonical.d.ts.map +1 -0
- package/dist/v2/crypto/canonical.js +111 -0
- package/dist/v2/crypto/canonical.js.map +1 -0
- package/dist/v2/crypto/dh-path.d.ts +21 -0
- package/dist/v2/crypto/dh-path.d.ts.map +1 -0
- package/dist/v2/crypto/dh-path.js +50 -0
- package/dist/v2/crypto/dh-path.js.map +1 -0
- package/dist/v2/crypto/ecdh.d.ts +19 -0
- package/dist/v2/crypto/ecdh.d.ts.map +1 -0
- package/dist/v2/crypto/ecdh.js +101 -0
- package/dist/v2/crypto/ecdh.js.map +1 -0
- package/dist/v2/crypto/ecdsa.d.ts +16 -0
- package/dist/v2/crypto/ecdsa.d.ts.map +1 -0
- package/dist/v2/crypto/ecdsa.js +52 -0
- package/dist/v2/crypto/ecdsa.js.map +1 -0
- package/dist/v2/crypto/hkdf.d.ts +21 -0
- package/dist/v2/crypto/hkdf.d.ts.map +1 -0
- package/dist/v2/crypto/hkdf.js +32 -0
- package/dist/v2/crypto/hkdf.js.map +1 -0
- package/dist/v2/crypto/index.d.ts +9 -0
- package/dist/v2/crypto/index.d.ts.map +1 -0
- package/dist/v2/crypto/index.js +8 -0
- package/dist/v2/crypto/index.js.map +1 -0
- package/dist/v2/crypto/recipients.d.ts +43 -0
- package/dist/v2/crypto/recipients.d.ts.map +1 -0
- package/dist/v2/crypto/recipients.js +188 -0
- package/dist/v2/crypto/recipients.js.map +1 -0
- package/dist/v2/e2ee/decrypt.d.ts +13 -0
- package/dist/v2/e2ee/decrypt.d.ts.map +1 -0
- package/dist/v2/e2ee/decrypt.js +176 -0
- package/dist/v2/e2ee/decrypt.js.map +1 -0
- package/dist/v2/e2ee/encrypt-group.d.ts +14 -0
- package/dist/v2/e2ee/encrypt-group.d.ts.map +1 -0
- package/dist/v2/e2ee/encrypt-group.js +196 -0
- package/dist/v2/e2ee/encrypt-group.js.map +1 -0
- package/dist/v2/e2ee/encrypt-p2p.d.ts +15 -0
- package/dist/v2/e2ee/encrypt-p2p.d.ts.map +1 -0
- package/dist/v2/e2ee/encrypt-p2p.js +240 -0
- package/dist/v2/e2ee/encrypt-p2p.js.map +1 -0
- package/dist/v2/e2ee/index.d.ts +9 -0
- package/dist/v2/e2ee/index.d.ts.map +1 -0
- package/dist/v2/e2ee/index.js +9 -0
- package/dist/v2/e2ee/index.js.map +1 -0
- package/dist/v2/e2ee/metadata-auth.d.ts +9 -0
- package/dist/v2/e2ee/metadata-auth.d.ts.map +1 -0
- package/dist/v2/e2ee/metadata-auth.js +60 -0
- package/dist/v2/e2ee/metadata-auth.js.map +1 -0
- package/dist/v2/e2ee/types.d.ts +57 -0
- package/dist/v2/e2ee/types.d.ts.map +1 -0
- package/dist/v2/e2ee/types.js +7 -0
- package/dist/v2/e2ee/types.js.map +1 -0
- package/dist/v2/session/index.d.ts +4 -0
- package/dist/v2/session/index.d.ts.map +1 -0
- package/dist/v2/session/index.js +3 -0
- package/dist/v2/session/index.js.map +1 -0
- package/dist/v2/session/keystore.d.ts +48 -0
- package/dist/v2/session/keystore.d.ts.map +1 -0
- package/dist/v2/session/keystore.js +184 -0
- package/dist/v2/session/keystore.js.map +1 -0
- package/dist/v2/session/session.d.ts +98 -0
- package/dist/v2/session/session.d.ts.map +1 -0
- package/dist/v2/session/session.js +270 -0
- package/dist/v2/session/session.js.map +1 -0
- package/dist/v2/state/commitment.d.ts +10 -0
- package/dist/v2/state/commitment.d.ts.map +1 -0
- package/dist/v2/state/commitment.js +86 -0
- package/dist/v2/state/commitment.js.map +1 -0
- package/dist/v2/state/index.d.ts +2 -0
- package/dist/v2/state/index.d.ts.map +1 -0
- package/dist/v2/state/index.js +2 -0
- package/dist/v2/state/index.js.map +1 -0
- package/package.json +8 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aead.d.ts","sourceRoot":"","sources":["../../../src/v2/crypto/aead.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,UAAU,EACf,KAAK,EAAE,UAAU,EACjB,SAAS,EAAE,UAAU,EACrB,GAAG,EAAE,UAAU,GACd,OAAO,CAAC;IAAE,UAAU,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,UAAU,CAAA;CAAE,CAAC,CA8BtD;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,UAAU,EACf,KAAK,EAAE,UAAU,EACjB,UAAU,EAAE,UAAU,EACtB,GAAG,EAAE,UAAU,EACf,GAAG,EAAE,UAAU,GACd,OAAO,CAAC,UAAU,CAAC,CA6BrB"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AUN E2EE V2: AES-256-GCM AEAD
|
|
3
|
+
*
|
|
4
|
+
* 规范引用: §3.3 / §5.1
|
|
5
|
+
* - key: 32 字节
|
|
6
|
+
* - nonce: 12 字节(不可重用)
|
|
7
|
+
* - tag: 16 字节
|
|
8
|
+
*
|
|
9
|
+
* 浏览器实现:使用 WebCrypto subtle.encrypt/decrypt('AES-GCM').
|
|
10
|
+
* - WebCrypto 输出 ciphertext || tag(16B),与 Python cryptography / Node crypto 一致。
|
|
11
|
+
* - 解密时需要将 ciphertext 与 tag 拼接成单一 buffer 传入 decrypt。
|
|
12
|
+
*/
|
|
13
|
+
const TAG_LENGTH = 16;
|
|
14
|
+
/**
|
|
15
|
+
* AES-256-GCM 加密。
|
|
16
|
+
*
|
|
17
|
+
* @returns { ciphertext, tag } — 分离形式
|
|
18
|
+
*/
|
|
19
|
+
export async function aesGcmEncrypt(key, nonce, plaintext, aad) {
|
|
20
|
+
if (key.length !== 32)
|
|
21
|
+
throw new Error(`AES-256-GCM key must be 32 bytes, got ${key.length}`);
|
|
22
|
+
if (nonce.length !== 12)
|
|
23
|
+
throw new Error(`AES-GCM nonce must be 12 bytes, got ${nonce.length}`);
|
|
24
|
+
const cryptoKey = await crypto.subtle.importKey('raw', key.slice().buffer, { name: 'AES-GCM' }, false, ['encrypt']);
|
|
25
|
+
const ctWithTag = await crypto.subtle.encrypt({
|
|
26
|
+
name: 'AES-GCM',
|
|
27
|
+
iv: nonce.slice().buffer,
|
|
28
|
+
additionalData: aad.slice().buffer,
|
|
29
|
+
tagLength: TAG_LENGTH * 8,
|
|
30
|
+
}, cryptoKey, plaintext.slice().buffer);
|
|
31
|
+
const buf = new Uint8Array(ctWithTag);
|
|
32
|
+
if (buf.length < TAG_LENGTH) {
|
|
33
|
+
throw new Error(`AES-GCM output too short: ${buf.length}`);
|
|
34
|
+
}
|
|
35
|
+
// copy 出独立缓冲区,避免对外暴露 subarray 视图导致后续 slice 行为出乎意料
|
|
36
|
+
const ciphertext = buf.slice(0, buf.length - TAG_LENGTH);
|
|
37
|
+
const tag = buf.slice(buf.length - TAG_LENGTH);
|
|
38
|
+
return { ciphertext, tag };
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* AES-256-GCM 解密。
|
|
42
|
+
*/
|
|
43
|
+
export async function aesGcmDecrypt(key, nonce, ciphertext, tag, aad) {
|
|
44
|
+
if (key.length !== 32)
|
|
45
|
+
throw new Error(`AES-256-GCM key must be 32 bytes, got ${key.length}`);
|
|
46
|
+
if (nonce.length !== 12)
|
|
47
|
+
throw new Error(`AES-GCM nonce must be 12 bytes, got ${nonce.length}`);
|
|
48
|
+
if (tag.length !== TAG_LENGTH) {
|
|
49
|
+
throw new Error(`AES-GCM tag must be 16 bytes, got ${tag.length}`);
|
|
50
|
+
}
|
|
51
|
+
const ctWithTag = new Uint8Array(ciphertext.length + tag.length);
|
|
52
|
+
ctWithTag.set(ciphertext, 0);
|
|
53
|
+
ctWithTag.set(tag, ciphertext.length);
|
|
54
|
+
const cryptoKey = await crypto.subtle.importKey('raw', key.slice().buffer, { name: 'AES-GCM' }, false, ['decrypt']);
|
|
55
|
+
const pt = await crypto.subtle.decrypt({
|
|
56
|
+
name: 'AES-GCM',
|
|
57
|
+
iv: nonce.slice().buffer,
|
|
58
|
+
additionalData: aad.slice().buffer,
|
|
59
|
+
tagLength: TAG_LENGTH * 8,
|
|
60
|
+
}, cryptoKey, ctWithTag.buffer);
|
|
61
|
+
return new Uint8Array(pt);
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=aead.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aead.js","sourceRoot":"","sources":["../../../src/v2/crypto/aead.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AUN E2EE V2: Canonical JSON 序列化
|
|
3
|
+
*
|
|
4
|
+
* 规范引用: §10.2
|
|
5
|
+
* 规则:
|
|
6
|
+
* - 键递归字典序排序
|
|
7
|
+
* - UTF-8 直出(非 ASCII 不转义)
|
|
8
|
+
* - 数值无前导零、不科学计数法
|
|
9
|
+
* - 字符串最小转义(仅 " \\ \b \f \n \r \t,其它控制字符 \u00XX)
|
|
10
|
+
* - 无空格分隔(紧凑格式)
|
|
11
|
+
* - null / true / false 字面
|
|
12
|
+
* - 数组顺序保留(不排序)
|
|
13
|
+
*
|
|
14
|
+
* 输出: UTF-8 编码的 Uint8Array
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* 将任意 JS 值序列化为 Canonical JSON 的 UTF-8 字节。
|
|
18
|
+
* 所有 SDK 的输出必须字节级一致。
|
|
19
|
+
*/
|
|
20
|
+
export declare function canonicalJson(obj: unknown): Uint8Array;
|
|
21
|
+
//# sourceMappingURL=canonical.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical.d.ts","sourceRoot":"","sources":["../../../src/v2/crypto/canonical.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,UAAU,CAEtD"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AUN E2EE V2: Canonical JSON 序列化
|
|
3
|
+
*
|
|
4
|
+
* 规范引用: §10.2
|
|
5
|
+
* 规则:
|
|
6
|
+
* - 键递归字典序排序
|
|
7
|
+
* - UTF-8 直出(非 ASCII 不转义)
|
|
8
|
+
* - 数值无前导零、不科学计数法
|
|
9
|
+
* - 字符串最小转义(仅 " \\ \b \f \n \r \t,其它控制字符 \u00XX)
|
|
10
|
+
* - 无空格分隔(紧凑格式)
|
|
11
|
+
* - null / true / false 字面
|
|
12
|
+
* - 数组顺序保留(不排序)
|
|
13
|
+
*
|
|
14
|
+
* 输出: UTF-8 编码的 Uint8Array
|
|
15
|
+
*/
|
|
16
|
+
const encoder = new TextEncoder();
|
|
17
|
+
/**
|
|
18
|
+
* 将任意 JS 值序列化为 Canonical JSON 的 UTF-8 字节。
|
|
19
|
+
* 所有 SDK 的输出必须字节级一致。
|
|
20
|
+
*/
|
|
21
|
+
export function canonicalJson(obj) {
|
|
22
|
+
return encoder.encode(serialize(obj));
|
|
23
|
+
}
|
|
24
|
+
function serialize(obj) {
|
|
25
|
+
if (obj === null)
|
|
26
|
+
return 'null';
|
|
27
|
+
if (obj === true)
|
|
28
|
+
return 'true';
|
|
29
|
+
if (obj === false)
|
|
30
|
+
return 'false';
|
|
31
|
+
if (typeof obj === 'number') {
|
|
32
|
+
return serializeNumber(obj);
|
|
33
|
+
}
|
|
34
|
+
if (typeof obj === 'string') {
|
|
35
|
+
return serializeString(obj);
|
|
36
|
+
}
|
|
37
|
+
if (Array.isArray(obj)) {
|
|
38
|
+
return serializeArray(obj);
|
|
39
|
+
}
|
|
40
|
+
if (typeof obj === 'object') {
|
|
41
|
+
return serializeObject(obj);
|
|
42
|
+
}
|
|
43
|
+
throw new TypeError(`canonicalJson: unsupported type ${typeof obj}`);
|
|
44
|
+
}
|
|
45
|
+
function serializeNumber(n) {
|
|
46
|
+
if (!isFinite(n)) {
|
|
47
|
+
throw new RangeError('canonicalJson: Infinity and NaN not allowed');
|
|
48
|
+
}
|
|
49
|
+
if (Number.isInteger(n)) {
|
|
50
|
+
// 整数:直接 toString,无前导零、无科学计数法(安全整数范围内)
|
|
51
|
+
return n.toString(10);
|
|
52
|
+
}
|
|
53
|
+
// 浮点数:确保不使用科学计数法
|
|
54
|
+
let s = String(n);
|
|
55
|
+
if (s.includes('e') || s.includes('E')) {
|
|
56
|
+
// 科学计数法 → 转为定点
|
|
57
|
+
s = n.toFixed(20).replace(/0+$/, '');
|
|
58
|
+
if (s.endsWith('.')) {
|
|
59
|
+
s += '0';
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return s;
|
|
63
|
+
}
|
|
64
|
+
function serializeString(s) {
|
|
65
|
+
let result = '"';
|
|
66
|
+
for (let i = 0; i < s.length; i++) {
|
|
67
|
+
const ch = s[i];
|
|
68
|
+
const code = s.charCodeAt(i);
|
|
69
|
+
if (ch === '"') {
|
|
70
|
+
result += '\\"';
|
|
71
|
+
}
|
|
72
|
+
else if (ch === '\\') {
|
|
73
|
+
result += '\\\\';
|
|
74
|
+
}
|
|
75
|
+
else if (ch === '\b') {
|
|
76
|
+
result += '\\b';
|
|
77
|
+
}
|
|
78
|
+
else if (ch === '\f') {
|
|
79
|
+
result += '\\f';
|
|
80
|
+
}
|
|
81
|
+
else if (ch === '\n') {
|
|
82
|
+
result += '\\n';
|
|
83
|
+
}
|
|
84
|
+
else if (ch === '\r') {
|
|
85
|
+
result += '\\r';
|
|
86
|
+
}
|
|
87
|
+
else if (ch === '\t') {
|
|
88
|
+
result += '\\t';
|
|
89
|
+
}
|
|
90
|
+
else if (code < 0x20) {
|
|
91
|
+
// 其它控制字符用 \u00XX
|
|
92
|
+
result += '\\u' + code.toString(16).padStart(4, '0');
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
// 非 ASCII 直出(UTF-8 直出)
|
|
96
|
+
result += ch;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
result += '"';
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
function serializeArray(arr) {
|
|
103
|
+
const items = arr.map((item) => serialize(item));
|
|
104
|
+
return '[' + items.join(',') + ']';
|
|
105
|
+
}
|
|
106
|
+
function serializeObject(obj) {
|
|
107
|
+
const sortedKeys = Object.keys(obj).sort();
|
|
108
|
+
const pairs = sortedKeys.map((key) => serializeString(key) + ':' + serialize(obj[key]));
|
|
109
|
+
return '{' + pairs.join(',') + '}';
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=canonical.js.map
|
|
@@ -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,21 @@
|
|
|
1
|
+
export declare const INFO_3DH: Uint8Array<ArrayBuffer>;
|
|
2
|
+
export declare const INFO_1DH: Uint8Array<ArrayBuffer>;
|
|
3
|
+
export declare const WRAP_KEY_LENGTH = 32;
|
|
4
|
+
/**
|
|
5
|
+
* 计算 3DH wrap_key。
|
|
6
|
+
*
|
|
7
|
+
* - DH1 = ECDH(sender_session_priv, recv_ik_pub)
|
|
8
|
+
* - DH2 = ECDH(sender_master_priv, recv_spk_pub)
|
|
9
|
+
* - DH3 = ECDH(sender_session_priv, recv_spk_pub)
|
|
10
|
+
* - ikm = DH1 || DH2 || DH3 (96B)
|
|
11
|
+
* - wrap_key = HKDF-SHA256(ikm, salt, "AUN-V2-3DH", 32)
|
|
12
|
+
*/
|
|
13
|
+
export declare function compute3DHWrap(senderSessionPriv: Uint8Array, senderMasterPriv: Uint8Array, recvIKPub: Uint8Array, recvSPKPub: Uint8Array, salt: Uint8Array): Promise<Uint8Array>;
|
|
14
|
+
/**
|
|
15
|
+
* 计算 1DH wrap_key。
|
|
16
|
+
*
|
|
17
|
+
* - DH1 = ECDH(sender_session_priv, recv_ik_pub)
|
|
18
|
+
* - wrap_key = HKDF-SHA256(DH1, salt, "AUN-V2-1DH", 32)
|
|
19
|
+
*/
|
|
20
|
+
export declare function compute1DHWrap(senderSessionPriv: Uint8Array, recvIKPub: Uint8Array, salt: Uint8Array): Promise<Uint8Array>;
|
|
21
|
+
//# sourceMappingURL=dh-path.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dh-path.d.ts","sourceRoot":"","sources":["../../../src/v2/crypto/dh-path.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,QAAQ,yBAAyC,CAAC;AAC/D,eAAO,MAAM,QAAQ,yBAAyC,CAAC;AAC/D,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,iBAAiB,EAAE,UAAU,EAC7B,gBAAgB,EAAE,UAAU,EAC5B,SAAS,EAAE,UAAU,EACrB,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,UAAU,CAAC,CAcrB;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,iBAAiB,EAAE,UAAU,EAC7B,SAAS,EAAE,UAAU,EACrB,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,UAAU,CAAC,CAMrB"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AUN E2EE V2: DH 派生路径
|
|
3
|
+
*
|
|
4
|
+
* 规范引用: §3.1 / §5.2
|
|
5
|
+
* - 1DH: ECDH(sender_session_priv, recv_ik_pub) → HKDF
|
|
6
|
+
* - 3DH: 三个 ECDH 拼接 → HKDF
|
|
7
|
+
*
|
|
8
|
+
* 浏览器实现:组合 ecdh.ts + hkdf.ts。
|
|
9
|
+
*/
|
|
10
|
+
import { ecdhComputeShared } from './ecdh';
|
|
11
|
+
import { hkdfSha256 } from './hkdf';
|
|
12
|
+
export const INFO_3DH = new TextEncoder().encode('AUN-V2-3DH');
|
|
13
|
+
export const INFO_1DH = new TextEncoder().encode('AUN-V2-1DH');
|
|
14
|
+
export const WRAP_KEY_LENGTH = 32;
|
|
15
|
+
/**
|
|
16
|
+
* 计算 3DH wrap_key。
|
|
17
|
+
*
|
|
18
|
+
* - DH1 = ECDH(sender_session_priv, recv_ik_pub)
|
|
19
|
+
* - DH2 = ECDH(sender_master_priv, recv_spk_pub)
|
|
20
|
+
* - DH3 = ECDH(sender_session_priv, recv_spk_pub)
|
|
21
|
+
* - ikm = DH1 || DH2 || DH3 (96B)
|
|
22
|
+
* - wrap_key = HKDF-SHA256(ikm, salt, "AUN-V2-3DH", 32)
|
|
23
|
+
*/
|
|
24
|
+
export async function compute3DHWrap(senderSessionPriv, senderMasterPriv, recvIKPub, recvSPKPub, salt) {
|
|
25
|
+
const dh1 = await ecdhComputeShared(senderSessionPriv, recvIKPub);
|
|
26
|
+
const dh2 = await ecdhComputeShared(senderMasterPriv, recvSPKPub);
|
|
27
|
+
const dh3 = await ecdhComputeShared(senderSessionPriv, recvSPKPub);
|
|
28
|
+
if (dh1.length !== 32 || dh2.length !== 32 || dh3.length !== 32) {
|
|
29
|
+
throw new Error(`3DH expected 32B shares, got dh1=${dh1.length} dh2=${dh2.length} dh3=${dh3.length}`);
|
|
30
|
+
}
|
|
31
|
+
const ikm = new Uint8Array(96);
|
|
32
|
+
ikm.set(dh1, 0);
|
|
33
|
+
ikm.set(dh2, 32);
|
|
34
|
+
ikm.set(dh3, 64);
|
|
35
|
+
return hkdfSha256(ikm, salt, INFO_3DH, WRAP_KEY_LENGTH);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* 计算 1DH wrap_key。
|
|
39
|
+
*
|
|
40
|
+
* - DH1 = ECDH(sender_session_priv, recv_ik_pub)
|
|
41
|
+
* - wrap_key = HKDF-SHA256(DH1, salt, "AUN-V2-1DH", 32)
|
|
42
|
+
*/
|
|
43
|
+
export async function compute1DHWrap(senderSessionPriv, recvIKPub, salt) {
|
|
44
|
+
const dh1 = await ecdhComputeShared(senderSessionPriv, recvIKPub);
|
|
45
|
+
if (dh1.length !== 32) {
|
|
46
|
+
throw new Error(`1DH expected 32B share, got ${dh1.length}`);
|
|
47
|
+
}
|
|
48
|
+
return hkdfSha256(dh1, salt, INFO_1DH, WRAP_KEY_LENGTH);
|
|
49
|
+
}
|
|
50
|
+
//# 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;;;;;;;;GAQG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;AAC/D,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;AAC/D,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAC;AAElC;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,iBAA6B,EAC7B,gBAA4B,EAC5B,SAAqB,EACrB,UAAsB,EACtB,IAAgB;IAEhB,MAAM,GAAG,GAAG,MAAM,iBAAiB,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC;IAClE,MAAM,GAAG,GAAG,MAAM,iBAAiB,CAAC,gBAAgB,EAAE,UAAU,CAAC,CAAC;IAClE,MAAM,GAAG,GAAG,MAAM,iBAAiB,CAAC,iBAAiB,EAAE,UAAU,CAAC,CAAC;IACnE,IAAI,GAAG,CAAC,MAAM,KAAK,EAAE,IAAI,GAAG,CAAC,MAAM,KAAK,EAAE,IAAI,GAAG,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QAChE,MAAM,IAAI,KAAK,CACb,oCAAoC,GAAG,CAAC,MAAM,QAAQ,GAAG,CAAC,MAAM,QAAQ,GAAG,CAAC,MAAM,EAAE,CACrF,CAAC;IACJ,CAAC;IACD,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;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,iBAA6B,EAC7B,SAAqB,EACrB,IAAgB;IAEhB,MAAM,GAAG,GAAG,MAAM,iBAAiB,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC;IAClE,IAAI,GAAG,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,+BAA+B,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,UAAU,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;AAC1D,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 计算 ECDH 共享秘密(P-256 X 坐标,32 字节)。
|
|
3
|
+
*
|
|
4
|
+
* @param privateKeyScalar 私钥标量(32 字节 big-endian)
|
|
5
|
+
* @param peerPublicKeyDer 对端公钥(DER SubjectPublicKeyInfo 编码)
|
|
6
|
+
* @returns 32 字节共享秘密(椭圆曲线点 X 坐标)
|
|
7
|
+
*/
|
|
8
|
+
export declare function ecdhComputeShared(privateKeyScalar: Uint8Array, peerPublicKeyDer: Uint8Array): Promise<Uint8Array>;
|
|
9
|
+
/**
|
|
10
|
+
* 生成 P-256 密钥对。
|
|
11
|
+
*
|
|
12
|
+
* @returns [privateKeyScalar 32B, publicKeyDer SubjectPublicKeyInfo]
|
|
13
|
+
*/
|
|
14
|
+
export declare function generateP256Keypair(): Promise<[Uint8Array, Uint8Array]>;
|
|
15
|
+
/**
|
|
16
|
+
* 从私钥标量导出公钥 DER (SubjectPublicKeyInfo)。
|
|
17
|
+
*/
|
|
18
|
+
export declare function privateToPublicDer(privateKeyScalar: Uint8Array): Promise<Uint8Array>;
|
|
19
|
+
//# sourceMappingURL=ecdh.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ecdh.d.ts","sourceRoot":"","sources":["../../../src/v2/crypto/ecdh.ts"],"names":[],"mappings":"AA0CA;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,gBAAgB,EAAE,UAAU,EAC5B,gBAAgB,EAAE,UAAU,GAC3B,OAAO,CAAC,UAAU,CAAC,CA6CrB;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAe7E;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,gBAAgB,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAgB1F"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AUN E2EE V2: ECDH P-256
|
|
3
|
+
*
|
|
4
|
+
* 规范引用: §3.1
|
|
5
|
+
* - 曲线: P-256 (secp256r1)
|
|
6
|
+
* - 输出: 椭圆曲线点 X 坐标字节(32 字节,无前缀)
|
|
7
|
+
*
|
|
8
|
+
* 浏览器实现:使用 WebCrypto (crypto.subtle) 完成 ECDH 派生。
|
|
9
|
+
* - 私钥输入是 32 字节 raw scalar,借助 @noble/curves 推算公钥点 (X, Y),
|
|
10
|
+
* 然后构造 JWK 格式导入 WebCrypto。
|
|
11
|
+
* - 公钥输入是 DER SubjectPublicKeyInfo,直接走 spki 导入。
|
|
12
|
+
* - deriveBits(256) 返回 32 字节 X 坐标,与 Python cryptography 库行为一致。
|
|
13
|
+
*/
|
|
14
|
+
import { p256 } from '@noble/curves/nist.js';
|
|
15
|
+
/** base64url(无 padding)编码,用于 JWK 字段 */
|
|
16
|
+
function bytesToB64Url(bytes) {
|
|
17
|
+
let bin = '';
|
|
18
|
+
for (let i = 0; i < bytes.length; i++)
|
|
19
|
+
bin += String.fromCharCode(bytes[i]);
|
|
20
|
+
return btoa(bin).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
21
|
+
}
|
|
22
|
+
/** base64url 解码 */
|
|
23
|
+
function b64UrlToBytes(s) {
|
|
24
|
+
const std = s.replace(/-/g, '+').replace(/_/g, '/');
|
|
25
|
+
const pad = std.length % 4 === 0 ? '' : '='.repeat(4 - (std.length % 4));
|
|
26
|
+
const bin = atob(std + pad);
|
|
27
|
+
const out = new Uint8Array(bin.length);
|
|
28
|
+
for (let i = 0; i < bin.length; i++)
|
|
29
|
+
out[i] = bin.charCodeAt(i);
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
/** 从 raw 32B scalar 推算 P-256 公钥的未压缩 (X, Y) 字节,各 32B */
|
|
33
|
+
function p256PublicXY(privateKeyScalar) {
|
|
34
|
+
// p256.getPublicKey(secretKey, isCompressed=false) → 65 字节 0x04 || X || Y
|
|
35
|
+
const pub = p256.getPublicKey(privateKeyScalar, false);
|
|
36
|
+
if (pub.length !== 65 || pub[0] !== 0x04) {
|
|
37
|
+
throw new Error(`unexpected uncompressed public key encoding: len=${pub.length}`);
|
|
38
|
+
}
|
|
39
|
+
return { x: pub.subarray(1, 33), y: pub.subarray(33, 65) };
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* 计算 ECDH 共享秘密(P-256 X 坐标,32 字节)。
|
|
43
|
+
*
|
|
44
|
+
* @param privateKeyScalar 私钥标量(32 字节 big-endian)
|
|
45
|
+
* @param peerPublicKeyDer 对端公钥(DER SubjectPublicKeyInfo 编码)
|
|
46
|
+
* @returns 32 字节共享秘密(椭圆曲线点 X 坐标)
|
|
47
|
+
*/
|
|
48
|
+
export async function ecdhComputeShared(privateKeyScalar, peerPublicKeyDer) {
|
|
49
|
+
if (privateKeyScalar.length !== 32) {
|
|
50
|
+
throw new Error(`P-256 private scalar must be 32 bytes, got ${privateKeyScalar.length}`);
|
|
51
|
+
}
|
|
52
|
+
// 推算公钥点用于构造 JWK(WebCrypto 不接受 raw scalar)
|
|
53
|
+
const { x, y } = p256PublicXY(privateKeyScalar);
|
|
54
|
+
const privJwk = {
|
|
55
|
+
kty: 'EC',
|
|
56
|
+
crv: 'P-256',
|
|
57
|
+
d: bytesToB64Url(privateKeyScalar),
|
|
58
|
+
x: bytesToB64Url(x),
|
|
59
|
+
y: bytesToB64Url(y),
|
|
60
|
+
ext: true,
|
|
61
|
+
};
|
|
62
|
+
const privKey = await crypto.subtle.importKey('jwk', privJwk, { name: 'ECDH', namedCurve: 'P-256' }, false, ['deriveBits']);
|
|
63
|
+
const pubKey = await crypto.subtle.importKey('spki',
|
|
64
|
+
// BufferSource:copy 到独立 ArrayBuffer,避免传入 SharedArrayBuffer/视图歧义
|
|
65
|
+
peerPublicKeyDer.slice().buffer, { name: 'ECDH', namedCurve: 'P-256' }, false, []);
|
|
66
|
+
const sharedBits = await crypto.subtle.deriveBits({ name: 'ECDH', public: pubKey }, privKey, 256);
|
|
67
|
+
const out = new Uint8Array(sharedBits);
|
|
68
|
+
if (out.length !== 32) {
|
|
69
|
+
throw new Error(`ECDH derive returned ${out.length} bytes, expected 32`);
|
|
70
|
+
}
|
|
71
|
+
return out;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* 生成 P-256 密钥对。
|
|
75
|
+
*
|
|
76
|
+
* @returns [privateKeyScalar 32B, publicKeyDer SubjectPublicKeyInfo]
|
|
77
|
+
*/
|
|
78
|
+
export async function generateP256Keypair() {
|
|
79
|
+
const keyPair = await crypto.subtle.generateKey({ name: 'ECDH', namedCurve: 'P-256' }, true, ['deriveBits']);
|
|
80
|
+
const jwk = await crypto.subtle.exportKey('jwk', keyPair.privateKey);
|
|
81
|
+
if (!jwk.d) {
|
|
82
|
+
throw new Error('exportKey(jwk) returned no private component');
|
|
83
|
+
}
|
|
84
|
+
const priv = b64UrlToBytes(jwk.d);
|
|
85
|
+
const pubDerBuf = await crypto.subtle.exportKey('spki', keyPair.publicKey);
|
|
86
|
+
return [priv, new Uint8Array(pubDerBuf)];
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* 从私钥标量导出公钥 DER (SubjectPublicKeyInfo)。
|
|
90
|
+
*/
|
|
91
|
+
export async function privateToPublicDer(privateKeyScalar) {
|
|
92
|
+
if (privateKeyScalar.length !== 32) {
|
|
93
|
+
throw new Error(`P-256 private scalar must be 32 bytes, got ${privateKeyScalar.length}`);
|
|
94
|
+
}
|
|
95
|
+
const { x, y } = p256PublicXY(privateKeyScalar);
|
|
96
|
+
// 仅导入公钥点,再以 spki 导出
|
|
97
|
+
const pubKey = await crypto.subtle.importKey('jwk', { kty: 'EC', crv: 'P-256', x: bytesToB64Url(x), y: bytesToB64Url(y), ext: true }, { name: 'ECDH', namedCurve: 'P-256' }, true, []);
|
|
98
|
+
const der = await crypto.subtle.exportKey('spki', pubKey);
|
|
99
|
+
return new Uint8Array(der);
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=ecdh.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ecdh.js","sourceRoot":"","sources":["../../../src/v2/crypto/ecdh.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ECDSA-SHA256 RAW 签名(RFC 6979 deterministic, r||s 64 字节)。
|
|
3
|
+
*
|
|
4
|
+
* @param privateKeyScalar 32 字节 P-256 私钥标量
|
|
5
|
+
* @param message 原始消息(noble 内部 SHA-256)
|
|
6
|
+
*/
|
|
7
|
+
export declare function ecdsaSignRaw(privateKeyScalar: Uint8Array, message: Uint8Array): Promise<Uint8Array>;
|
|
8
|
+
/**
|
|
9
|
+
* ECDSA-SHA256 RAW 验签。
|
|
10
|
+
*
|
|
11
|
+
* @param publicKeyDer SPKI DER 公钥
|
|
12
|
+
* @param signatureRaw 64 字节 r||s
|
|
13
|
+
* @param message 原始消息(内部做 SHA-256)
|
|
14
|
+
*/
|
|
15
|
+
export declare function ecdsaVerifyRaw(publicKeyDer: Uint8Array, signatureRaw: Uint8Array, message: Uint8Array): Promise<boolean>;
|
|
16
|
+
//# sourceMappingURL=ecdsa.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ecdsa.d.ts","sourceRoot":"","sources":["../../../src/v2/crypto/ecdsa.ts"],"names":[],"mappings":"AAeA;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,gBAAgB,EAAE,UAAU,EAC5B,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,UAAU,CAAC,CAWrB;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,YAAY,EAAE,UAAU,EACxB,YAAY,EAAE,UAAU,EACxB,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,OAAO,CAAC,CAoBlB"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AUN E2EE V2: ECDSA P-256 + SHA-256 RAW(r||s, 64B)
|
|
3
|
+
*
|
|
4
|
+
* 规范引用: §3.4 / §5.1 / §10
|
|
5
|
+
*
|
|
6
|
+
* 浏览器实现:
|
|
7
|
+
* - 签名:使用 @noble/curves p256(RFC 6979 deterministic),保持与 Python /
|
|
8
|
+
* Go SDK 字节一致。WebCrypto 的 ECDSA 签名是不确定性的(每次随机 k),
|
|
9
|
+
* 无法用于 golden 比对,因此签名走 noble。
|
|
10
|
+
* - 验签:用 WebCrypto subtle.verify,公钥从 SPKI DER 导入。
|
|
11
|
+
* - 哈希:noble p256.sign 默认 prehash=true(自带 SHA-256),与 Python /
|
|
12
|
+
* Go ECDSA-SHA256 行为一致;显式传 prehash 让意图更明确。
|
|
13
|
+
*/
|
|
14
|
+
import { p256 } from '@noble/curves/nist.js';
|
|
15
|
+
/**
|
|
16
|
+
* ECDSA-SHA256 RAW 签名(RFC 6979 deterministic, r||s 64 字节)。
|
|
17
|
+
*
|
|
18
|
+
* @param privateKeyScalar 32 字节 P-256 私钥标量
|
|
19
|
+
* @param message 原始消息(noble 内部 SHA-256)
|
|
20
|
+
*/
|
|
21
|
+
export async function ecdsaSignRaw(privateKeyScalar, message) {
|
|
22
|
+
if (privateKeyScalar.length !== 32) {
|
|
23
|
+
throw new Error(`ECDSA private key must be 32 bytes, got ${privateKeyScalar.length}`);
|
|
24
|
+
}
|
|
25
|
+
// noble v2: sign 直接返回 Uint8Array(默认 format='compact' 即 r||s 64B)
|
|
26
|
+
// lowS=false 与 Python cryptography / Go ecdsa 行为一致
|
|
27
|
+
const sig = p256.sign(message, privateKeyScalar, { lowS: false, prehash: true });
|
|
28
|
+
if (!(sig instanceof Uint8Array) || sig.length !== 64) {
|
|
29
|
+
throw new Error(`unexpected ECDSA signature shape: ${sig?.constructor?.name} len=${sig?.length}`);
|
|
30
|
+
}
|
|
31
|
+
return sig;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* ECDSA-SHA256 RAW 验签。
|
|
35
|
+
*
|
|
36
|
+
* @param publicKeyDer SPKI DER 公钥
|
|
37
|
+
* @param signatureRaw 64 字节 r||s
|
|
38
|
+
* @param message 原始消息(内部做 SHA-256)
|
|
39
|
+
*/
|
|
40
|
+
export async function ecdsaVerifyRaw(publicKeyDer, signatureRaw, message) {
|
|
41
|
+
if (signatureRaw.length !== 64)
|
|
42
|
+
return false;
|
|
43
|
+
try {
|
|
44
|
+
const pubKey = await crypto.subtle.importKey('spki', publicKeyDer.slice().buffer, { name: 'ECDSA', namedCurve: 'P-256' }, false, ['verify']);
|
|
45
|
+
const ok = await crypto.subtle.verify({ name: 'ECDSA', hash: { name: 'SHA-256' } }, pubKey, signatureRaw.slice().buffer, message.slice().buffer);
|
|
46
|
+
return Boolean(ok);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=ecdsa.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ecdsa.js","sourceRoot":"","sources":["../../../src/v2/crypto/ecdsa.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAE7C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,gBAA4B,EAC5B,OAAmB;IAEnB,IAAI,gBAAgB,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,2CAA2C,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC;IACxF,CAAC;IACD,iEAAiE;IACjE,mDAAmD;IACnD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IACjF,IAAI,CAAC,CAAC,GAAG,YAAY,UAAU,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,qCAAqC,GAAG,EAAE,WAAW,EAAE,IAAI,QAAS,GAA2B,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7H,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,YAAwB,EACxB,YAAwB,EACxB,OAAmB;IAEnB,IAAI,YAAY,CAAC,MAAM,KAAK,EAAE;QAAE,OAAO,KAAK,CAAC;IAC7C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAC1C,MAAM,EACN,YAAY,CAAC,KAAK,EAAE,CAAC,MAAM,EAC3B,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,EACtC,KAAK,EACL,CAAC,QAAQ,CAAC,CACX,CAAC;QACF,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CACnC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAC5C,MAAM,EACN,YAAY,CAAC,KAAK,EAAE,CAAC,MAAM,EAC3B,OAAO,CAAC,KAAK,EAAE,CAAC,MAAM,CACvB,CAAC;QACF,OAAO,OAAO,CAAC,EAAE,CAAC,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AUN E2EE V2: HKDF-SHA256
|
|
3
|
+
*
|
|
4
|
+
* 规范引用: §3.2 / §5.2 / §10
|
|
5
|
+
*
|
|
6
|
+
* 浏览器实现:使用 WebCrypto subtle.deriveBits 完成 HKDF。
|
|
7
|
+
* - salt 长度为 0 时按 RFC 5869 规则替换为 32 字节零(与 Python sdk 行为一致)。
|
|
8
|
+
* - info 必须是 BufferSource(Uint8Array 即可)。
|
|
9
|
+
* - 输出长度由 `length` 控制(字节数)。
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* 计算 HKDF-SHA256(ikm, salt, info, length)。
|
|
13
|
+
*
|
|
14
|
+
* @param ikm 输入密钥材料
|
|
15
|
+
* @param salt 盐(可空)
|
|
16
|
+
* @param info 上下文/信息字段
|
|
17
|
+
* @param length 输出字节数
|
|
18
|
+
* @returns 派生密钥
|
|
19
|
+
*/
|
|
20
|
+
export declare function hkdfSha256(ikm: Uint8Array, salt: Uint8Array, info: Uint8Array, length: number): Promise<Uint8Array>;
|
|
21
|
+
//# sourceMappingURL=hkdf.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hkdf.d.ts","sourceRoot":"","sources":["../../../src/v2/crypto/hkdf.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAC9B,GAAG,EAAE,UAAU,EACf,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,UAAU,CAAC,CAqBrB"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AUN E2EE V2: HKDF-SHA256
|
|
3
|
+
*
|
|
4
|
+
* 规范引用: §3.2 / §5.2 / §10
|
|
5
|
+
*
|
|
6
|
+
* 浏览器实现:使用 WebCrypto subtle.deriveBits 完成 HKDF。
|
|
7
|
+
* - salt 长度为 0 时按 RFC 5869 规则替换为 32 字节零(与 Python sdk 行为一致)。
|
|
8
|
+
* - info 必须是 BufferSource(Uint8Array 即可)。
|
|
9
|
+
* - 输出长度由 `length` 控制(字节数)。
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* 计算 HKDF-SHA256(ikm, salt, info, length)。
|
|
13
|
+
*
|
|
14
|
+
* @param ikm 输入密钥材料
|
|
15
|
+
* @param salt 盐(可空)
|
|
16
|
+
* @param info 上下文/信息字段
|
|
17
|
+
* @param length 输出字节数
|
|
18
|
+
* @returns 派生密钥
|
|
19
|
+
*/
|
|
20
|
+
export async function hkdfSha256(ikm, salt, info, length) {
|
|
21
|
+
const realSalt = salt.length === 0 ? new Uint8Array(32) : salt;
|
|
22
|
+
// ikm 必须是独立 ArrayBuffer,避免视图歧义
|
|
23
|
+
const baseKey = await crypto.subtle.importKey('raw', ikm.slice().buffer, 'HKDF', false, ['deriveBits']);
|
|
24
|
+
const bits = await crypto.subtle.deriveBits({
|
|
25
|
+
name: 'HKDF',
|
|
26
|
+
hash: 'SHA-256',
|
|
27
|
+
salt: realSalt.slice().buffer,
|
|
28
|
+
info: info.slice().buffer,
|
|
29
|
+
}, baseKey, length * 8);
|
|
30
|
+
return new Uint8Array(bits);
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=hkdf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hkdf.js","sourceRoot":"","sources":["../../../src/v2/crypto/hkdf.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,GAAe,EACf,IAAgB,EAChB,IAAgB,EAChB,MAAc;IAEd,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/D,+BAA+B;IAC/B,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAC3C,KAAK,EACL,GAAG,CAAC,KAAK,EAAE,CAAC,MAAM,EAClB,MAAM,EACN,KAAK,EACL,CAAC,YAAY,CAAC,CACf,CAAC;IACF,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,UAAU,CACzC;QACE,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,MAAM;QAC7B,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,MAAM;KACZ,EACf,OAAO,EACP,MAAM,GAAG,CAAC,CACX,CAAC;IACF,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { canonicalJson } from './canonical';
|
|
2
|
+
export { ecdhComputeShared, generateP256Keypair, privateToPublicDer, } from './ecdh';
|
|
3
|
+
export { hkdfSha256 } from './hkdf';
|
|
4
|
+
export { aesGcmEncrypt, aesGcmDecrypt } from './aead';
|
|
5
|
+
export { ecdsaSignRaw, ecdsaVerifyRaw } from './ecdsa';
|
|
6
|
+
export { compute1DHWrap, compute3DHWrap, INFO_1DH, INFO_3DH, WRAP_KEY_LENGTH, } from './dh-path';
|
|
7
|
+
export { sortRecipients, computeLeafHash, computeMerkleRoot, computeMerkleProof, verifyMerkleProof, computeRecipientsDigest, } from './recipients';
|
|
8
|
+
export type { ProofStep } from './recipients';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/v2/crypto/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,QAAQ,CAAC;AAChB,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACvD,OAAO,EACL,cAAc,EACd,cAAc,EACd,QAAQ,EACR,QAAQ,EACR,eAAe,GAChB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { canonicalJson } from './canonical';
|
|
2
|
+
export { ecdhComputeShared, generateP256Keypair, privateToPublicDer, } from './ecdh';
|
|
3
|
+
export { hkdfSha256 } from './hkdf';
|
|
4
|
+
export { aesGcmEncrypt, aesGcmDecrypt } from './aead';
|
|
5
|
+
export { ecdsaSignRaw, ecdsaVerifyRaw } from './ecdsa';
|
|
6
|
+
export { compute1DHWrap, compute3DHWrap, INFO_1DH, INFO_3DH, WRAP_KEY_LENGTH, } from './dh-path';
|
|
7
|
+
export { sortRecipients, computeLeafHash, computeMerkleRoot, computeMerkleProof, verifyMerkleProof, computeRecipientsDigest, } from './recipients';
|
|
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,MAAM,aAAa,CAAC;AAC5C,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,QAAQ,CAAC;AAChB,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACvD,OAAO,EACL,cAAc,EACd,cAAc,EACd,QAAQ,EACR,QAAQ,EACR,eAAe,GAChB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,cAAc,CAAC"}
|