secure-crypto-top-sdk 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 +21 -0
- package/README.md +238 -0
- package/dist/base-v1-7dHNy.d.mts +183 -0
- package/dist/base-v1-7dHNy.d.ts +183 -0
- package/dist/client.d.mts +72 -0
- package/dist/client.d.ts +72 -0
- package/dist/client.js +1436 -0
- package/dist/client.js.map +1 -0
- package/dist/client.mjs +1406 -0
- package/dist/client.mjs.map +1 -0
- package/dist/index.d.mts +162 -0
- package/dist/index.d.ts +162 -0
- package/dist/index.js +1393 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1335 -0
- package/dist/index.mjs.map +1 -0
- package/dist/key-store-BCmOK04m.d.ts +49 -0
- package/dist/key-store-BF0_3do0.d.mts +49 -0
- package/dist/server.d.mts +60 -0
- package/dist/server.d.ts +60 -0
- package/dist/server.js +1369 -0
- package/dist/server.js.map +1 -0
- package/dist/server.mjs +1338 -0
- package/dist/server.mjs.map +1 -0
- package/package.json +70 -0
package/dist/client.mjs
ADDED
|
@@ -0,0 +1,1406 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __esm = (fn, res) => function __init() {
|
|
4
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
5
|
+
};
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// src/errors/index.ts
|
|
12
|
+
var ErrorMessages, SecureError;
|
|
13
|
+
var init_errors = __esm({
|
|
14
|
+
"src/errors/index.ts"() {
|
|
15
|
+
"use strict";
|
|
16
|
+
ErrorMessages = {
|
|
17
|
+
[1e3 /* ENCRYPTION_FAILED */]: "\u52A0\u5BC6\u5931\u8D25",
|
|
18
|
+
[1001 /* DECRYPTION_FAILED */]: "\u89E3\u5BC6\u5931\u8D25",
|
|
19
|
+
[1002 /* INVALID_AUTH_TAG */]: "\u8BA4\u8BC1\u6807\u7B7E\u65E0\u6548",
|
|
20
|
+
[1003 /* UNSUPPORTED_CIPHER */]: "\u4E0D\u652F\u6301\u7684\u52A0\u5BC6\u7B97\u6CD5",
|
|
21
|
+
[1004 /* UNSUPPORTED_DIGEST */]: "\u4E0D\u652F\u6301\u7684\u6458\u8981/\u7B7E\u540D\u7B97\u6CD5",
|
|
22
|
+
[1005 /* INVALID_KEY_LENGTH */]: "\u5BC6\u94A5\u957F\u5EA6\u65E0\u6548",
|
|
23
|
+
[1006 /* INVALID_IV_LENGTH */]: "IV \u957F\u5EA6\u65E0\u6548",
|
|
24
|
+
[1100 /* HMAC_MISMATCH */]: "HMAC \u9A8C\u8BC1\u5931\u8D25",
|
|
25
|
+
[1101 /* SIGNATURE_MISMATCH */]: "\u7B7E\u540D\u4E0D\u5339\u914D",
|
|
26
|
+
[1102 /* TIMESTAMP_EXPIRED */]: "\u8BF7\u6C42\u5DF2\u8FC7\u671F",
|
|
27
|
+
[1103 /* NONCE_REUSED */]: "\u8BF7\u6C42\u5DF2\u88AB\u5904\u7406\uFF0C\u8BF7\u52FF\u91CD\u653E",
|
|
28
|
+
[1104 /* INVALID_TIMESTAMP */]: "\u65E0\u6548\u7684\u65F6\u95F4\u6233",
|
|
29
|
+
[1105 /* SIGN_METHOD_NOT_ALLOWED */]: "\u8BE5\u7B7E\u540D\u65B9\u6CD5\u672A\u88AB\u8BE5 app \u5141\u8BB8",
|
|
30
|
+
[1200 /* APP_NOT_FOUND */]: "\u672A\u627E\u5230\u5BF9\u5E94\u7684 app \u914D\u7F6E",
|
|
31
|
+
[1201 /* APP_DISABLED */]: "\u8BE5 app \u5DF2\u88AB\u7981\u7528",
|
|
32
|
+
[1202 /* PROTOCOL_NOT_FOUND */]: "\u672A\u6CE8\u518C\u5BF9\u5E94\u534F\u8BAE",
|
|
33
|
+
[1203 /* MISSING_APP_KEY */]: "\u7F3A\u5C11 app_key \u53C2\u6570",
|
|
34
|
+
[1204 /* MISSING_METHOD */]: "\u7F3A\u5C11 method \u53C2\u6570",
|
|
35
|
+
[1300 /* VALIDATION_ERROR */]: "\u6570\u636E\u6821\u9A8C\u5931\u8D25",
|
|
36
|
+
[1301 /* INVALID_REQUEST */]: "\u8BF7\u6C42\u683C\u5F0F\u9519\u8BEF",
|
|
37
|
+
[1302 /* INVALID_PAYLOAD */]: "\u8BF7\u6C42\u8F7D\u8377\u65E0\u6548"
|
|
38
|
+
};
|
|
39
|
+
SecureError = class extends Error {
|
|
40
|
+
constructor(code, details, statusCode) {
|
|
41
|
+
super(typeof details === "string" ? details : ErrorMessages[code]);
|
|
42
|
+
this.name = "SecureError";
|
|
43
|
+
this.code = code;
|
|
44
|
+
this.statusCode = statusCode || this.getDefaultStatusCode(code);
|
|
45
|
+
this.details = details;
|
|
46
|
+
Error.captureStackTrace(this, this.constructor);
|
|
47
|
+
}
|
|
48
|
+
getDefaultStatusCode(code) {
|
|
49
|
+
if (code >= 1e3 && code < 1100) return 400;
|
|
50
|
+
if (code >= 1100 && code < 1200) return 401;
|
|
51
|
+
if (code >= 1200 && code < 1300) return 403;
|
|
52
|
+
if (code >= 1300 && code < 1400) return 400;
|
|
53
|
+
return 500;
|
|
54
|
+
}
|
|
55
|
+
toJSON() {
|
|
56
|
+
return { success: false, code: this.code, message: this.message, details: this.details };
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// src/algorithms/cipher/aes-gcm.ts
|
|
63
|
+
import * as nodeCrypto from "crypto";
|
|
64
|
+
var META, aesGcm;
|
|
65
|
+
var init_aes_gcm = __esm({
|
|
66
|
+
"src/algorithms/cipher/aes-gcm.ts"() {
|
|
67
|
+
"use strict";
|
|
68
|
+
init_errors();
|
|
69
|
+
META = {
|
|
70
|
+
name: "aes-256-gcm",
|
|
71
|
+
keyLength: 32,
|
|
72
|
+
ivLength: 12,
|
|
73
|
+
hasAuthTag: true,
|
|
74
|
+
blockSize: 16
|
|
75
|
+
};
|
|
76
|
+
aesGcm = {
|
|
77
|
+
name: "aes-256-gcm",
|
|
78
|
+
meta: META,
|
|
79
|
+
generateKey() {
|
|
80
|
+
return nodeCrypto.randomBytes(META.keyLength);
|
|
81
|
+
},
|
|
82
|
+
generateIv() {
|
|
83
|
+
return nodeCrypto.randomBytes(META.ivLength);
|
|
84
|
+
},
|
|
85
|
+
encrypt(plain, params = {}) {
|
|
86
|
+
if (!params.key) {
|
|
87
|
+
throw new SecureError(1005 /* INVALID_KEY_LENGTH */, "AES-256-GCM \u9700\u8981\u4F20\u5165 32 \u5B57\u8282\u5BF9\u79F0\u5BC6\u94A5");
|
|
88
|
+
}
|
|
89
|
+
const key = params.key;
|
|
90
|
+
if (key.length !== META.keyLength) {
|
|
91
|
+
throw new SecureError(1005 /* INVALID_KEY_LENGTH */, `AES-256 \u5BC6\u94A5\u9700 ${META.keyLength} \u5B57\u8282`);
|
|
92
|
+
}
|
|
93
|
+
const iv = params.rsaPublicKeyPem ? nodeCrypto.randomBytes(META.ivLength) : params.iv ?? this.generateIv();
|
|
94
|
+
const cipher = nodeCrypto.createCipheriv("aes-256-gcm", key, iv, { authTagLength: 16 });
|
|
95
|
+
const enc = Buffer.concat([cipher.update(plain), cipher.final()]);
|
|
96
|
+
return { data: enc, iv, tag: cipher.getAuthTag() };
|
|
97
|
+
},
|
|
98
|
+
decrypt(cipherBuf, params) {
|
|
99
|
+
if (!params.key) throw new SecureError(1005 /* INVALID_KEY_LENGTH */, "AES-256-GCM \u9700\u8981\u5BC6\u94A5");
|
|
100
|
+
if (!params.tag) throw new SecureError(1002 /* INVALID_AUTH_TAG */, "AES-256-GCM \u9700\u8981 authTag");
|
|
101
|
+
const decipher = nodeCrypto.createDecipheriv("aes-256-gcm", params.key, params.iv, { authTagLength: 16 });
|
|
102
|
+
decipher.setAuthTag(params.tag);
|
|
103
|
+
try {
|
|
104
|
+
return Buffer.concat([decipher.update(cipherBuf), decipher.final()]);
|
|
105
|
+
} catch {
|
|
106
|
+
throw new SecureError(1002 /* INVALID_AUTH_TAG */, "AES-GCM authTag \u6821\u9A8C\u5931\u8D25,\u6570\u636E\u53EF\u80FD\u5DF2\u88AB\u7BE1\u6539");
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// src/algorithms/cipher/aes-cbc.ts
|
|
114
|
+
import * as nodeCrypto2 from "crypto";
|
|
115
|
+
function pkcs7Pad(data, blockSize) {
|
|
116
|
+
const pad = blockSize - data.length % blockSize;
|
|
117
|
+
return Buffer.concat([data, Buffer.alloc(pad, pad)]);
|
|
118
|
+
}
|
|
119
|
+
function pkcs7Unpad(data) {
|
|
120
|
+
if (data.length === 0) return data;
|
|
121
|
+
const pad = data[data.length - 1];
|
|
122
|
+
if (pad < 1 || pad > data.length) {
|
|
123
|
+
throw new SecureError(1001 /* DECRYPTION_FAILED */, "PKCS#7 padding \u65E0\u6548");
|
|
124
|
+
}
|
|
125
|
+
return data.subarray(0, data.length - pad);
|
|
126
|
+
}
|
|
127
|
+
function makeAesCbc(meta, openSslName) {
|
|
128
|
+
return {
|
|
129
|
+
name: meta.name,
|
|
130
|
+
meta,
|
|
131
|
+
generateKey() {
|
|
132
|
+
return nodeCrypto2.randomBytes(meta.keyLength);
|
|
133
|
+
},
|
|
134
|
+
generateIv() {
|
|
135
|
+
return nodeCrypto2.randomBytes(meta.ivLength);
|
|
136
|
+
},
|
|
137
|
+
encrypt(plain, params = {}) {
|
|
138
|
+
if (!params.key || params.key.length !== meta.keyLength) {
|
|
139
|
+
throw new SecureError(1005 /* INVALID_KEY_LENGTH */, `${meta.name} \u5BC6\u94A5\u9700 ${meta.keyLength} \u5B57\u8282`);
|
|
140
|
+
}
|
|
141
|
+
const iv = nodeCrypto2.randomBytes(meta.ivLength);
|
|
142
|
+
const cipher = nodeCrypto2.createCipheriv(openSslName, params.key, iv);
|
|
143
|
+
cipher.setAutoPadding(false);
|
|
144
|
+
const padded = pkcs7Pad(plain, meta.blockSize);
|
|
145
|
+
const enc = Buffer.concat([cipher.update(padded), cipher.final()]);
|
|
146
|
+
return { data: enc, iv };
|
|
147
|
+
},
|
|
148
|
+
decrypt(cipherBuf, params) {
|
|
149
|
+
if (!params.key || params.key.length !== meta.keyLength) {
|
|
150
|
+
throw new SecureError(1005 /* INVALID_KEY_LENGTH */, `${meta.name} \u5BC6\u94A5\u9700 ${meta.keyLength} \u5B57\u8282`);
|
|
151
|
+
}
|
|
152
|
+
const decipher = nodeCrypto2.createDecipheriv(openSslName, params.key, params.iv);
|
|
153
|
+
decipher.setAutoPadding(false);
|
|
154
|
+
const dec = Buffer.concat([decipher.update(cipherBuf), decipher.final()]);
|
|
155
|
+
return pkcs7Unpad(dec);
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
var META_256, META_128, aesCbc256, aesCbc128;
|
|
160
|
+
var init_aes_cbc = __esm({
|
|
161
|
+
"src/algorithms/cipher/aes-cbc.ts"() {
|
|
162
|
+
"use strict";
|
|
163
|
+
init_errors();
|
|
164
|
+
META_256 = {
|
|
165
|
+
name: "aes-256-cbc",
|
|
166
|
+
keyLength: 32,
|
|
167
|
+
ivLength: 16,
|
|
168
|
+
hasAuthTag: false,
|
|
169
|
+
blockSize: 16
|
|
170
|
+
};
|
|
171
|
+
META_128 = {
|
|
172
|
+
name: "aes-128-cbc",
|
|
173
|
+
keyLength: 16,
|
|
174
|
+
ivLength: 16,
|
|
175
|
+
hasAuthTag: false,
|
|
176
|
+
blockSize: 16
|
|
177
|
+
};
|
|
178
|
+
aesCbc256 = makeAesCbc(META_256, "aes-256-cbc");
|
|
179
|
+
aesCbc128 = makeAesCbc(META_128, "aes-128-cbc");
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
// src/algorithms/cipher/sm4-cbc.ts
|
|
184
|
+
import * as nodeCrypto3 from "crypto";
|
|
185
|
+
function rotl(x, n) {
|
|
186
|
+
return (x << n | x >>> 32 - n) >>> 0;
|
|
187
|
+
}
|
|
188
|
+
function bytesToU32(b, off) {
|
|
189
|
+
return (b[off] << 24 | b[off + 1] << 16 | b[off + 2] << 8 | b[off + 3]) >>> 0;
|
|
190
|
+
}
|
|
191
|
+
function u32ToBytes(x, b, off) {
|
|
192
|
+
b[off] = x >>> 24 & 255;
|
|
193
|
+
b[off + 1] = x >>> 16 & 255;
|
|
194
|
+
b[off + 2] = x >>> 8 & 255;
|
|
195
|
+
b[off + 3] = x & 255;
|
|
196
|
+
}
|
|
197
|
+
function tau(a) {
|
|
198
|
+
return SBOX[a >>> 24 & 255] << 24 | SBOX[a >>> 16 & 255] << 16 | SBOX[a >>> 8 & 255] << 8 | SBOX[a & 255];
|
|
199
|
+
}
|
|
200
|
+
function L(b) {
|
|
201
|
+
return b ^ rotl(b, 2) ^ rotl(b, 10) ^ rotl(b, 18) ^ rotl(b, 24);
|
|
202
|
+
}
|
|
203
|
+
function Lp(b) {
|
|
204
|
+
return b ^ rotl(b, 13) ^ rotl(b, 23);
|
|
205
|
+
}
|
|
206
|
+
function T(x) {
|
|
207
|
+
return L(tau(x));
|
|
208
|
+
}
|
|
209
|
+
function Tp(x) {
|
|
210
|
+
return Lp(tau(x));
|
|
211
|
+
}
|
|
212
|
+
function expandKey(key) {
|
|
213
|
+
const MK = new Array(4);
|
|
214
|
+
for (let i = 0; i < 4; i++) MK[i] = bytesToU32(key, i * 4);
|
|
215
|
+
const rk = new Array(32);
|
|
216
|
+
for (let i = 0; i < 32; i++) {
|
|
217
|
+
const k1 = MK[i] ^ CK[i];
|
|
218
|
+
rk[i] = k1 ^ Tp(k1 ^ MK[(i + 1) % 4] ^ MK[(i + 2) % 4] ^ MK[(i + 3) % 4]);
|
|
219
|
+
}
|
|
220
|
+
return rk;
|
|
221
|
+
}
|
|
222
|
+
function cryptBlock(input, off, rk) {
|
|
223
|
+
const X = new Array(36);
|
|
224
|
+
for (let i = 0; i < 4; i++) X[i] = bytesToU32(input, off + i * 4);
|
|
225
|
+
for (let i = 0; i < 32; i++) {
|
|
226
|
+
X[i + 4] = X[i] ^ T(X[i + 1] ^ X[i + 2] ^ X[i + 3] ^ rk[i]);
|
|
227
|
+
}
|
|
228
|
+
return [X[35], X[34], X[33], X[32]];
|
|
229
|
+
}
|
|
230
|
+
function pkcs7Pad2(data, blockSize) {
|
|
231
|
+
const pad = blockSize - data.length % blockSize;
|
|
232
|
+
return Buffer.concat([data, Buffer.alloc(pad, pad)]);
|
|
233
|
+
}
|
|
234
|
+
function pkcs7Unpad2(data) {
|
|
235
|
+
if (data.length === 0) return data;
|
|
236
|
+
const pad = data[data.length - 1];
|
|
237
|
+
if (pad < 1 || pad > data.length) throw new SecureError(1001 /* DECRYPTION_FAILED */, "PKCS#7 padding \u65E0\u6548");
|
|
238
|
+
return data.subarray(0, data.length - pad);
|
|
239
|
+
}
|
|
240
|
+
function xorBlock(a, b) {
|
|
241
|
+
const out = Buffer.alloc(a.length);
|
|
242
|
+
for (let i = 0; i < a.length; i++) out[i] = a[i] ^ b[i];
|
|
243
|
+
return out;
|
|
244
|
+
}
|
|
245
|
+
var META2, SBOX, CK, sm4Cbc;
|
|
246
|
+
var init_sm4_cbc = __esm({
|
|
247
|
+
"src/algorithms/cipher/sm4-cbc.ts"() {
|
|
248
|
+
"use strict";
|
|
249
|
+
init_errors();
|
|
250
|
+
META2 = {
|
|
251
|
+
name: "sm4-cbc",
|
|
252
|
+
keyLength: 16,
|
|
253
|
+
ivLength: 16,
|
|
254
|
+
hasAuthTag: false,
|
|
255
|
+
blockSize: 16
|
|
256
|
+
};
|
|
257
|
+
SBOX = [
|
|
258
|
+
214,
|
|
259
|
+
144,
|
|
260
|
+
233,
|
|
261
|
+
254,
|
|
262
|
+
204,
|
|
263
|
+
225,
|
|
264
|
+
61,
|
|
265
|
+
183,
|
|
266
|
+
22,
|
|
267
|
+
182,
|
|
268
|
+
20,
|
|
269
|
+
194,
|
|
270
|
+
40,
|
|
271
|
+
251,
|
|
272
|
+
44,
|
|
273
|
+
5,
|
|
274
|
+
43,
|
|
275
|
+
103,
|
|
276
|
+
154,
|
|
277
|
+
118,
|
|
278
|
+
42,
|
|
279
|
+
190,
|
|
280
|
+
4,
|
|
281
|
+
195,
|
|
282
|
+
170,
|
|
283
|
+
68,
|
|
284
|
+
19,
|
|
285
|
+
38,
|
|
286
|
+
73,
|
|
287
|
+
134,
|
|
288
|
+
6,
|
|
289
|
+
153,
|
|
290
|
+
156,
|
|
291
|
+
66,
|
|
292
|
+
80,
|
|
293
|
+
244,
|
|
294
|
+
145,
|
|
295
|
+
239,
|
|
296
|
+
152,
|
|
297
|
+
122,
|
|
298
|
+
51,
|
|
299
|
+
84,
|
|
300
|
+
11,
|
|
301
|
+
67,
|
|
302
|
+
237,
|
|
303
|
+
207,
|
|
304
|
+
172,
|
|
305
|
+
98,
|
|
306
|
+
228,
|
|
307
|
+
179,
|
|
308
|
+
28,
|
|
309
|
+
169,
|
|
310
|
+
201,
|
|
311
|
+
8,
|
|
312
|
+
232,
|
|
313
|
+
149,
|
|
314
|
+
128,
|
|
315
|
+
223,
|
|
316
|
+
148,
|
|
317
|
+
250,
|
|
318
|
+
117,
|
|
319
|
+
143,
|
|
320
|
+
63,
|
|
321
|
+
166,
|
|
322
|
+
71,
|
|
323
|
+
7,
|
|
324
|
+
167,
|
|
325
|
+
252,
|
|
326
|
+
243,
|
|
327
|
+
115,
|
|
328
|
+
23,
|
|
329
|
+
186,
|
|
330
|
+
131,
|
|
331
|
+
89,
|
|
332
|
+
60,
|
|
333
|
+
25,
|
|
334
|
+
230,
|
|
335
|
+
133,
|
|
336
|
+
79,
|
|
337
|
+
168,
|
|
338
|
+
104,
|
|
339
|
+
107,
|
|
340
|
+
129,
|
|
341
|
+
178,
|
|
342
|
+
113,
|
|
343
|
+
100,
|
|
344
|
+
218,
|
|
345
|
+
139,
|
|
346
|
+
248,
|
|
347
|
+
235,
|
|
348
|
+
15,
|
|
349
|
+
75,
|
|
350
|
+
112,
|
|
351
|
+
86,
|
|
352
|
+
157,
|
|
353
|
+
53,
|
|
354
|
+
30,
|
|
355
|
+
36,
|
|
356
|
+
14,
|
|
357
|
+
94,
|
|
358
|
+
99,
|
|
359
|
+
88,
|
|
360
|
+
209,
|
|
361
|
+
162,
|
|
362
|
+
37,
|
|
363
|
+
34,
|
|
364
|
+
124,
|
|
365
|
+
59,
|
|
366
|
+
1,
|
|
367
|
+
33,
|
|
368
|
+
120,
|
|
369
|
+
135,
|
|
370
|
+
212,
|
|
371
|
+
0,
|
|
372
|
+
70,
|
|
373
|
+
87,
|
|
374
|
+
159,
|
|
375
|
+
211,
|
|
376
|
+
39,
|
|
377
|
+
82,
|
|
378
|
+
76,
|
|
379
|
+
54,
|
|
380
|
+
2,
|
|
381
|
+
231,
|
|
382
|
+
160,
|
|
383
|
+
196,
|
|
384
|
+
200,
|
|
385
|
+
158,
|
|
386
|
+
234,
|
|
387
|
+
191,
|
|
388
|
+
138,
|
|
389
|
+
210,
|
|
390
|
+
64,
|
|
391
|
+
199,
|
|
392
|
+
56,
|
|
393
|
+
181,
|
|
394
|
+
163,
|
|
395
|
+
247,
|
|
396
|
+
242,
|
|
397
|
+
206,
|
|
398
|
+
249,
|
|
399
|
+
97,
|
|
400
|
+
21,
|
|
401
|
+
161,
|
|
402
|
+
224,
|
|
403
|
+
174,
|
|
404
|
+
93,
|
|
405
|
+
164,
|
|
406
|
+
155,
|
|
407
|
+
52,
|
|
408
|
+
26,
|
|
409
|
+
85,
|
|
410
|
+
173,
|
|
411
|
+
147,
|
|
412
|
+
50,
|
|
413
|
+
48,
|
|
414
|
+
245,
|
|
415
|
+
140,
|
|
416
|
+
177,
|
|
417
|
+
227,
|
|
418
|
+
29,
|
|
419
|
+
246,
|
|
420
|
+
226,
|
|
421
|
+
46,
|
|
422
|
+
130,
|
|
423
|
+
102,
|
|
424
|
+
202,
|
|
425
|
+
96,
|
|
426
|
+
192,
|
|
427
|
+
41,
|
|
428
|
+
35,
|
|
429
|
+
171,
|
|
430
|
+
13,
|
|
431
|
+
83,
|
|
432
|
+
78,
|
|
433
|
+
111,
|
|
434
|
+
213,
|
|
435
|
+
219,
|
|
436
|
+
55,
|
|
437
|
+
69,
|
|
438
|
+
222,
|
|
439
|
+
253,
|
|
440
|
+
142,
|
|
441
|
+
47,
|
|
442
|
+
3,
|
|
443
|
+
255,
|
|
444
|
+
106,
|
|
445
|
+
114,
|
|
446
|
+
109,
|
|
447
|
+
108,
|
|
448
|
+
91,
|
|
449
|
+
81,
|
|
450
|
+
141,
|
|
451
|
+
27,
|
|
452
|
+
175,
|
|
453
|
+
146,
|
|
454
|
+
187,
|
|
455
|
+
221,
|
|
456
|
+
188,
|
|
457
|
+
127,
|
|
458
|
+
17,
|
|
459
|
+
217,
|
|
460
|
+
92,
|
|
461
|
+
65,
|
|
462
|
+
31,
|
|
463
|
+
16,
|
|
464
|
+
90,
|
|
465
|
+
216,
|
|
466
|
+
10,
|
|
467
|
+
193,
|
|
468
|
+
49,
|
|
469
|
+
136,
|
|
470
|
+
165,
|
|
471
|
+
205,
|
|
472
|
+
123,
|
|
473
|
+
189,
|
|
474
|
+
45,
|
|
475
|
+
116,
|
|
476
|
+
208,
|
|
477
|
+
18,
|
|
478
|
+
184,
|
|
479
|
+
229,
|
|
480
|
+
180,
|
|
481
|
+
176,
|
|
482
|
+
137,
|
|
483
|
+
105,
|
|
484
|
+
151,
|
|
485
|
+
74,
|
|
486
|
+
12,
|
|
487
|
+
150,
|
|
488
|
+
119,
|
|
489
|
+
126,
|
|
490
|
+
101,
|
|
491
|
+
185,
|
|
492
|
+
241,
|
|
493
|
+
9,
|
|
494
|
+
197,
|
|
495
|
+
110,
|
|
496
|
+
198,
|
|
497
|
+
132,
|
|
498
|
+
24,
|
|
499
|
+
240,
|
|
500
|
+
125,
|
|
501
|
+
236,
|
|
502
|
+
58,
|
|
503
|
+
220,
|
|
504
|
+
77,
|
|
505
|
+
32,
|
|
506
|
+
121,
|
|
507
|
+
238,
|
|
508
|
+
95,
|
|
509
|
+
62,
|
|
510
|
+
215,
|
|
511
|
+
203,
|
|
512
|
+
57,
|
|
513
|
+
72
|
|
514
|
+
];
|
|
515
|
+
CK = [
|
|
516
|
+
462357,
|
|
517
|
+
472066609,
|
|
518
|
+
943670861,
|
|
519
|
+
1415275113,
|
|
520
|
+
1886879365,
|
|
521
|
+
2358483617,
|
|
522
|
+
2830087869,
|
|
523
|
+
3301692121,
|
|
524
|
+
3773296373,
|
|
525
|
+
4228057617,
|
|
526
|
+
404694573,
|
|
527
|
+
876298825,
|
|
528
|
+
1347903077,
|
|
529
|
+
1819507329,
|
|
530
|
+
2291111581,
|
|
531
|
+
2762715833,
|
|
532
|
+
3234320085,
|
|
533
|
+
3705924337,
|
|
534
|
+
4177462797,
|
|
535
|
+
337322537,
|
|
536
|
+
808926789,
|
|
537
|
+
1280531041,
|
|
538
|
+
1752135293,
|
|
539
|
+
2223739545,
|
|
540
|
+
2695343797,
|
|
541
|
+
3166948049,
|
|
542
|
+
3638552301,
|
|
543
|
+
4110090761,
|
|
544
|
+
269950501,
|
|
545
|
+
741554753,
|
|
546
|
+
1213159005,
|
|
547
|
+
1684763257
|
|
548
|
+
];
|
|
549
|
+
sm4Cbc = {
|
|
550
|
+
name: "sm4-cbc",
|
|
551
|
+
meta: META2,
|
|
552
|
+
generateKey() {
|
|
553
|
+
return nodeCrypto3.randomBytes(META2.keyLength);
|
|
554
|
+
},
|
|
555
|
+
generateIv() {
|
|
556
|
+
return nodeCrypto3.randomBytes(META2.ivLength);
|
|
557
|
+
},
|
|
558
|
+
encrypt(plain, params = {}) {
|
|
559
|
+
if (!params.key || params.key.length !== 16) {
|
|
560
|
+
throw new SecureError(1005 /* INVALID_KEY_LENGTH */, "SM4 \u5BC6\u94A5\u9700 16 \u5B57\u8282");
|
|
561
|
+
}
|
|
562
|
+
const rk = expandKey(params.key);
|
|
563
|
+
const iv = nodeCrypto3.randomBytes(META2.ivLength);
|
|
564
|
+
const padded = pkcs7Pad2(plain, META2.blockSize);
|
|
565
|
+
const out = Buffer.alloc(padded.length);
|
|
566
|
+
let prev = iv;
|
|
567
|
+
for (let off = 0; off < padded.length; off += 16) {
|
|
568
|
+
const block = xorBlock(padded.subarray(off, off + 16), prev);
|
|
569
|
+
const r = cryptBlock(block, 0, rk);
|
|
570
|
+
const enc = Buffer.alloc(16);
|
|
571
|
+
for (let i = 0; i < 4; i++) u32ToBytes(r[i], enc, i * 4);
|
|
572
|
+
out.set(enc, off);
|
|
573
|
+
prev = enc;
|
|
574
|
+
}
|
|
575
|
+
return { data: out, iv };
|
|
576
|
+
},
|
|
577
|
+
decrypt(cipherBuf, params) {
|
|
578
|
+
if (!params.key || params.key.length !== 16) {
|
|
579
|
+
throw new SecureError(1005 /* INVALID_KEY_LENGTH */, "SM4 \u5BC6\u94A5\u9700 16 \u5B57\u8282");
|
|
580
|
+
}
|
|
581
|
+
if (params.iv.length !== 16) {
|
|
582
|
+
throw new SecureError(1006 /* INVALID_IV_LENGTH */, "SM4 IV \u9700 16 \u5B57\u8282");
|
|
583
|
+
}
|
|
584
|
+
const rk = expandKey(params.key).slice().reverse();
|
|
585
|
+
const out = Buffer.alloc(cipherBuf.length);
|
|
586
|
+
let prev = params.iv;
|
|
587
|
+
for (let off = 0; off < cipherBuf.length; off += 16) {
|
|
588
|
+
const enc = cipherBuf.subarray(off, off + 16);
|
|
589
|
+
const r = cryptBlock(enc, 0, rk);
|
|
590
|
+
const dec = Buffer.alloc(16);
|
|
591
|
+
for (let i = 0; i < 4; i++) u32ToBytes(r[i], dec, i * 4);
|
|
592
|
+
const plain = xorBlock(dec, prev);
|
|
593
|
+
out.set(plain, off);
|
|
594
|
+
prev = enc;
|
|
595
|
+
}
|
|
596
|
+
return pkcs7Unpad2(out);
|
|
597
|
+
}
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
});
|
|
601
|
+
|
|
602
|
+
// src/algorithms/cipher/rsa-oaep-aes-gcm.ts
|
|
603
|
+
import * as nodeCrypto4 from "crypto";
|
|
604
|
+
var META3, rsaOaepAesGcm;
|
|
605
|
+
var init_rsa_oaep_aes_gcm = __esm({
|
|
606
|
+
"src/algorithms/cipher/rsa-oaep-aes-gcm.ts"() {
|
|
607
|
+
"use strict";
|
|
608
|
+
init_errors();
|
|
609
|
+
init_aes_gcm();
|
|
610
|
+
META3 = {
|
|
611
|
+
name: "rsa-oaep-aes-256-gcm",
|
|
612
|
+
keyLength: 32,
|
|
613
|
+
// 对称密钥长度
|
|
614
|
+
ivLength: 12,
|
|
615
|
+
// GCM IV 长度
|
|
616
|
+
hasAuthTag: true,
|
|
617
|
+
blockSize: 16
|
|
618
|
+
};
|
|
619
|
+
rsaOaepAesGcm = {
|
|
620
|
+
name: "rsa-oaep-aes-256-gcm",
|
|
621
|
+
meta: META3,
|
|
622
|
+
generateKey() {
|
|
623
|
+
return nodeCrypto4.randomBytes(META3.keyLength);
|
|
624
|
+
},
|
|
625
|
+
generateIv() {
|
|
626
|
+
return nodeCrypto4.randomBytes(META3.ivLength);
|
|
627
|
+
},
|
|
628
|
+
encrypt(plain, params = {}) {
|
|
629
|
+
if (!params.rsaPublicKeyPem) {
|
|
630
|
+
throw new SecureError(1e3 /* ENCRYPTION_FAILED */, "rsa-oaep-aes-256-gcm \u9700\u8981 rsaPublicKeyPem");
|
|
631
|
+
}
|
|
632
|
+
const aesKey = nodeCrypto4.randomBytes(32);
|
|
633
|
+
const iv = nodeCrypto4.randomBytes(12);
|
|
634
|
+
const r = aesGcm.encrypt(plain, { key: aesKey, iv });
|
|
635
|
+
const encryptedKey = nodeCrypto4.publicEncrypt(
|
|
636
|
+
{ key: params.rsaPublicKeyPem, padding: nodeCrypto4.constants.RSA_PKCS1_OAEP_PADDING, oaepHash: "sha256" },
|
|
637
|
+
aesKey
|
|
638
|
+
);
|
|
639
|
+
return { data: r.data, iv: r.iv, tag: r.tag, encryptedKey };
|
|
640
|
+
},
|
|
641
|
+
decrypt(cipherBuf, params) {
|
|
642
|
+
if (!params.rsaPrivateKeyPem) {
|
|
643
|
+
throw new SecureError(1001 /* DECRYPTION_FAILED */, "rsa-oaep-aes-256-gcm \u9700\u8981 rsaPrivateKeyPem");
|
|
644
|
+
}
|
|
645
|
+
if (!params.encryptedKey) {
|
|
646
|
+
throw new SecureError(1001 /* DECRYPTION_FAILED */, "\u7F3A\u5C11 encryptedKey");
|
|
647
|
+
}
|
|
648
|
+
const aesKey = nodeCrypto4.privateDecrypt(
|
|
649
|
+
{ key: params.rsaPrivateKeyPem, padding: nodeCrypto4.constants.RSA_PKCS1_OAEP_PADDING, oaepHash: "sha256" },
|
|
650
|
+
params.encryptedKey
|
|
651
|
+
);
|
|
652
|
+
return aesGcm.decrypt(cipherBuf, { key: aesKey, iv: params.iv, tag: params.tag });
|
|
653
|
+
}
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
});
|
|
657
|
+
|
|
658
|
+
// src/algorithms/cipher/index.ts
|
|
659
|
+
var init_cipher = __esm({
|
|
660
|
+
"src/algorithms/cipher/index.ts"() {
|
|
661
|
+
"use strict";
|
|
662
|
+
init_aes_gcm();
|
|
663
|
+
init_aes_cbc();
|
|
664
|
+
init_sm4_cbc();
|
|
665
|
+
init_rsa_oaep_aes_gcm();
|
|
666
|
+
}
|
|
667
|
+
});
|
|
668
|
+
|
|
669
|
+
// src/algorithms/digest/hmac.ts
|
|
670
|
+
import * as nodeCrypto5 from "crypto";
|
|
671
|
+
function makeHmac(meta, algo) {
|
|
672
|
+
return {
|
|
673
|
+
name: meta.name,
|
|
674
|
+
meta,
|
|
675
|
+
sign(data, key) {
|
|
676
|
+
if (!key) throw new SecureError(1005 /* INVALID_KEY_LENGTH */, `${meta.name} \u9700\u8981\u5BC6\u94A5`);
|
|
677
|
+
const keyBuf = typeof key === "string" ? Buffer.from(key, "utf-8") : key;
|
|
678
|
+
if (keyBuf.length < meta.minKeyLength) {
|
|
679
|
+
throw new SecureError(1005 /* INVALID_KEY_LENGTH */, `${meta.name} \u5BC6\u94A5\u81F3\u5C11 ${meta.minKeyLength} \u5B57\u8282`);
|
|
680
|
+
}
|
|
681
|
+
const dataBuf = typeof data === "string" ? Buffer.from(data, "utf-8") : data;
|
|
682
|
+
return nodeCrypto5.createHmac(algo, keyBuf).update(dataBuf).digest("hex");
|
|
683
|
+
},
|
|
684
|
+
verify(sig, data, key) {
|
|
685
|
+
const expected = this.sign(data, key);
|
|
686
|
+
try {
|
|
687
|
+
return nodeCrypto5.timingSafeEqual(Buffer.from(sig, "hex"), Buffer.from(expected, "hex"));
|
|
688
|
+
} catch {
|
|
689
|
+
return false;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
var META_2562, META_512, hmacSha256, hmacSha512;
|
|
695
|
+
var init_hmac = __esm({
|
|
696
|
+
"src/algorithms/digest/hmac.ts"() {
|
|
697
|
+
"use strict";
|
|
698
|
+
init_errors();
|
|
699
|
+
META_2562 = {
|
|
700
|
+
name: "hmac-sha256",
|
|
701
|
+
outputLength: 32,
|
|
702
|
+
keyed: true,
|
|
703
|
+
minKeyLength: 16
|
|
704
|
+
};
|
|
705
|
+
META_512 = {
|
|
706
|
+
name: "hmac-sha512",
|
|
707
|
+
outputLength: 64,
|
|
708
|
+
keyed: true,
|
|
709
|
+
minKeyLength: 16
|
|
710
|
+
};
|
|
711
|
+
hmacSha256 = makeHmac(META_2562, "sha256");
|
|
712
|
+
hmacSha512 = makeHmac(META_512, "sha512");
|
|
713
|
+
}
|
|
714
|
+
});
|
|
715
|
+
|
|
716
|
+
// src/algorithms/digest/hash.ts
|
|
717
|
+
import * as nodeCrypto6 from "crypto";
|
|
718
|
+
function makeHash(meta, algo) {
|
|
719
|
+
return {
|
|
720
|
+
name: meta.name,
|
|
721
|
+
meta,
|
|
722
|
+
sign(data) {
|
|
723
|
+
const dataBuf = typeof data === "string" ? Buffer.from(data, "utf-8") : data;
|
|
724
|
+
return nodeCrypto6.createHash(algo).update(dataBuf).digest("hex");
|
|
725
|
+
},
|
|
726
|
+
// 非密钥散列的"verify"是直接比较
|
|
727
|
+
verify(sig, data) {
|
|
728
|
+
try {
|
|
729
|
+
return this.sign(data) === sig.toLowerCase();
|
|
730
|
+
} catch {
|
|
731
|
+
return false;
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
var META_MD5, META_SHA256, md5, sha256;
|
|
737
|
+
var init_hash = __esm({
|
|
738
|
+
"src/algorithms/digest/hash.ts"() {
|
|
739
|
+
"use strict";
|
|
740
|
+
META_MD5 = {
|
|
741
|
+
name: "md5",
|
|
742
|
+
outputLength: 16,
|
|
743
|
+
keyed: false,
|
|
744
|
+
minKeyLength: 0
|
|
745
|
+
};
|
|
746
|
+
META_SHA256 = {
|
|
747
|
+
name: "sha256",
|
|
748
|
+
outputLength: 32,
|
|
749
|
+
keyed: false,
|
|
750
|
+
minKeyLength: 0
|
|
751
|
+
};
|
|
752
|
+
md5 = makeHash(META_MD5, "md5");
|
|
753
|
+
sha256 = makeHash(META_SHA256, "sha256");
|
|
754
|
+
}
|
|
755
|
+
});
|
|
756
|
+
|
|
757
|
+
// src/algorithms/digest/sm3.ts
|
|
758
|
+
function rotl2(x, n) {
|
|
759
|
+
return (x << n | x >>> 32 - n) >>> 0;
|
|
760
|
+
}
|
|
761
|
+
function P0(x) {
|
|
762
|
+
return x ^ rotl2(x, 9) ^ rotl2(x, 17);
|
|
763
|
+
}
|
|
764
|
+
function P1(x) {
|
|
765
|
+
return x ^ rotl2(x, 15) ^ rotl2(x, 23);
|
|
766
|
+
}
|
|
767
|
+
function FF(x, y, z, j) {
|
|
768
|
+
return j < 16 ? x ^ y ^ z : x & y | x & z | y & z;
|
|
769
|
+
}
|
|
770
|
+
function GG(x, y, z, j) {
|
|
771
|
+
return j < 16 ? x ^ y ^ z : x & y | (~x & z) >>> 0;
|
|
772
|
+
}
|
|
773
|
+
function Tj(j) {
|
|
774
|
+
return j < 16 ? 2043430169 : 2055708042;
|
|
775
|
+
}
|
|
776
|
+
function CF(V, B) {
|
|
777
|
+
const W = new Uint32Array(68);
|
|
778
|
+
const W1 = new Uint32Array(64);
|
|
779
|
+
for (let i = 0; i < 16; i++) W[i] = B[i];
|
|
780
|
+
for (let i = 16; i < 68; i++) {
|
|
781
|
+
W[i] = P1(W[i - 16] ^ W[i - 9] ^ rotl2(W[i - 3], 15)) ^ rotl2(W[i - 13], 7) ^ W[i - 6];
|
|
782
|
+
}
|
|
783
|
+
for (let i = 0; i < 64; i++) W1[i] = W[i] ^ W[i + 4];
|
|
784
|
+
let A = V[0], Bb = V[1], C = V[2], D = V[3];
|
|
785
|
+
let E = V[4], F = V[5], G = V[6], H = V[7];
|
|
786
|
+
for (let j = 0; j < 64; j++) {
|
|
787
|
+
const SS1 = rotl2(rotl2(A, 12) + E + rotl2(Tj(j), j), 7);
|
|
788
|
+
const SS2 = SS1 ^ rotl2(A, 12);
|
|
789
|
+
const TT1 = FF(A, Bb, C, j) + D + SS2 + W1[j] >>> 0;
|
|
790
|
+
const TT2 = GG(E, F, G, j) + H + SS1 + W[j] >>> 0;
|
|
791
|
+
D = C;
|
|
792
|
+
C = rotl2(Bb, 9);
|
|
793
|
+
Bb = A;
|
|
794
|
+
A = TT1;
|
|
795
|
+
H = G;
|
|
796
|
+
G = rotl2(F, 19);
|
|
797
|
+
F = E;
|
|
798
|
+
E = P0(TT2);
|
|
799
|
+
}
|
|
800
|
+
return new Uint32Array([
|
|
801
|
+
V[0] ^ A,
|
|
802
|
+
V[1] ^ Bb,
|
|
803
|
+
V[2] ^ C,
|
|
804
|
+
V[3] ^ D,
|
|
805
|
+
V[4] ^ E,
|
|
806
|
+
V[5] ^ F,
|
|
807
|
+
V[6] ^ G,
|
|
808
|
+
V[7] ^ H
|
|
809
|
+
]);
|
|
810
|
+
}
|
|
811
|
+
function sm3Hash(data) {
|
|
812
|
+
const bitLen = BigInt(data.length) * 8n;
|
|
813
|
+
const padLen = (56 - (data.length + 1) % 64 + 64) % 64;
|
|
814
|
+
const padded = Buffer.alloc(data.length + 1 + padLen + 8);
|
|
815
|
+
data.copy(padded, 0);
|
|
816
|
+
padded[data.length] = 128;
|
|
817
|
+
for (let i = 0; i < 8; i++) {
|
|
818
|
+
padded[padded.length - 1 - i] = Number(bitLen >> BigInt(i * 8) & 0xffn);
|
|
819
|
+
}
|
|
820
|
+
const V = new Uint32Array(IV);
|
|
821
|
+
for (let off = 0; off < padded.length; off += 64) {
|
|
822
|
+
const B = new Uint32Array(16);
|
|
823
|
+
for (let i = 0; i < 16; i++) {
|
|
824
|
+
B[i] = padded.readUInt32BE(off + i * 4);
|
|
825
|
+
}
|
|
826
|
+
const Vn = CF(V, B);
|
|
827
|
+
for (let i = 0; i < 8; i++) V[i] = Vn[i];
|
|
828
|
+
}
|
|
829
|
+
const out = Buffer.alloc(32);
|
|
830
|
+
for (let i = 0; i < 8; i++) V[i] = V[i] >>> 0, out.writeUInt32BE(V[i], i * 4);
|
|
831
|
+
return out;
|
|
832
|
+
}
|
|
833
|
+
var META4, IV, sm3;
|
|
834
|
+
var init_sm3 = __esm({
|
|
835
|
+
"src/algorithms/digest/sm3.ts"() {
|
|
836
|
+
"use strict";
|
|
837
|
+
META4 = {
|
|
838
|
+
name: "sm3",
|
|
839
|
+
outputLength: 32,
|
|
840
|
+
keyed: false,
|
|
841
|
+
minKeyLength: 0
|
|
842
|
+
};
|
|
843
|
+
IV = new Uint32Array([
|
|
844
|
+
1937774191,
|
|
845
|
+
1226093241,
|
|
846
|
+
388252375,
|
|
847
|
+
3666478592,
|
|
848
|
+
2842636476,
|
|
849
|
+
372324522,
|
|
850
|
+
3817729613,
|
|
851
|
+
2969243214
|
|
852
|
+
]);
|
|
853
|
+
sm3 = {
|
|
854
|
+
name: "sm3",
|
|
855
|
+
meta: META4,
|
|
856
|
+
sign(data) {
|
|
857
|
+
const buf = typeof data === "string" ? Buffer.from(data, "utf-8") : data;
|
|
858
|
+
return sm3Hash(buf).toString("hex");
|
|
859
|
+
},
|
|
860
|
+
verify(sig, data) {
|
|
861
|
+
try {
|
|
862
|
+
return this.sign(data) === sig.toLowerCase();
|
|
863
|
+
} catch {
|
|
864
|
+
return false;
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
};
|
|
868
|
+
}
|
|
869
|
+
});
|
|
870
|
+
|
|
871
|
+
// src/algorithms/digest/index.ts
|
|
872
|
+
var init_digest = __esm({
|
|
873
|
+
"src/algorithms/digest/index.ts"() {
|
|
874
|
+
"use strict";
|
|
875
|
+
init_hmac();
|
|
876
|
+
init_hash();
|
|
877
|
+
init_sm3();
|
|
878
|
+
}
|
|
879
|
+
});
|
|
880
|
+
|
|
881
|
+
// src/algorithms/registry.ts
|
|
882
|
+
var registry_exports = {};
|
|
883
|
+
__export(registry_exports, {
|
|
884
|
+
cipherRegistry: () => cipherRegistry,
|
|
885
|
+
digestRegistry: () => digestRegistry,
|
|
886
|
+
getCipher: () => getCipher,
|
|
887
|
+
getDigest: () => getDigest,
|
|
888
|
+
parseKeyHex: () => parseKeyHex,
|
|
889
|
+
parseSecret: () => parseSecret
|
|
890
|
+
});
|
|
891
|
+
function getCipher(name) {
|
|
892
|
+
const c = cipherRegistry.get(name);
|
|
893
|
+
if (!c) {
|
|
894
|
+
throw new SecureError(1003 /* UNSUPPORTED_CIPHER */, `Unsupported cipher: ${name}`);
|
|
895
|
+
}
|
|
896
|
+
return c;
|
|
897
|
+
}
|
|
898
|
+
function getDigest(name) {
|
|
899
|
+
const d = digestRegistry.get(name);
|
|
900
|
+
if (!d) {
|
|
901
|
+
throw new SecureError(1004 /* UNSUPPORTED_DIGEST */, `Unsupported digest: ${name}`);
|
|
902
|
+
}
|
|
903
|
+
return d;
|
|
904
|
+
}
|
|
905
|
+
function parseKeyHex(hex, expectedLength = 32) {
|
|
906
|
+
if (!hex || hex.length !== expectedLength * 2) {
|
|
907
|
+
throw new SecureError(
|
|
908
|
+
1005 /* INVALID_KEY_LENGTH */,
|
|
909
|
+
`Key hex \u957F\u5EA6\u9700\u4E3A ${expectedLength * 2} \u5B57\u7B26(\u5BF9\u5E94 ${expectedLength} \u5B57\u8282)`
|
|
910
|
+
);
|
|
911
|
+
}
|
|
912
|
+
return Buffer.from(hex, "hex");
|
|
913
|
+
}
|
|
914
|
+
function parseSecret(secret, minLength = 32) {
|
|
915
|
+
if (!secret || secret.length < minLength) {
|
|
916
|
+
throw new SecureError(
|
|
917
|
+
1005 /* INVALID_KEY_LENGTH */,
|
|
918
|
+
`Secret \u957F\u5EA6\u9700\u81F3\u5C11 ${minLength} \u5B57\u7B26`
|
|
919
|
+
);
|
|
920
|
+
}
|
|
921
|
+
return Buffer.from(secret, "utf-8");
|
|
922
|
+
}
|
|
923
|
+
var cipherRegistry, digestRegistry;
|
|
924
|
+
var init_registry = __esm({
|
|
925
|
+
"src/algorithms/registry.ts"() {
|
|
926
|
+
"use strict";
|
|
927
|
+
init_errors();
|
|
928
|
+
init_cipher();
|
|
929
|
+
init_digest();
|
|
930
|
+
cipherRegistry = /* @__PURE__ */ new Map([
|
|
931
|
+
["aes-256-gcm", aesGcm],
|
|
932
|
+
["aes-256-cbc", aesCbc256],
|
|
933
|
+
["aes-128-cbc", aesCbc128],
|
|
934
|
+
["sm4-cbc", sm4Cbc],
|
|
935
|
+
["rsa-oaep-aes-256-gcm", rsaOaepAesGcm]
|
|
936
|
+
]);
|
|
937
|
+
digestRegistry = /* @__PURE__ */ new Map([
|
|
938
|
+
["hmac-sha256", hmacSha256],
|
|
939
|
+
["hmac-sha512", hmacSha512],
|
|
940
|
+
["md5", md5],
|
|
941
|
+
["sha256", sha256],
|
|
942
|
+
["sm3", sm3]
|
|
943
|
+
]);
|
|
944
|
+
}
|
|
945
|
+
});
|
|
946
|
+
|
|
947
|
+
// src/client/SecureClient.ts
|
|
948
|
+
init_registry();
|
|
949
|
+
|
|
950
|
+
// src/protocol/registry.ts
|
|
951
|
+
init_errors();
|
|
952
|
+
|
|
953
|
+
// src/protocol/custom/strategy.ts
|
|
954
|
+
init_registry();
|
|
955
|
+
init_errors();
|
|
956
|
+
import * as nodeCrypto7 from "crypto";
|
|
957
|
+
var PROTOCOL = "custom";
|
|
958
|
+
var customProtocol = {
|
|
959
|
+
kind: PROTOCOL,
|
|
960
|
+
async buildRequest(input, ctx) {
|
|
961
|
+
const cipherName = input.cipher || "aes-256-gcm";
|
|
962
|
+
const cipher = getCipher(cipherName);
|
|
963
|
+
const digest = getDigest(input.digest || "hmac-sha256");
|
|
964
|
+
const payload = JSON.stringify({
|
|
965
|
+
path: input.path,
|
|
966
|
+
method: input.method,
|
|
967
|
+
body: input.body,
|
|
968
|
+
query: input.query
|
|
969
|
+
});
|
|
970
|
+
const r = cipher.encrypt(Buffer.from(payload, "utf-8"), { key: ctx.encryptionKey });
|
|
971
|
+
const timestamp = Date.now();
|
|
972
|
+
const nonce = nodeCrypto7.randomUUID();
|
|
973
|
+
const signData = `${timestamp}.${nonce}.${r.data.toString("base64")}.${r.iv.toString("base64")}.${(r.tag ?? Buffer.alloc(0)).toString("base64")}`;
|
|
974
|
+
const signature = digest.sign(signData, ctx.hmacSecret);
|
|
975
|
+
const envelope = {
|
|
976
|
+
protocol: PROTOCOL,
|
|
977
|
+
app_key: ctx.appKey,
|
|
978
|
+
cipher: cipherName,
|
|
979
|
+
encryptedPayload: r.data.toString("base64"),
|
|
980
|
+
iv: r.iv.toString("base64"),
|
|
981
|
+
timestamp,
|
|
982
|
+
nonce,
|
|
983
|
+
signature
|
|
984
|
+
};
|
|
985
|
+
if (r.tag) envelope.authTag = r.tag.toString("base64");
|
|
986
|
+
if (r.encryptedKey) envelope.encryptedKey = r.encryptedKey.toString("base64");
|
|
987
|
+
return envelope;
|
|
988
|
+
},
|
|
989
|
+
async parseAndVerify(raw, ctx) {
|
|
990
|
+
const encryptedPayload = raw.encryptedPayload;
|
|
991
|
+
const iv = raw.iv;
|
|
992
|
+
const authTag = raw.authTag;
|
|
993
|
+
const signature = raw.signature;
|
|
994
|
+
const timestamp = raw.timestamp;
|
|
995
|
+
const nonce = raw.nonce;
|
|
996
|
+
const encryptedKey = raw.encryptedKey;
|
|
997
|
+
const cipherName = raw.cipher || "aes-256-gcm";
|
|
998
|
+
if (!encryptedPayload || !iv || !signature || !timestamp || !nonce) {
|
|
999
|
+
throw new SecureError(1301 /* INVALID_REQUEST */, "Custom \u534F\u8BAE\u5B57\u6BB5\u7F3A\u5931");
|
|
1000
|
+
}
|
|
1001
|
+
validateTimestamp(timestamp, ctx.requestWindowMs);
|
|
1002
|
+
await checkNonce(ctx.nonceStore, nonce, ctx.requestWindowMs);
|
|
1003
|
+
const digest = getDigest("hmac-sha256");
|
|
1004
|
+
const signData = `${timestamp}.${nonce}.${encryptedPayload}.${iv}.${authTag ?? ""}`;
|
|
1005
|
+
if (!digest.verify(signature, signData, ctx.app.appSecret)) {
|
|
1006
|
+
throw new SecureError(1101 /* SIGNATURE_MISMATCH */, "Custom \u534F\u8BAE\u7B7E\u540D\u9A8C\u8BC1\u5931\u8D25");
|
|
1007
|
+
}
|
|
1008
|
+
const cipher = getCipher(cipherName);
|
|
1009
|
+
const plain = cipher.decrypt(Buffer.from(encryptedPayload, "base64"), {
|
|
1010
|
+
key: ctx.encryptionKey,
|
|
1011
|
+
iv: Buffer.from(iv, "base64"),
|
|
1012
|
+
tag: authTag ? Buffer.from(authTag, "base64") : void 0
|
|
1013
|
+
});
|
|
1014
|
+
const json = JSON.parse(plain.toString("utf-8"));
|
|
1015
|
+
return {
|
|
1016
|
+
appKey: ctx.app.appKey,
|
|
1017
|
+
method: json.method,
|
|
1018
|
+
path: json.path,
|
|
1019
|
+
body: json.body,
|
|
1020
|
+
query: json.query,
|
|
1021
|
+
biz: json
|
|
1022
|
+
};
|
|
1023
|
+
},
|
|
1024
|
+
async buildResponse(biz, ctx) {
|
|
1025
|
+
const cipher = getCipher("aes-256-gcm");
|
|
1026
|
+
const digest = getDigest("hmac-sha256");
|
|
1027
|
+
const r = cipher.encrypt(Buffer.from(JSON.stringify(biz), "utf-8"), { key: ctx.encryptionKey });
|
|
1028
|
+
const timestamp = Date.now();
|
|
1029
|
+
const nonce = ctx.nonce || nodeCrypto7.randomUUID();
|
|
1030
|
+
const signData = `${timestamp}.${nonce}.${r.data.toString("base64")}.${r.iv.toString("base64")}.${(r.tag ?? Buffer.alloc(0)).toString("base64")}`;
|
|
1031
|
+
const signature = digest.sign(signData, ctx.app.appSecret);
|
|
1032
|
+
return {
|
|
1033
|
+
protocol: PROTOCOL,
|
|
1034
|
+
encryptedPayload: r.data.toString("base64"),
|
|
1035
|
+
iv: r.iv.toString("base64"),
|
|
1036
|
+
authTag: r.tag?.toString("base64"),
|
|
1037
|
+
signature,
|
|
1038
|
+
timestamp,
|
|
1039
|
+
nonce
|
|
1040
|
+
};
|
|
1041
|
+
}
|
|
1042
|
+
};
|
|
1043
|
+
function validateTimestamp(ts, windowMs) {
|
|
1044
|
+
const now = Date.now();
|
|
1045
|
+
if (ts > now + 5e3) throw new SecureError(1104 /* INVALID_TIMESTAMP */, "\u65F6\u95F4\u6233\u6765\u81EA\u672A\u6765");
|
|
1046
|
+
if (now - ts > windowMs) throw new SecureError(1102 /* TIMESTAMP_EXPIRED */, "\u8BF7\u6C42\u5DF2\u8FC7\u671F");
|
|
1047
|
+
}
|
|
1048
|
+
async function checkNonce(store, nonce, windowMs) {
|
|
1049
|
+
if (!store) return;
|
|
1050
|
+
const ttl = Math.ceil(windowMs * 2 / 1e3);
|
|
1051
|
+
const r = await store.set(`nonce:${nonce}`, "1", "EX", ttl, "NX");
|
|
1052
|
+
if (r === null) throw new SecureError(1103 /* NONCE_REUSED */, "nonce \u5DF2\u88AB\u4F7F\u7528");
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
// src/protocol/top/strategy.ts
|
|
1056
|
+
init_registry();
|
|
1057
|
+
init_errors();
|
|
1058
|
+
|
|
1059
|
+
// src/protocol/top/signer.ts
|
|
1060
|
+
var SYSTEM_PARAMS = /* @__PURE__ */ new Set([
|
|
1061
|
+
"protocol",
|
|
1062
|
+
"method",
|
|
1063
|
+
"app_key",
|
|
1064
|
+
"session",
|
|
1065
|
+
"timestamp",
|
|
1066
|
+
"v",
|
|
1067
|
+
"sign_method",
|
|
1068
|
+
"sign",
|
|
1069
|
+
"format",
|
|
1070
|
+
"simplify",
|
|
1071
|
+
"target_app_key",
|
|
1072
|
+
"session_auth_token",
|
|
1073
|
+
"cipher",
|
|
1074
|
+
"digest",
|
|
1075
|
+
"biz_content",
|
|
1076
|
+
// TOP 把整个业务内容 base64 后放在这个字段
|
|
1077
|
+
"encrypted_key"
|
|
1078
|
+
// 混合加密场景
|
|
1079
|
+
]);
|
|
1080
|
+
function buildSortedParams(input, includeSystem = false) {
|
|
1081
|
+
const filtered = {};
|
|
1082
|
+
for (const [k, v] of Object.entries(input)) {
|
|
1083
|
+
if (v === void 0 || v === null) continue;
|
|
1084
|
+
if (!includeSystem && SYSTEM_PARAMS.has(k)) continue;
|
|
1085
|
+
filtered[k] = v;
|
|
1086
|
+
}
|
|
1087
|
+
const keys = Object.keys(filtered).sort();
|
|
1088
|
+
return keys.map((k) => k + stringifyVal(filtered[k])).join("");
|
|
1089
|
+
}
|
|
1090
|
+
function stringifyVal(v) {
|
|
1091
|
+
if (v === null || v === void 0) return "";
|
|
1092
|
+
if (typeof v === "object") return JSON.stringify(v);
|
|
1093
|
+
return String(v);
|
|
1094
|
+
}
|
|
1095
|
+
function signTop(opts) {
|
|
1096
|
+
const bizStr = buildSortedParams(opts.params, false);
|
|
1097
|
+
const source = bizStr + opts.appSecret + (opts.cipherText ?? "");
|
|
1098
|
+
return opts.digest.sign(source, opts.appSecret);
|
|
1099
|
+
}
|
|
1100
|
+
function verifyTop(opts) {
|
|
1101
|
+
return opts.digest.verify(opts.signature, (() => {
|
|
1102
|
+
const bizStr = buildSortedParams(opts.params, false);
|
|
1103
|
+
return bizStr + opts.appSecret + (opts.cipherText ?? "");
|
|
1104
|
+
})(), opts.appSecret);
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
// src/protocol/top/strategy.ts
|
|
1108
|
+
var PROTOCOL2 = "top";
|
|
1109
|
+
var topProtocol = {
|
|
1110
|
+
kind: PROTOCOL2,
|
|
1111
|
+
async buildRequest(input, ctx) {
|
|
1112
|
+
const cipherName = input.cipher || "aes-256-gcm";
|
|
1113
|
+
const digestName = input.digest || "hmac-sha256";
|
|
1114
|
+
const cipher = getCipher(cipherName);
|
|
1115
|
+
const digest = getDigest(digestName);
|
|
1116
|
+
const bizJson = JSON.stringify(input.biz);
|
|
1117
|
+
const r = cipher.encrypt(Buffer.from(bizJson, "utf-8"), {
|
|
1118
|
+
key: ctx.encryptionKey,
|
|
1119
|
+
rsaPublicKeyPem: ctx.rsaPublicKeyPem
|
|
1120
|
+
});
|
|
1121
|
+
const cipherText = r.data.toString("base64");
|
|
1122
|
+
const iv = r.iv.toString("base64");
|
|
1123
|
+
const tag = r.tag?.toString("base64");
|
|
1124
|
+
const encryptedKey = r.encryptedKey?.toString("base64");
|
|
1125
|
+
const sysParams = {
|
|
1126
|
+
method: input.path,
|
|
1127
|
+
// TOP 风格:path 实际是 method 名
|
|
1128
|
+
app_key: ctx.appKey,
|
|
1129
|
+
timestamp: Date.now(),
|
|
1130
|
+
v: "2.0",
|
|
1131
|
+
sign_method: digestName,
|
|
1132
|
+
cipher: cipherName,
|
|
1133
|
+
format: "json"
|
|
1134
|
+
};
|
|
1135
|
+
if (input.session) sysParams.session = input.session;
|
|
1136
|
+
const paramsForSign = {
|
|
1137
|
+
...input.biz,
|
|
1138
|
+
method: sysParams.method,
|
|
1139
|
+
app_key: sysParams.appKey,
|
|
1140
|
+
timestamp: sysParams.timestamp,
|
|
1141
|
+
v: sysParams.v,
|
|
1142
|
+
sign_method: sysParams.sign_method,
|
|
1143
|
+
cipher: sysParams.cipher
|
|
1144
|
+
};
|
|
1145
|
+
if (input.session) paramsForSign.session = input.session;
|
|
1146
|
+
const signature = signTop({
|
|
1147
|
+
appSecret: ctx.appSecret,
|
|
1148
|
+
params: paramsForSign,
|
|
1149
|
+
cipherText,
|
|
1150
|
+
digest
|
|
1151
|
+
});
|
|
1152
|
+
const envelope = {
|
|
1153
|
+
protocol: PROTOCOL2,
|
|
1154
|
+
...sysParams,
|
|
1155
|
+
biz_content: cipherText,
|
|
1156
|
+
sign: signature
|
|
1157
|
+
};
|
|
1158
|
+
if (iv) envelope.iv = iv;
|
|
1159
|
+
if (tag) envelope.authTag = tag;
|
|
1160
|
+
if (encryptedKey) envelope.encrypted_key = encryptedKey;
|
|
1161
|
+
return envelope;
|
|
1162
|
+
},
|
|
1163
|
+
async parseAndVerify(raw, ctx) {
|
|
1164
|
+
const appKey = raw.app_key || ctx.app.appKey;
|
|
1165
|
+
if (!appKey) throw new SecureError(1203 /* MISSING_APP_KEY */, "TOP \u534F\u8BAE\u7F3A\u5C11 app_key");
|
|
1166
|
+
const method = raw.method;
|
|
1167
|
+
if (!method) throw new SecureError(1204 /* MISSING_METHOD */, "TOP \u534F\u8BAE\u7F3A\u5C11 method");
|
|
1168
|
+
const cipherName = raw.cipher || "aes-256-gcm";
|
|
1169
|
+
const digestName = raw.sign_method || "hmac-sha256";
|
|
1170
|
+
if (ctx.app.allowedCiphers?.length && !ctx.app.allowedCiphers.includes(cipherName)) {
|
|
1171
|
+
throw new SecureError(1003 /* UNSUPPORTED_CIPHER */, `app ${appKey} \u4E0D\u5141\u8BB8 cipher: ${cipherName}`);
|
|
1172
|
+
}
|
|
1173
|
+
if (ctx.app.allowedDigests?.length && !ctx.app.allowedDigests.includes(digestName)) {
|
|
1174
|
+
throw new SecureError(1105 /* SIGN_METHOD_NOT_ALLOWED */, `app ${appKey} \u4E0D\u5141\u8BB8 sign_method: ${digestName}`);
|
|
1175
|
+
}
|
|
1176
|
+
const timestamp = Number(raw.timestamp);
|
|
1177
|
+
validateTimestamp2(timestamp, ctx.requestWindowMs);
|
|
1178
|
+
await checkNonce2(ctx.nonceStore, raw.nonce || `top:${method}:${timestamp}`, ctx.requestWindowMs);
|
|
1179
|
+
const bizContent = raw.biz_content;
|
|
1180
|
+
if (!bizContent) throw new SecureError(1302 /* INVALID_PAYLOAD */, "TOP \u534F\u8BAE\u7F3A\u5C11 biz_content");
|
|
1181
|
+
const iv = raw.iv;
|
|
1182
|
+
const tag = raw.authTag;
|
|
1183
|
+
const encryptedKey = raw.encrypted_key;
|
|
1184
|
+
const cipher = getCipher(cipherName);
|
|
1185
|
+
const plain = cipher.decrypt(Buffer.from(bizContent, "base64"), {
|
|
1186
|
+
key: ctx.encryptionKey,
|
|
1187
|
+
iv: iv ? Buffer.from(iv, "base64") : Buffer.alloc(0),
|
|
1188
|
+
tag: tag ? Buffer.from(tag, "base64") : void 0,
|
|
1189
|
+
encryptedKey: encryptedKey ? Buffer.from(encryptedKey, "base64") : void 0,
|
|
1190
|
+
rsaPrivateKeyPem: ctx.rsaPrivateKeyPem
|
|
1191
|
+
});
|
|
1192
|
+
const biz = JSON.parse(plain.toString("utf-8"));
|
|
1193
|
+
const digest = getDigest(digestName);
|
|
1194
|
+
const paramsForSign = {
|
|
1195
|
+
...biz,
|
|
1196
|
+
method,
|
|
1197
|
+
app_key: appKey,
|
|
1198
|
+
timestamp,
|
|
1199
|
+
v: raw.v,
|
|
1200
|
+
sign_method: digestName,
|
|
1201
|
+
cipher: cipherName
|
|
1202
|
+
};
|
|
1203
|
+
if (raw.session) paramsForSign.session = raw.session;
|
|
1204
|
+
const ok = verifyTop({
|
|
1205
|
+
appSecret: ctx.app.appSecret,
|
|
1206
|
+
params: paramsForSign,
|
|
1207
|
+
cipherText: bizContent,
|
|
1208
|
+
digest,
|
|
1209
|
+
signature: raw.sign
|
|
1210
|
+
});
|
|
1211
|
+
if (!ok) throw new SecureError(1101 /* SIGNATURE_MISMATCH */, "TOP \u534F\u8BAE\u7B7E\u540D\u9A8C\u8BC1\u5931\u8D25");
|
|
1212
|
+
return {
|
|
1213
|
+
appKey,
|
|
1214
|
+
method,
|
|
1215
|
+
path: method,
|
|
1216
|
+
session: raw.session,
|
|
1217
|
+
biz
|
|
1218
|
+
};
|
|
1219
|
+
},
|
|
1220
|
+
async buildResponse(biz, ctx) {
|
|
1221
|
+
const cipherName = "aes-256-gcm";
|
|
1222
|
+
const digestName = "hmac-sha256";
|
|
1223
|
+
const cipher = getCipher(cipherName);
|
|
1224
|
+
const digest = getDigest(digestName);
|
|
1225
|
+
const r = cipher.encrypt(Buffer.from(JSON.stringify(biz), "utf-8"), { key: ctx.encryptionKey });
|
|
1226
|
+
const cipherText = r.data.toString("base64");
|
|
1227
|
+
const iv = r.iv.toString("base64");
|
|
1228
|
+
const tag = r.tag?.toString("base64");
|
|
1229
|
+
const timestamp = Date.now();
|
|
1230
|
+
const paramsForSign = {
|
|
1231
|
+
app_key: ctx.app.appKey,
|
|
1232
|
+
timestamp,
|
|
1233
|
+
sign_method: digestName,
|
|
1234
|
+
cipher: cipherName
|
|
1235
|
+
};
|
|
1236
|
+
const sign = signTop({ appSecret: ctx.app.appSecret, params: paramsForSign, cipherText, digest });
|
|
1237
|
+
return {
|
|
1238
|
+
protocol: PROTOCOL2,
|
|
1239
|
+
app_key: ctx.app.appKey,
|
|
1240
|
+
timestamp,
|
|
1241
|
+
v: "2.0",
|
|
1242
|
+
sign_method: digestName,
|
|
1243
|
+
cipher: cipherName,
|
|
1244
|
+
biz_content: cipherText,
|
|
1245
|
+
iv,
|
|
1246
|
+
authTag: tag,
|
|
1247
|
+
sign
|
|
1248
|
+
};
|
|
1249
|
+
}
|
|
1250
|
+
};
|
|
1251
|
+
function validateTimestamp2(ts, windowMs) {
|
|
1252
|
+
const now = Date.now();
|
|
1253
|
+
if (!ts) throw new SecureError(1104 /* INVALID_TIMESTAMP */, "\u65F6\u95F4\u6233\u65E0\u6548");
|
|
1254
|
+
if (ts > now + 5e3) throw new SecureError(1104 /* INVALID_TIMESTAMP */, "\u65F6\u95F4\u6233\u6765\u81EA\u672A\u6765");
|
|
1255
|
+
if (now - ts > windowMs) throw new SecureError(1102 /* TIMESTAMP_EXPIRED */, "\u8BF7\u6C42\u5DF2\u8FC7\u671F");
|
|
1256
|
+
}
|
|
1257
|
+
async function checkNonce2(store, nonce, windowMs) {
|
|
1258
|
+
if (!store) return;
|
|
1259
|
+
const ttl = Math.ceil(windowMs * 2 / 1e3);
|
|
1260
|
+
const r = await store.set(`nonce:${nonce}`, "1", "EX", ttl, "NX");
|
|
1261
|
+
if (r === null) throw new SecureError(1103 /* NONCE_REUSED */, "nonce \u5DF2\u88AB\u4F7F\u7528");
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
// src/protocol/registry.ts
|
|
1265
|
+
var protocolRegistry = /* @__PURE__ */ new Map([
|
|
1266
|
+
["custom", customProtocol],
|
|
1267
|
+
["top", topProtocol]
|
|
1268
|
+
]);
|
|
1269
|
+
function getProtocol(kind) {
|
|
1270
|
+
const p = protocolRegistry.get(kind);
|
|
1271
|
+
if (!p) throw new SecureError(1202 /* PROTOCOL_NOT_FOUND */, `Unsupported protocol: ${kind}`);
|
|
1272
|
+
return p;
|
|
1273
|
+
}
|
|
1274
|
+
function pickProtocol(envelope, defaultKind = "top") {
|
|
1275
|
+
const k = envelope.protocol || defaultKind;
|
|
1276
|
+
return getProtocol(k);
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
// src/client/SecureClient.ts
|
|
1280
|
+
init_errors();
|
|
1281
|
+
var SecureClient = class {
|
|
1282
|
+
constructor(config) {
|
|
1283
|
+
this.baseURL = config.baseURL.replace(/\/$/, "");
|
|
1284
|
+
this.encryptionKey = parseKeyHex(config.encryptionKey);
|
|
1285
|
+
this.hmacSecret = parseSecret(config.hmacSecret).toString("utf-8");
|
|
1286
|
+
this.appKey = config.appKey;
|
|
1287
|
+
this.defaultProtocol = config.protocol ?? "top";
|
|
1288
|
+
this.defaultCipher = config.cipher ?? "aes-256-gcm";
|
|
1289
|
+
this.defaultDigest = config.digest ?? "hmac-sha256";
|
|
1290
|
+
this.defaultHeaders = config.defaultHeaders ?? {};
|
|
1291
|
+
this.requestWindowMs = config.requestWindowMs ?? 3e5;
|
|
1292
|
+
this.rsaPublicKeyPem = config.rsaPublicKeyPem;
|
|
1293
|
+
this.fetchImpl = config.fetchImpl ?? (typeof fetch !== "undefined" ? fetch : (() => {
|
|
1294
|
+
throw new SecureError(1301 /* INVALID_REQUEST */, "fetch \u4E0D\u53EF\u7528,\u8BF7\u901A\u8FC7 fetchImpl \u6CE8\u5165");
|
|
1295
|
+
})());
|
|
1296
|
+
}
|
|
1297
|
+
/**
|
|
1298
|
+
* 发起加密请求并解密响应
|
|
1299
|
+
*/
|
|
1300
|
+
async request(method, path, options = {}) {
|
|
1301
|
+
const protocol = pickProtocol({ protocol: options.protocol ?? this.defaultProtocol });
|
|
1302
|
+
const envelope = await protocol.buildRequest(
|
|
1303
|
+
{
|
|
1304
|
+
method,
|
|
1305
|
+
path,
|
|
1306
|
+
biz: options.body ?? {},
|
|
1307
|
+
body: options.body,
|
|
1308
|
+
session: options.session,
|
|
1309
|
+
cipher: options.cipher ?? this.defaultCipher,
|
|
1310
|
+
digest: options.digest ?? this.defaultDigest
|
|
1311
|
+
},
|
|
1312
|
+
{
|
|
1313
|
+
appKey: this.appKey ?? "browser",
|
|
1314
|
+
appSecret: this.hmacSecret,
|
|
1315
|
+
encryptionKey: this.encryptionKey,
|
|
1316
|
+
hmacSecret: this.hmacSecret,
|
|
1317
|
+
rsaPublicKeyPem: this.rsaPublicKeyPem
|
|
1318
|
+
}
|
|
1319
|
+
);
|
|
1320
|
+
const url = this.baseURL + path;
|
|
1321
|
+
const resp = await this.fetchImpl(url, {
|
|
1322
|
+
method: "POST",
|
|
1323
|
+
// 加密请求统一用 POST 发送
|
|
1324
|
+
headers: {
|
|
1325
|
+
"Content-Type": "application/json",
|
|
1326
|
+
...this.defaultHeaders,
|
|
1327
|
+
...options.headers ?? {}
|
|
1328
|
+
},
|
|
1329
|
+
body: JSON.stringify(envelope),
|
|
1330
|
+
signal: options.signal
|
|
1331
|
+
});
|
|
1332
|
+
const respJson = await resp.json().catch(() => ({}));
|
|
1333
|
+
if (respJson && (respJson.biz_content || respJson.encryptedPayload)) {
|
|
1334
|
+
const respProtocol = pickProtocol(respJson, this.defaultProtocol);
|
|
1335
|
+
try {
|
|
1336
|
+
const plain = await this.decryptResponseOnly(respJson, respProtocol.kind);
|
|
1337
|
+
return plain;
|
|
1338
|
+
} catch (e) {
|
|
1339
|
+
if (respJson.biz_content) {
|
|
1340
|
+
const cipherName = respJson.cipher || this.defaultCipher || "aes-256-gcm";
|
|
1341
|
+
const { getCipher: getCipher2 } = await Promise.resolve().then(() => (init_registry(), registry_exports));
|
|
1342
|
+
const cipher = getCipher2(cipherName);
|
|
1343
|
+
const plain = cipher.decrypt(Buffer.from(respJson.biz_content, "base64"), {
|
|
1344
|
+
iv: Buffer.from(respJson.iv || "", "base64"),
|
|
1345
|
+
tag: respJson.authTag ? Buffer.from(respJson.authTag, "base64") : void 0,
|
|
1346
|
+
key: this.encryptionKey
|
|
1347
|
+
});
|
|
1348
|
+
return JSON.parse(plain.toString("utf-8"));
|
|
1349
|
+
}
|
|
1350
|
+
if (respJson.encryptedPayload) {
|
|
1351
|
+
const { getCipher: getCipher2 } = await Promise.resolve().then(() => (init_registry(), registry_exports));
|
|
1352
|
+
const cipher = getCipher2("aes-256-gcm");
|
|
1353
|
+
const plain = cipher.decrypt(Buffer.from(respJson.encryptedPayload, "base64"), {
|
|
1354
|
+
iv: Buffer.from(respJson.iv, "base64"),
|
|
1355
|
+
tag: respJson.authTag ? Buffer.from(respJson.authTag, "base64") : void 0,
|
|
1356
|
+
key: this.encryptionKey
|
|
1357
|
+
});
|
|
1358
|
+
return JSON.parse(plain.toString("utf-8"));
|
|
1359
|
+
}
|
|
1360
|
+
throw e;
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
return respJson;
|
|
1364
|
+
}
|
|
1365
|
+
async decryptResponseOnly(envelope, protocolKind) {
|
|
1366
|
+
if (envelope.biz_content) {
|
|
1367
|
+
const { getCipher: getCipher2 } = await Promise.resolve().then(() => (init_registry(), registry_exports));
|
|
1368
|
+
const cipherName = envelope.cipher || this.defaultCipher || "aes-256-gcm";
|
|
1369
|
+
const cipher = getCipher2(cipherName);
|
|
1370
|
+
return JSON.parse(cipher.decrypt(Buffer.from(envelope.biz_content, "base64"), {
|
|
1371
|
+
key: this.encryptionKey,
|
|
1372
|
+
iv: Buffer.from(envelope.iv || "", "base64"),
|
|
1373
|
+
tag: envelope.authTag ? Buffer.from(envelope.authTag, "base64") : void 0
|
|
1374
|
+
}).toString("utf-8"));
|
|
1375
|
+
}
|
|
1376
|
+
if (envelope.encryptedPayload) {
|
|
1377
|
+
const { getCipher: getCipher2 } = await Promise.resolve().then(() => (init_registry(), registry_exports));
|
|
1378
|
+
const cipher = getCipher2("aes-256-gcm");
|
|
1379
|
+
return JSON.parse(cipher.decrypt(Buffer.from(envelope.encryptedPayload, "base64"), {
|
|
1380
|
+
key: this.encryptionKey,
|
|
1381
|
+
iv: Buffer.from(envelope.iv, "base64"),
|
|
1382
|
+
tag: envelope.authTag ? Buffer.from(envelope.authTag, "base64") : void 0
|
|
1383
|
+
}).toString("utf-8"));
|
|
1384
|
+
}
|
|
1385
|
+
return envelope;
|
|
1386
|
+
}
|
|
1387
|
+
get(path, options) {
|
|
1388
|
+
return this.request("GET", path, options);
|
|
1389
|
+
}
|
|
1390
|
+
post(path, body, options) {
|
|
1391
|
+
return this.request("POST", path, { ...options ?? {}, body });
|
|
1392
|
+
}
|
|
1393
|
+
put(path, body, options) {
|
|
1394
|
+
return this.request("PUT", path, { ...options ?? {}, body });
|
|
1395
|
+
}
|
|
1396
|
+
delete(path, options) {
|
|
1397
|
+
return this.request("DELETE", path, options);
|
|
1398
|
+
}
|
|
1399
|
+
patch(path, body, options) {
|
|
1400
|
+
return this.request("PATCH", path, { ...options ?? {}, body });
|
|
1401
|
+
}
|
|
1402
|
+
};
|
|
1403
|
+
export {
|
|
1404
|
+
SecureClient
|
|
1405
|
+
};
|
|
1406
|
+
//# sourceMappingURL=client.mjs.map
|