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