@hongxian/crypto 0.0.0-stage → 0.1.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/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or Derivative
95
+ Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright 2026 The Hongxian Project Contributors
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
package/README.md CHANGED
@@ -1,3 +1,40 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
1
+ # @hongxian/crypto
2
+
3
+ 红线密钥体系。**零网络、零 IO、无随机源之外的副作用**——所有函数都是纯计算。
4
+
5
+ ## 密钥链路
6
+
7
+ ```
8
+ 24 词恢复短语 (BIP39)
9
+ │ Argon2id(内存硬,抗 GPU 爆破)
10
+ ▼
11
+ 主种子
12
+ ├── Ed25519 身份密钥 签名:证明「这张卡是我发的」
13
+ ├── X25519 协商密钥 封装:把对称密钥交给对方
14
+ └── HKDF 派生的层密钥 L1 / L2 / L3,各自独立
15
+ ```
16
+
17
+ L3 是 sealed container,每个字段用 `HKDF(L3层密钥, "l3/<字段名>")` 单独派生一把子密钥。
18
+ 所以「只给微信号、不给手机号」在密码学上成立,不是靠自觉。
19
+
20
+ ## 用法
21
+
22
+ ```ts
23
+ import { mnemonicToKeys, signCard, verifyCard, sealLayer, openLayer } from '@hongxian/crypto';
24
+
25
+ const keys = await mnemonicToKeys(mnemonic);
26
+ const sealed = sealLayer(keys.layers.L2, JSON.stringify(payload));
27
+ ```
28
+
29
+ ## 命令
30
+
31
+ - **密钥即身份**:没有邮箱、没有手机号、没有密码。恢复短语是唯一备份,丢了就没了,没有找回通道。
32
+ - 恢复短语只在本机生成与使用,永不外发。
33
+ - 封装用 AES-256-GCM;签名用 Ed25519;协商用 X25519。底层是 audited 的 noble / hash-wasm,不含自研密码学。
34
+
35
+ ## 许可
36
+
37
+ Apache-2.0。
38
+
39
+ - 源码:https://github.com/hongxian-dev/hongxian/tree/main/packages/crypto
40
+ - 理论说明:https://github.com/hongxian-dev/hongxian/blob/main/docs/protocol-v1-spec.md
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @hongxian/crypto —— 红线密钥体系
3
+ *
4
+ * 恢复短语(BIP39 中文 24 词)→ Argon2id → 三种子密钥;
5
+ * Ed25519 签名 / X25519 sealed box / AES-256-GCM;私钥永不落明文。
6
+ */
7
+ export * from './mnemonic.js';
8
+ export * from './kdf.js';
9
+ export * from './primitives.js';
10
+ export * from './keystore.js';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @hongxian/crypto —— 红线密钥体系
3
+ *
4
+ * 恢复短语(BIP39 中文 24 词)→ Argon2id → 三种子密钥;
5
+ * Ed25519 签名 / X25519 sealed box / AES-256-GCM;私钥永不落明文。
6
+ */
7
+ export * from './mnemonic.js';
8
+ export * from './kdf.js';
9
+ export * from './primitives.js';
10
+ export * from './keystore.js';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC"}
package/dist/kdf.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ /**
2
+ * 红线密钥体系 · 第二层:Argon2id 主密钥派生(技术详设 §4 / 执行设计 E5)
3
+ *
4
+ * 恢复短语 → Argon2id → MK。每个密钥文件独立盐(备份/恢复单文件可行)。
5
+ * MK 仅存内存,进程退出即清零(zeroize)。
6
+ */
7
+ /** Argon2id 参数(t=3, m=64MB, p=4)——OWASP 2023 推荐档,哈希前向兼容 */
8
+ export interface Argon2Params {
9
+ /** 时间成本(迭代次数) */
10
+ iterations: number;
11
+ /** 内存成本(KiB) */
12
+ memorySize: number;
13
+ /** 并行度 */
14
+ parallelism: number;
15
+ /** 输出长度(字节) */
16
+ hashLength: number;
17
+ }
18
+ export declare const ARGON2_PARAMS: Argon2Params;
19
+ /** 从密码(BIP39 seed)与盐派生 32 字节密钥 */
20
+ export declare function deriveKey(password: Uint8Array, salt: Uint8Array, params?: Argon2Params): Promise<Uint8Array>;
21
+ /** 显式清零(MK 生命周期管理:lock / 进程退出) */
22
+ export declare function zeroize(...bufs: (Uint8Array | undefined)[]): void;
23
+ //# sourceMappingURL=kdf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kdf.d.ts","sourceRoot":"","sources":["../src/kdf.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,2DAA2D;AAC3D,MAAM,WAAW,YAAY;IAC3B,iBAAiB;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU;IACV,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,aAAa,EAAE,YAK3B,CAAC;AAEF,kCAAkC;AAClC,wBAAsB,SAAS,CAC7B,QAAQ,EAAE,UAAU,EACpB,IAAI,EAAE,UAAU,EAChB,MAAM,GAAE,YAA4B,GACnC,OAAO,CAAC,UAAU,CAAC,CAWrB;AAED,kCAAkC;AAClC,wBAAgB,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC,UAAU,GAAG,SAAS,CAAC,EAAE,GAAG,IAAI,CAIjE"}
package/dist/kdf.js ADDED
@@ -0,0 +1,34 @@
1
+ /**
2
+ * 红线密钥体系 · 第二层:Argon2id 主密钥派生(技术详设 §4 / 执行设计 E5)
3
+ *
4
+ * 恢复短语 → Argon2id → MK。每个密钥文件独立盐(备份/恢复单文件可行)。
5
+ * MK 仅存内存,进程退出即清零(zeroize)。
6
+ */
7
+ import { argon2id } from 'hash-wasm';
8
+ export const ARGON2_PARAMS = {
9
+ iterations: 3,
10
+ memorySize: 65536, // KiB = 64 MB
11
+ parallelism: 4,
12
+ hashLength: 32,
13
+ };
14
+ /** 从密码(BIP39 seed)与盐派生 32 字节密钥 */
15
+ export async function deriveKey(password, salt, params = ARGON2_PARAMS) {
16
+ const key = await argon2id({
17
+ password,
18
+ salt,
19
+ parallelism: params.parallelism,
20
+ iterations: params.iterations,
21
+ memorySize: params.memorySize,
22
+ hashLength: params.hashLength,
23
+ outputType: 'binary',
24
+ });
25
+ return new Uint8Array(key);
26
+ }
27
+ /** 显式清零(MK 生命周期管理:lock / 进程退出) */
28
+ export function zeroize(...bufs) {
29
+ for (const buf of bufs) {
30
+ if (buf)
31
+ buf.fill(0);
32
+ }
33
+ }
34
+ //# sourceMappingURL=kdf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kdf.js","sourceRoot":"","sources":["../src/kdf.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAcrC,MAAM,CAAC,MAAM,aAAa,GAAiB;IACzC,UAAU,EAAE,CAAC;IACb,UAAU,EAAE,KAAK,EAAE,cAAc;IACjC,WAAW,EAAE,CAAC;IACd,UAAU,EAAE,EAAE;CACf,CAAC;AAEF,kCAAkC;AAClC,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,QAAoB,EACpB,IAAgB,EAChB,SAAuB,aAAa;IAEpC,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC;QACzB,QAAQ;QACR,IAAI;QACJ,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,UAAU,EAAE,QAAQ;KACrB,CAAC,CAAC;IACH,OAAO,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;AAC7B,CAAC;AAED,kCAAkC;AAClC,MAAM,UAAU,OAAO,CAAC,GAAG,IAAgC;IACzD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG;YAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvB,CAAC;AACH,CAAC"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * 红线密钥体系 · 第三层:加密密钥文件与 KeyMaterial 管理
3
+ *
4
+ * 布局(技术详设 §4/§5):
5
+ * ~/.hongxian/keys/id.enc 身份密钥对(Ed25519)
6
+ * ~/.hongxian/keys/kx.enc 协商密钥对(X25519)
7
+ * ~/.hongxian/keys/lk.enc 层密钥 key_L1/L2/L3
8
+ * 每文件独立盐 + Argon2id → AES-256-GCM。私钥永不落明文;
9
+ * 解锁会话内 MK 仅存内存,lock/退出即 zeroize。
10
+ */
11
+ import { type Argon2Params } from './kdf.js';
12
+ /** 加密密钥文件格式(v1) */
13
+ export declare const EncryptedKeyFile: {
14
+ readonly version: 1;
15
+ readonly kdf: "argon2id";
16
+ readonly aead: "aes-256-gcm";
17
+ };
18
+ export interface SealedKeyFile {
19
+ v: 1;
20
+ kdf: 'argon2id';
21
+ params: {
22
+ t: number;
23
+ m: number;
24
+ p: number;
25
+ };
26
+ salt: string;
27
+ nonce: string;
28
+ ct: string;
29
+ }
30
+ /** 内存中的完整密钥材料(进程级,退出即消失) */
31
+ export interface KeyMaterial {
32
+ identityPrivate: Uint8Array;
33
+ identityPublic: Uint8Array;
34
+ kxPrivate: Uint8Array;
35
+ kxPublic: Uint8Array;
36
+ layerKeys: {
37
+ L1: Uint8Array;
38
+ L2: Uint8Array;
39
+ L3: Uint8Array;
40
+ };
41
+ }
42
+ export declare function generateKeyMaterial(): KeyMaterial;
43
+ /**
44
+ * 协议固定盐(Argon2id 派生 MK 用)——公开常量。
45
+ * seed 本身是 256-bit BIP39 输出(高熵),固定盐无安全损失
46
+ * (盐的使命是防彩虹表与并行化,对单用户单口令场景不适用)。
47
+ */
48
+ export declare const PROTOCOL_SALT: NodeJS.NonSharedUint8Array;
49
+ /**
50
+ * 从恢复短语 seed 确定性派生 KeyMaterial("恢复短语即身份"的工程实现)。
51
+ *
52
+ * 同短语 → 同 MK → 同 identity/kx/layer 密钥 → 同 owner_key_id:
53
+ * 换设备输入旧短语即重建同一身份,旧卡片签名可验、旧 grant 信封可解、
54
+ * 姻缘线关系不断(D15③ 的成立前提)。MK 仅存内存。
55
+ */
56
+ export declare function deriveKeyMaterial(seed: Uint8Array, params?: Argon2Params): Promise<KeyMaterial>;
57
+ /** owner_key_id(32 字节指纹) */
58
+ export declare function keyMaterialId(km: KeyMaterial): Uint8Array;
59
+ /** 锁定:清零全部敏感字节 */
60
+ export declare function lockKeyMaterial(km: KeyMaterial): void;
61
+ /**
62
+ * 用恢复短语 seed 加密一份明文 → SealedKeyFile。
63
+ * 盐独立随机(每文件不同盐:备份/恢复单文件可行,且盐无需保密)。
64
+ * 参数随文件记录(哈希前向兼容:未来调参不影响旧文件解密)。
65
+ */
66
+ export declare function sealKeyFile(plaintext: Uint8Array, password: Uint8Array, params?: Argon2Params): Promise<SealedKeyFile>;
67
+ /** 解密 SealedKeyFile;密码错误/文件被篡改返回 null。参数取文件自带记录 */
68
+ export declare function openKeyFile(file: SealedKeyFile, password: Uint8Array): Promise<Uint8Array | null>;
69
+ /** 从恢复短语 seed 创建三份加密文件 */
70
+ export declare function createKeyFiles(password: Uint8Array, km: KeyMaterial, params?: Argon2Params): Promise<{
71
+ id: SealedKeyFile;
72
+ kx: SealedKeyFile;
73
+ lk: SealedKeyFile;
74
+ }>;
75
+ /** 从三份加密文件 + 恢复短语 seed 恢复 KeyMaterial(换设备场景,D15③) */
76
+ export declare function restoreKeyFiles(files: {
77
+ id: SealedKeyFile;
78
+ kx: SealedKeyFile;
79
+ lk: SealedKeyFile;
80
+ }, password: Uint8Array): Promise<KeyMaterial | null>;
81
+ //# sourceMappingURL=keystore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keystore.d.ts","sourceRoot":"","sources":["../src/keystore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAiB,KAAK,YAAY,EAAsB,MAAM,UAAU,CAAC;AAchF,mBAAmB;AACnB,eAAO,MAAM,gBAAgB;;;;CAInB,CAAC;AAEX,MAAM,WAAW,aAAa;IAC5B,CAAC,EAAE,CAAC,CAAC;IACL,GAAG,EAAE,UAAU,CAAC;IAChB,MAAM,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,4BAA4B;AAC5B,MAAM,WAAW,WAAW;IAC1B,eAAe,EAAE,UAAU,CAAC;IAC5B,cAAc,EAAE,UAAU,CAAC;IAC3B,SAAS,EAAE,UAAU,CAAC;IACtB,QAAQ,EAAE,UAAU,CAAC;IACrB,SAAS,EAAE;QAAE,EAAE,EAAE,UAAU,CAAC;QAAC,EAAE,EAAE,UAAU,CAAC;QAAC,EAAE,EAAE,UAAU,CAAA;KAAE,CAAC;CAC/D;AAED,wBAAgB,mBAAmB,IAAI,WAAW,CAUjD;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,4BAA8D,CAAC;AAWzF;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAgBrG;AAED,4BAA4B;AAC5B,wBAAgB,aAAa,CAAC,EAAE,EAAE,WAAW,GAAG,UAAU,CAEzD;AAED,kBAAkB;AAClB,wBAAgB,eAAe,CAAC,EAAE,EAAE,WAAW,GAAG,IAAI,CAErD;AA0BD;;;;GAIG;AACH,wBAAsB,WAAW,CAC/B,SAAS,EAAE,UAAU,EACrB,QAAQ,EAAE,UAAU,EACpB,MAAM,GAAE,YAA4B,GACnC,OAAO,CAAC,aAAa,CAAC,CAgBxB;AAED,mDAAmD;AACnD,wBAAsB,WAAW,CAC/B,IAAI,EAAE,aAAa,EACnB,QAAQ,EAAE,UAAU,GACnB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAc5B;AAID,0BAA0B;AAC1B,wBAAsB,cAAc,CAClC,QAAQ,EAAE,UAAU,EACpB,EAAE,EAAE,WAAW,EACf,MAAM,CAAC,EAAE,YAAY,GACpB,OAAO,CAAC;IAAE,EAAE,EAAE,aAAa,CAAC;IAAC,EAAE,EAAE,aAAa,CAAC;IAAC,EAAE,EAAE,aAAa,CAAA;CAAE,CAAC,CAOtE;AAED,qDAAqD;AACrD,wBAAsB,eAAe,CACnC,KAAK,EAAE;IAAE,EAAE,EAAE,aAAa,CAAC;IAAC,EAAE,EAAE,aAAa,CAAC;IAAC,EAAE,EAAE,aAAa,CAAA;CAAE,EAClE,QAAQ,EAAE,UAAU,GACnB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAoB7B"}
@@ -0,0 +1,174 @@
1
+ /**
2
+ * 红线密钥体系 · 第三层:加密密钥文件与 KeyMaterial 管理
3
+ *
4
+ * 布局(技术详设 §4/§5):
5
+ * ~/.hongxian/keys/id.enc 身份密钥对(Ed25519)
6
+ * ~/.hongxian/keys/kx.enc 协商密钥对(X25519)
7
+ * ~/.hongxian/keys/lk.enc 层密钥 key_L1/L2/L3
8
+ * 每文件独立盐 + Argon2id → AES-256-GCM。私钥永不落明文;
9
+ * 解锁会话内 MK 仅存内存,lock/退出即 zeroize。
10
+ */
11
+ import { ARGON2_PARAMS, deriveKey, zeroize } from './kdf.js';
12
+ import { hkdf } from '@noble/hashes/hkdf';
13
+ import { sha256 } from '@noble/hashes/sha256';
14
+ import { aesGcmDecrypt, aesGcmEncrypt, generateIdentityKeyPair, generateKexKeyPair, getKexPublicKey, identityPublicKeyFromSeed, keyIdFromPublicKey, randomKey, } from './primitives.js';
15
+ /** 加密密钥文件格式(v1) */
16
+ export const EncryptedKeyFile = {
17
+ version: 1,
18
+ kdf: 'argon2id',
19
+ aead: 'aes-256-gcm',
20
+ };
21
+ export function generateKeyMaterial() {
22
+ const id = generateIdentityKeyPair();
23
+ const kx = generateKexKeyPair();
24
+ return {
25
+ identityPrivate: id.privateKey,
26
+ identityPublic: id.publicKey,
27
+ kxPrivate: kx.privateKey,
28
+ kxPublic: kx.publicKey,
29
+ layerKeys: { L1: randomKey(32), L2: randomKey(32), L3: randomKey(32) },
30
+ };
31
+ }
32
+ /**
33
+ * 协议固定盐(Argon2id 派生 MK 用)——公开常量。
34
+ * seed 本身是 256-bit BIP39 输出(高熵),固定盐无安全损失
35
+ * (盐的使命是防彩虹表与并行化,对单用户单口令场景不适用)。
36
+ */
37
+ export const PROTOCOL_SALT = new TextEncoder().encode('hongxian/protocol-v0/mk-salt/v1');
38
+ /** HKDF 域分离 info(各子密钥独立派生路径) */
39
+ const INFO = {
40
+ identity: new TextEncoder().encode('hongxian/protocol-v0/identity-seed/v1'),
41
+ kx: new TextEncoder().encode('hongxian/protocol-v0/keyexchange-seed/v1'),
42
+ L1: new TextEncoder().encode('hongxian/protocol-v0/layer-key/L1/v1'),
43
+ L2: new TextEncoder().encode('hongxian/protocol-v0/layer-key/L2/v1'),
44
+ L3: new TextEncoder().encode('hongxian/protocol-v0/layer-key/L3/v1'),
45
+ };
46
+ /**
47
+ * 从恢复短语 seed 确定性派生 KeyMaterial("恢复短语即身份"的工程实现)。
48
+ *
49
+ * 同短语 → 同 MK → 同 identity/kx/layer 密钥 → 同 owner_key_id:
50
+ * 换设备输入旧短语即重建同一身份,旧卡片签名可验、旧 grant 信封可解、
51
+ * 姻缘线关系不断(D15③ 的成立前提)。MK 仅存内存。
52
+ */
53
+ export async function deriveKeyMaterial(seed, params) {
54
+ const mk = await deriveKey(seed, PROTOCOL_SALT, params ?? ARGON2_PARAMS);
55
+ try {
56
+ const sub = (info) => hkdf(sha256, mk, undefined, info, 32);
57
+ const identityPrivate = sub(INFO.identity);
58
+ const kxPrivate = sub(INFO.kx);
59
+ return {
60
+ identityPrivate,
61
+ identityPublic: identityPublicKeyFromSeed(identityPrivate),
62
+ kxPrivate,
63
+ kxPublic: getKexPublicKey(kxPrivate),
64
+ layerKeys: { L1: sub(INFO.L1), L2: sub(INFO.L2), L3: sub(INFO.L3) },
65
+ };
66
+ }
67
+ finally {
68
+ zeroize(mk);
69
+ }
70
+ }
71
+ /** owner_key_id(32 字节指纹) */
72
+ export function keyMaterialId(km) {
73
+ return keyIdFromPublicKey(km.identityPublic);
74
+ }
75
+ /** 锁定:清零全部敏感字节 */
76
+ export function lockKeyMaterial(km) {
77
+ zeroize(km.identityPrivate, km.kxPrivate, km.layerKeys.L1, km.layerKeys.L2, km.layerKeys.L3);
78
+ }
79
+ // ---------- 文件序列化 ----------
80
+ function toB64(bytes) {
81
+ return Buffer.from(bytes).toString('base64');
82
+ }
83
+ function fromB64(s) {
84
+ return new Uint8Array(Buffer.from(s, 'base64'));
85
+ }
86
+ /** 层密钥明文结构(lk.enc 的内容) */
87
+ function serializeLayerKeys(km) {
88
+ const json = JSON.stringify({
89
+ L1: toB64(km.layerKeys.L1),
90
+ L2: toB64(km.layerKeys.L2),
91
+ L3: toB64(km.layerKeys.L3),
92
+ });
93
+ return new TextEncoder().encode(json);
94
+ }
95
+ function parseLayerKeys(bytes) {
96
+ const obj = JSON.parse(new TextDecoder().decode(bytes));
97
+ return { L1: fromB64(obj.L1), L2: fromB64(obj.L2), L3: fromB64(obj.L3) };
98
+ }
99
+ /**
100
+ * 用恢复短语 seed 加密一份明文 → SealedKeyFile。
101
+ * 盐独立随机(每文件不同盐:备份/恢复单文件可行,且盐无需保密)。
102
+ * 参数随文件记录(哈希前向兼容:未来调参不影响旧文件解密)。
103
+ */
104
+ export async function sealKeyFile(plaintext, password, params = ARGON2_PARAMS) {
105
+ const salt = randomKey(16);
106
+ const fileKey = await deriveKey(password, salt, params);
107
+ try {
108
+ const { nonce, ct } = aesGcmEncrypt(fileKey, plaintext);
109
+ return {
110
+ v: EncryptedKeyFile.version,
111
+ kdf: EncryptedKeyFile.kdf,
112
+ params: { t: params.iterations, m: params.memorySize, p: params.parallelism },
113
+ salt: toB64(salt),
114
+ nonce: toB64(nonce),
115
+ ct: toB64(ct),
116
+ };
117
+ }
118
+ finally {
119
+ zeroize(fileKey);
120
+ }
121
+ }
122
+ /** 解密 SealedKeyFile;密码错误/文件被篡改返回 null。参数取文件自带记录 */
123
+ export async function openKeyFile(file, password) {
124
+ if (file.v !== EncryptedKeyFile.version)
125
+ return null;
126
+ const salt = fromB64(file.salt);
127
+ const fileKey = await deriveKey(password, salt, {
128
+ iterations: file.params.t,
129
+ memorySize: file.params.m,
130
+ parallelism: file.params.p,
131
+ hashLength: 32,
132
+ });
133
+ try {
134
+ return aesGcmDecrypt(fileKey, fromB64(file.nonce), fromB64(file.ct));
135
+ }
136
+ finally {
137
+ zeroize(fileKey);
138
+ }
139
+ }
140
+ // ---------- 三份密钥文件的高层存取 ----------
141
+ /** 从恢复短语 seed 创建三份加密文件 */
142
+ export async function createKeyFiles(password, km, params) {
143
+ const [id, kx, lk] = await Promise.all([
144
+ sealKeyFile(km.identityPrivate, password, params),
145
+ sealKeyFile(km.kxPrivate, password, params),
146
+ sealKeyFile(serializeLayerKeys(km), password, params),
147
+ ]);
148
+ return { id, kx, lk };
149
+ }
150
+ /** 从三份加密文件 + 恢复短语 seed 恢复 KeyMaterial(换设备场景,D15③) */
151
+ export async function restoreKeyFiles(files, password) {
152
+ const [idBytes, kxBytes, lkBytes] = await Promise.all([
153
+ openKeyFile(files.id, password),
154
+ openKeyFile(files.kx, password),
155
+ openKeyFile(files.lk, password),
156
+ ]);
157
+ if (!idBytes || !kxBytes || !lkBytes)
158
+ return null;
159
+ try {
160
+ const layers = parseLayerKeys(lkBytes);
161
+ const identityPrivate = idBytes;
162
+ return {
163
+ identityPrivate,
164
+ identityPublic: identityPublicKeyFromSeed(identityPrivate),
165
+ kxPrivate: kxBytes,
166
+ kxPublic: getKexPublicKey(kxBytes),
167
+ layerKeys: layers,
168
+ };
169
+ }
170
+ catch {
171
+ return null;
172
+ }
173
+ }
174
+ //# sourceMappingURL=keystore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keystore.js","sourceRoot":"","sources":["../src/keystore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * 红线密钥体系 · 第一层:BIP39 恢复短语(技术详设 §4)
3
+ *
4
+ * 恢复短语 = 24 个中文简体词 = 身份的唯一备份通道(D15③)。
5
+ * 丢失不可恢复(设计如此);密钥文件只是短语的加密容器——容器可复制,短语才是身份。
6
+ */
7
+ /** 24 词 = 256 bit 熵(协议定稿口径) */
8
+ export declare const MNEMONIC_WORDS = 24;
9
+ /** 生成 24 词中文简体恢复短语 */
10
+ export declare function generateMnemonicZh(): string;
11
+ /** 校验中文恢复短语(词表 + 校验和) */
12
+ export declare function validateMnemonicZh(phrase: string): boolean;
13
+ /** 归一化用户输入(全角空格/多余空白 → 单空格分隔) */
14
+ export declare function normalizeMnemonic(phrase: string): string;
15
+ /** 短语 → 64 字节 BIP39 seed(Argon2id 的密码输入) */
16
+ export declare function mnemonicToSeed(phrase: string): Uint8Array;
17
+ //# sourceMappingURL=mnemonic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mnemonic.d.ts","sourceRoot":"","sources":["../src/mnemonic.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,+BAA+B;AAC/B,eAAO,MAAM,cAAc,KAAK,CAAC;AAEjC,sBAAsB;AACtB,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,yBAAyB;AACzB,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAQ1D;AAED,iCAAiC;AACjC,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAMxD;AAED,4CAA4C;AAC5C,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAKzD"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * 红线密钥体系 · 第一层:BIP39 恢复短语(技术详设 §4)
3
+ *
4
+ * 恢复短语 = 24 个中文简体词 = 身份的唯一备份通道(D15③)。
5
+ * 丢失不可恢复(设计如此);密钥文件只是短语的加密容器——容器可复制,短语才是身份。
6
+ */
7
+ import { generateMnemonic as scureGenerate, mnemonicToSeedSync, validateMnemonic as scureValidate } from '@scure/bip39';
8
+ import { wordlist } from '@scure/bip39/wordlists/simplified-chinese';
9
+ /** 24 词 = 256 bit 熵(协议定稿口径) */
10
+ export const MNEMONIC_WORDS = 24;
11
+ /** 生成 24 词中文简体恢复短语 */
12
+ export function generateMnemonicZh() {
13
+ return scureGenerate(wordlist, 256);
14
+ }
15
+ /** 校验中文恢复短语(词表 + 校验和) */
16
+ export function validateMnemonicZh(phrase) {
17
+ const words = phrase.trim().split(/\s+/).filter(Boolean);
18
+ if (words.length !== MNEMONIC_WORDS)
19
+ return false;
20
+ try {
21
+ return scureValidate(phrase.trim(), wordlist);
22
+ }
23
+ catch {
24
+ return false;
25
+ }
26
+ }
27
+ /** 归一化用户输入(全角空格/多余空白 → 单空格分隔) */
28
+ export function normalizeMnemonic(phrase) {
29
+ return phrase
30
+ .replace(/\u3000/g, ' ')
31
+ .trim()
32
+ .split(/\s+/)
33
+ .join(' ');
34
+ }
35
+ /** 短语 → 64 字节 BIP39 seed(Argon2id 的密码输入) */
36
+ export function mnemonicToSeed(phrase) {
37
+ if (!validateMnemonicZh(phrase)) {
38
+ throw new Error('恢复短语无效:必须是 24 个中文词且校验和正确');
39
+ }
40
+ return mnemonicToSeedSync(normalizeMnemonic(phrase));
41
+ }
42
+ //# sourceMappingURL=mnemonic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mnemonic.js","sourceRoot":"","sources":["../src/mnemonic.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,IAAI,aAAa,EAAE,kBAAkB,EAAE,gBAAgB,IAAI,aAAa,EAAE,MAAM,cAAc,CAAC;AACxH,OAAO,EAAE,QAAQ,EAAE,MAAM,2CAA2C,CAAC;AAErE,+BAA+B;AAC/B,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AAEjC,sBAAsB;AACtB,MAAM,UAAU,kBAAkB;IAChC,OAAO,aAAa,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AACtC,CAAC;AAED,yBAAyB;AACzB,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACzD,IAAI,KAAK,CAAC,MAAM,KAAK,cAAc;QAAE,OAAO,KAAK,CAAC;IAClD,IAAI,CAAC;QACH,OAAO,aAAa,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,iCAAiC;AACjC,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,OAAO,MAAM;SACV,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,IAAI,EAAE;SACN,KAAK,CAAC,KAAK,CAAC;SACZ,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAED,4CAA4C;AAC5C,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,kBAAkB,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC;AACvD,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * 红线密钥体系 · 原语:Ed25519 身份签名 / X25519 密钥交换 / AES-256-GCM
3
+ *
4
+ * 纯 JS(@noble),无原生依赖——跨平台安装零摩擦(技术详设 §2 选型第一原则)。
5
+ */
6
+ export type IdentityKeyPair = {
7
+ /** 32 字节私钥种子(加密存储,永不出设备) */
8
+ privateKey: Uint8Array;
9
+ publicKey: Uint8Array;
10
+ };
11
+ export declare function generateIdentityKeyPair(): IdentityKeyPair;
12
+ export declare function identityPublicKeyFromSeed(seed: Uint8Array): Uint8Array;
13
+ /** 签名(对 canonical bytes 签名,调用方负责序列化规范) */
14
+ export declare function signDetached(message: Uint8Array, privateKey: Uint8Array): Uint8Array;
15
+ export declare function verifyDetached(signature: Uint8Array, message: Uint8Array, publicKey: Uint8Array): boolean;
16
+ /** owner_key_id = SHA-256(公钥) 的 32 字节指纹(Schema §2,非身份信息) */
17
+ export declare function keyIdFromPublicKey(publicKey: Uint8Array): Uint8Array;
18
+ export type KexKeyPair = {
19
+ privateKey: Uint8Array;
20
+ publicKey: Uint8Array;
21
+ };
22
+ export declare function generateKexKeyPair(): KexKeyPair;
23
+ export declare function getKexPublicKey(privateKey: Uint8Array): Uint8Array;
24
+ /** Sealed box:临时密钥对 + ECDH + AES-GCM。输出 = ephPub(32) || nonce(12) || ct||tag */
25
+ export declare function sealBox(plaintext: Uint8Array, recipientPublicKey: Uint8Array): Uint8Array;
26
+ /** 解开 sealed box;失败(伪造/篡改/非本方)返回 null */
27
+ export declare function openBox(sealed: Uint8Array, recipientPrivateKey: Uint8Array): Uint8Array | null;
28
+ /** 加密。ct = ciphertext || tag(16B);nonce 12 字节随机 */
29
+ export declare function aesGcmEncrypt(key: Uint8Array, plaintext: Uint8Array): {
30
+ nonce: Uint8Array;
31
+ ct: Uint8Array;
32
+ };
33
+ /** 解密;认证失败返回 null(不降级、不部分解密——Schema §7.4) */
34
+ export declare function aesGcmDecrypt(key: Uint8Array, nonce: Uint8Array, ct: Uint8Array): Uint8Array | null;
35
+ /** 随机 n 字节 */
36
+ export declare function randomKey(n: number): Uint8Array;
37
+ /**
38
+ * 由层密钥派生用途子密钥:HKDF-SHA256(master, info = prefix + label)。
39
+ *
40
+ * 见面层用它把单一的 L3 层密钥摊成「每字段一把」——
41
+ * 交付 contact_wechat 的子密钥不等于交付 contact_phone 的子密钥,
42
+ * D13「给微信号但不给手机号」由此在密码学层面成立,而不只是 UI 上的开关。
43
+ *
44
+ * 单向性:子密钥推不出主密钥,也无法推到别的字段(不同 info)。
45
+ */
46
+ export declare function deriveSubkey(masterKey: Uint8Array, label: string): Uint8Array;
47
+ //# sourceMappingURL=primitives.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../src/primitives.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAUH,MAAM,MAAM,eAAe,GAAG;IAC5B,4BAA4B;IAC5B,UAAU,EAAE,UAAU,CAAC;IACvB,SAAS,EAAE,UAAU,CAAC;CACvB,CAAC;AAEF,wBAAgB,uBAAuB,IAAI,eAAe,CAIzD;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,CAEtE;AAED,0CAA0C;AAC1C,wBAAgB,YAAY,CAAC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,GAAG,UAAU,CAEpF;AAED,wBAAgB,cAAc,CAC5B,SAAS,EAAE,UAAU,EACrB,OAAO,EAAE,UAAU,EACnB,SAAS,EAAE,UAAU,GACpB,OAAO,CAMT;AAED,4DAA4D;AAC5D,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,UAAU,GAAG,UAAU,CAEpE;AAID,MAAM,MAAM,UAAU,GAAG;IACvB,UAAU,EAAE,UAAU,CAAC;IACvB,SAAS,EAAE,UAAU,CAAC;CACvB,CAAC;AAEF,wBAAgB,kBAAkB,IAAI,UAAU,CAI/C;AAED,wBAAgB,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,UAAU,CAElE;AAWD,gFAAgF;AAChF,wBAAgB,OAAO,CAAC,SAAS,EAAE,UAAU,EAAE,kBAAkB,EAAE,UAAU,GAAG,UAAU,CAUzF;AAED,yCAAyC;AACzC,wBAAgB,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,mBAAmB,EAAE,UAAU,GAAG,UAAU,GAAG,IAAI,CAW9F;AAID,mDAAmD;AACnD,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,GAAG;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,EAAE,EAAE,UAAU,CAAA;CAAE,CAK3G;AAED,6CAA6C;AAC7C,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,UAAU,GAAG,UAAU,GAAG,IAAI,CAQnG;AAED,cAAc;AACd,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,UAAU,CAE/C;AAOD;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,CAI7E"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * 红线密钥体系 · 原语:Ed25519 身份签名 / X25519 密钥交换 / AES-256-GCM
3
+ *
4
+ * 纯 JS(@noble),无原生依赖——跨平台安装零摩擦(技术详设 §2 选型第一原则)。
5
+ */
6
+ import { gcm } from '@noble/ciphers/aes';
7
+ import { ed25519, x25519 } from '@noble/curves/ed25519';
8
+ import { hkdf } from '@noble/hashes/hkdf';
9
+ import { sha256 } from '@noble/hashes/sha256';
10
+ import { randomBytes } from 'node:crypto';
11
+ export function generateIdentityKeyPair() {
12
+ const privateKey = ed25519.utils.randomPrivateKey();
13
+ const publicKey = ed25519.getPublicKey(privateKey);
14
+ return { privateKey, publicKey };
15
+ }
16
+ export function identityPublicKeyFromSeed(seed) {
17
+ return ed25519.getPublicKey(seed);
18
+ }
19
+ /** 签名(对 canonical bytes 签名,调用方负责序列化规范) */
20
+ export function signDetached(message, privateKey) {
21
+ return ed25519.sign(message, privateKey);
22
+ }
23
+ export function verifyDetached(signature, message, publicKey) {
24
+ try {
25
+ return ed25519.verify(signature, message, publicKey);
26
+ }
27
+ catch {
28
+ return false;
29
+ }
30
+ }
31
+ /** owner_key_id = SHA-256(公钥) 的 32 字节指纹(Schema §2,非身份信息) */
32
+ export function keyIdFromPublicKey(publicKey) {
33
+ return sha256(publicKey);
34
+ }
35
+ export function generateKexKeyPair() {
36
+ const privateKey = x25519.utils.randomPrivateKey();
37
+ const publicKey = x25519.getPublicKey(privateKey);
38
+ return { privateKey, publicKey };
39
+ }
40
+ export function getKexPublicKey(privateKey) {
41
+ return x25519.getPublicKey(privateKey);
42
+ }
43
+ /** 协议固定 HKDF info(域分离) */
44
+ const HKDF_INFO = new TextEncoder().encode('hongxian/protocol-v0/sealed-box/v1');
45
+ /** ECDH(ephPriv, recipientPub) → HKDF-SHA256 → AES-256-GCM 密钥 */
46
+ function deriveSharedKey(ephemeralPrivate, recipientPublic) {
47
+ const shared = x25519.getSharedSecret(ephemeralPrivate, recipientPublic);
48
+ return hkdf(sha256, shared, undefined, HKDF_INFO, 32);
49
+ }
50
+ /** Sealed box:临时密钥对 + ECDH + AES-GCM。输出 = ephPub(32) || nonce(12) || ct||tag */
51
+ export function sealBox(plaintext, recipientPublicKey) {
52
+ const eph = generateKexKeyPair();
53
+ const key = deriveSharedKey(eph.privateKey, recipientPublicKey);
54
+ const nonce = randomBytes(12);
55
+ const sealed = gcm(key, nonce).encrypt(plaintext);
56
+ const out = new Uint8Array(32 + 12 + sealed.length);
57
+ out.set(eph.publicKey, 0);
58
+ out.set(nonce, 32);
59
+ out.set(sealed, 44);
60
+ return out;
61
+ }
62
+ /** 解开 sealed box;失败(伪造/篡改/非本方)返回 null */
63
+ export function openBox(sealed, recipientPrivateKey) {
64
+ if (sealed.length < 44 + 16)
65
+ return null;
66
+ const ephPub = sealed.slice(0, 32);
67
+ const nonce = sealed.slice(32, 44);
68
+ const ct = sealed.slice(44);
69
+ try {
70
+ const key = deriveSharedKey(recipientPrivateKey, ephPub);
71
+ return gcm(key, nonce).decrypt(ct);
72
+ }
73
+ catch {
74
+ return null;
75
+ }
76
+ }
77
+ // ---------- AES-256-GCM(层密钥直接封装) ----------
78
+ /** 加密。ct = ciphertext || tag(16B);nonce 12 字节随机 */
79
+ export function aesGcmEncrypt(key, plaintext) {
80
+ if (key.length !== 32)
81
+ throw new Error('AES-256 密钥必须是 32 字节');
82
+ const nonce = randomBytes(12);
83
+ const aes = gcm(key, nonce);
84
+ return { nonce, ct: aes.encrypt(plaintext) };
85
+ }
86
+ /** 解密;认证失败返回 null(不降级、不部分解密——Schema §7.4) */
87
+ export function aesGcmDecrypt(key, nonce, ct) {
88
+ if (key.length !== 32)
89
+ throw new Error('AES-256 密钥必须是 32 字节');
90
+ try {
91
+ const aes = gcm(key, nonce);
92
+ return aes.decrypt(ct);
93
+ }
94
+ catch {
95
+ return null;
96
+ }
97
+ }
98
+ /** 随机 n 字节 */
99
+ export function randomKey(n) {
100
+ return randomBytes(n);
101
+ }
102
+ // ---------- 域分离子密钥(D13 见面层逐字段 opt-in) ----------
103
+ /** 子密钥域分离前缀(改前缀 = 协议不兼容变更,不得随意改动) */
104
+ const SUBKEY_INFO_PREFIX = 'hongxian/protocol/v1/subkey/';
105
+ /**
106
+ * 由层密钥派生用途子密钥:HKDF-SHA256(master, info = prefix + label)。
107
+ *
108
+ * 见面层用它把单一的 L3 层密钥摊成「每字段一把」——
109
+ * 交付 contact_wechat 的子密钥不等于交付 contact_phone 的子密钥,
110
+ * D13「给微信号但不给手机号」由此在密码学层面成立,而不只是 UI 上的开关。
111
+ *
112
+ * 单向性:子密钥推不出主密钥,也无法推到别的字段(不同 info)。
113
+ */
114
+ export function deriveSubkey(masterKey, label) {
115
+ if (masterKey.length !== 32)
116
+ throw new Error('主密钥必须是 32 字节');
117
+ const info = new TextEncoder().encode(SUBKEY_INFO_PREFIX + label);
118
+ return hkdf(sha256, masterKey, undefined, info, 32);
119
+ }
120
+ //# sourceMappingURL=primitives.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"primitives.js","sourceRoot":"","sources":["../src/primitives.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAU1C,MAAM,UAAU,uBAAuB;IACrC,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC;IACpD,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;IACnD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,IAAgB;IACxD,OAAO,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;AACpC,CAAC;AAED,0CAA0C;AAC1C,MAAM,UAAU,YAAY,CAAC,OAAmB,EAAE,UAAsB;IACtE,OAAO,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,SAAqB,EACrB,OAAmB,EACnB,SAAqB;IAErB,IAAI,CAAC;QACH,OAAO,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,kBAAkB,CAAC,SAAqB;IACtD,OAAO,MAAM,CAAC,SAAS,CAAC,CAAC;AAC3B,CAAC;AASD,MAAM,UAAU,kBAAkB;IAChC,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC;IACnD,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;IAClD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,UAAsB;IACpD,OAAO,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;AACzC,CAAC;AAED,0BAA0B;AAC1B,MAAM,SAAS,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,oCAAoC,CAAC,CAAC;AAEjF,iEAAiE;AACjE,SAAS,eAAe,CAAC,gBAA4B,EAAE,eAA2B;IAChF,MAAM,MAAM,GAAG,MAAM,CAAC,eAAe,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAC;IACzE,OAAO,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;AACxD,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,OAAO,CAAC,SAAqB,EAAE,kBAA8B;IAC3E,MAAM,GAAG,GAAG,kBAAkB,EAAE,CAAC;IACjC,MAAM,GAAG,GAAG,eAAe,CAAC,GAAG,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;IAChE,MAAM,KAAK,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAClD,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACpD,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;IAC1B,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACnB,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACpB,OAAO,GAAG,CAAC;AACb,CAAC;AAED,yCAAyC;AACzC,MAAM,UAAU,OAAO,CAAC,MAAkB,EAAE,mBAA+B;IACzE,IAAI,MAAM,CAAC,MAAM,GAAG,EAAE,GAAG,EAAE;QAAE,OAAO,IAAI,CAAC;IACzC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IACnC,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC5B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,eAAe,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;QACzD,OAAO,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,6CAA6C;AAE7C,mDAAmD;AACnD,MAAM,UAAU,aAAa,CAAC,GAAe,EAAE,SAAqB;IAClE,IAAI,GAAG,CAAC,MAAM,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IAC9D,MAAM,KAAK,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC;IAC9B,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC5B,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;AAC/C,CAAC;AAED,6CAA6C;AAC7C,MAAM,UAAU,aAAa,CAAC,GAAe,EAAE,KAAiB,EAAE,EAAc;IAC9E,IAAI,GAAG,CAAC,MAAM,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IAC9D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC5B,OAAO,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,cAAc;AACd,MAAM,UAAU,SAAS,CAAC,CAAS;IACjC,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC;AACxB,CAAC;AAED,kDAAkD;AAElD,qCAAqC;AACrC,MAAM,kBAAkB,GAAG,8BAA8B,CAAC;AAE1D;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,SAAqB,EAAE,KAAa;IAC/D,IAAI,SAAS,CAAC,MAAM,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC;IAC7D,MAAM,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,kBAAkB,GAAG,KAAK,CAAC,CAAC;IAClE,OAAO,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;AACtD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,47 @@
1
- {
2
- "name": "@hongxian/crypto",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
1
+ {
2
+ "name": "@hongxian/crypto",
3
+ "version": "0.1.0",
4
+ "description": "红线密钥体系:BIP39 恢复短语 → Argon2id → 身份/协商/层密钥;Ed25519 签名、X25519 封装、AES-256-GCM",
5
+ "license": "Apache-2.0",
6
+ "author": "Hongxian contributors (https://hongxian.dev)",
7
+ "homepage": "https://hongxian.dev",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/hongxian-dev/hongxian.git",
11
+ "directory": "packages/crypto"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/hongxian-dev/hongxian/issues"
15
+ },
16
+ "type": "module",
17
+ "main": "./dist/index.js",
18
+ "types": "./dist/index.d.ts",
19
+ "exports": {
20
+ ".": {
21
+ "types": "./dist/index.d.ts",
22
+ "import": "./dist/index.js"
23
+ }
24
+ },
25
+ "files": [
26
+ "dist"
27
+ ],
28
+ "scripts": {
29
+ "build": "tsc -p tsconfig.json",
30
+ "test": "vitest run",
31
+ "prepublishOnly": "node ../../scripts/guard-publish.mjs"
32
+ },
33
+ "dependencies": {
34
+ "@noble/ciphers": "^1.3.0",
35
+ "@noble/curves": "^1.9.0",
36
+ "@noble/hashes": "^1.8.0",
37
+ "@scure/bip39": "^1.5.0",
38
+ "hash-wasm": "^4.12.0"
39
+ },
40
+ "engines": {
41
+ "node": ">=20"
42
+ },
43
+ "publishConfig": {
44
+ "access": "public",
45
+ "provenance": true
46
+ }
47
+ }