@quantabit/security-sdk 1.0.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.
@@ -0,0 +1,1444 @@
1
+ import React, { useState, useEffect, useCallback, useContext, createContext } from 'react';
2
+ import { BaseApiClient, logger, consentManager } from '@quantabit/sdk-config';
3
+
4
+ /**
5
+ * Security SDK - API 客户端
6
+ * 安全系统后端接口封装
7
+ *
8
+ * 使用 BaseApiClient 基类简化代码
9
+ */
10
+
11
+
12
+ /**
13
+ * 安全 API 客户端
14
+ */
15
+ class SecurityApiClient extends BaseApiClient {
16
+ constructor(config = {}) {
17
+ super('/security', config);
18
+ }
19
+
20
+ // ============ 密码管理 ============
21
+
22
+ /**
23
+ * 修改密码
24
+ * @param {string} oldPassword - 旧密码
25
+ * @param {string} newPassword - 新密码
26
+ */
27
+ async changePassword(oldPassword, newPassword) {
28
+ return this.post('/password/change', {
29
+ old_password: oldPassword,
30
+ new_password: newPassword
31
+ });
32
+ }
33
+
34
+ /**
35
+ * 重置密码
36
+ * @param {string} token - 重置 Token
37
+ * @param {string} newPassword - 新密码
38
+ */
39
+ async resetPassword(token, newPassword) {
40
+ return this.post('/password/reset', {
41
+ token,
42
+ new_password: newPassword
43
+ });
44
+ }
45
+
46
+ /**
47
+ * 发送重置密码邮件
48
+ * @param {string} email - 邮箱
49
+ */
50
+ async sendPasswordResetEmail(email) {
51
+ return this.post('/password/forgot', {
52
+ email
53
+ });
54
+ }
55
+
56
+ /**
57
+ * 验证密码强度
58
+ * @param {string} password - 密码
59
+ */
60
+ async checkPasswordStrength(password) {
61
+ return this.post('/password/strength', {
62
+ password
63
+ });
64
+ }
65
+
66
+ // ============ 双因素认证 ============
67
+
68
+ /**
69
+ * 获取 2FA 状态
70
+ */
71
+ async get2FAStatus() {
72
+ return this.get('/2fa/status');
73
+ }
74
+
75
+ /**
76
+ * 启用 2FA
77
+ * @param {string} type - 类型(totp, sms, email)
78
+ */
79
+ async enable2FA(type) {
80
+ return this.post('/2fa/enable', {
81
+ type
82
+ });
83
+ }
84
+
85
+ /**
86
+ * 验证并激活 2FA
87
+ * @param {string} code - 验证码
88
+ */
89
+ async verify2FA(code) {
90
+ return this.post('/2fa/verify', {
91
+ code
92
+ });
93
+ }
94
+
95
+ /**
96
+ * 禁用 2FA
97
+ * @param {string} code - 验证码
98
+ */
99
+ async disable2FA(code) {
100
+ return this.post('/2fa/disable', {
101
+ code
102
+ });
103
+ }
104
+
105
+ /**
106
+ * 获取备份码
107
+ */
108
+ async getBackupCodes() {
109
+ return this.get('/2fa/backup-codes');
110
+ }
111
+
112
+ /**
113
+ * 重新生成备份码
114
+ */
115
+ async regenerateBackupCodes() {
116
+ return this.post('/2fa/backup-codes/regenerate');
117
+ }
118
+
119
+ // ============ 登录安全 ============
120
+
121
+ /**
122
+ * 获取登录历史
123
+ * @param {Object} params - 查询参数
124
+ */
125
+ async getLoginHistory(params = {}) {
126
+ return this.get('/login/history', params);
127
+ }
128
+
129
+ /**
130
+ * 获取活动设备
131
+ */
132
+ async getActiveDevices() {
133
+ return this.get('/devices');
134
+ }
135
+
136
+ /**
137
+ * 登出设备
138
+ * @param {string} deviceId - 设备 ID
139
+ */
140
+ async logoutDevice(deviceId) {
141
+ return this.post(`/devices/${deviceId}/logout`);
142
+ }
143
+
144
+ /**
145
+ * 登出所有设备
146
+ */
147
+ async logoutAllDevices() {
148
+ return this.post('/devices/logout-all');
149
+ }
150
+
151
+ /**
152
+ * 信任设备
153
+ * @param {string} deviceId - 设备 ID
154
+ */
155
+ async trustDevice(deviceId) {
156
+ return this.post(`/devices/${deviceId}/trust`);
157
+ }
158
+
159
+ // ============ 安全设置 ============
160
+
161
+ /**
162
+ * 获取安全设置
163
+ */
164
+ async getSecuritySettings() {
165
+ return this.get('/settings');
166
+ }
167
+
168
+ /**
169
+ * 更新安全设置
170
+ * @param {Object} settings - 设置数据
171
+ */
172
+ async updateSecuritySettings(settings) {
173
+ return this.put('/settings', settings);
174
+ }
175
+
176
+ /**
177
+ * 获取登录通知设置
178
+ */
179
+ async getLoginNotificationSettings() {
180
+ return this.get('/settings/login-notification');
181
+ }
182
+
183
+ /**
184
+ * 更新登录通知设置
185
+ * @param {Object} settings - 设置数据
186
+ */
187
+ async updateLoginNotificationSettings(settings) {
188
+ return this.put('/settings/login-notification', settings);
189
+ }
190
+
191
+ // ============ 安全检查 ============
192
+
193
+ /**
194
+ * 安全状态检查
195
+ */
196
+ async getSecurityStatus() {
197
+ return this.get('/status');
198
+ }
199
+
200
+ /**
201
+ * 获取安全建议
202
+ */
203
+ async getSecurityRecommendations() {
204
+ return this.get('/recommendations');
205
+ }
206
+
207
+ /**
208
+ * 获取安全事件
209
+ * @param {Object} params - 查询参数
210
+ */
211
+ async getSecurityEvents(params = {}) {
212
+ return this.get('/events', params);
213
+ }
214
+
215
+ // ============ 恢复选项 ============
216
+
217
+ /**
218
+ * 获取恢复选项
219
+ */
220
+ async getRecoveryOptions() {
221
+ return this.get('/recovery/options');
222
+ }
223
+
224
+ /**
225
+ * 设置恢复邮箱
226
+ * @param {string} email - 恢复邮箱
227
+ */
228
+ async setRecoveryEmail(email) {
229
+ return this.post('/recovery/email', {
230
+ email
231
+ });
232
+ }
233
+
234
+ /**
235
+ * 设置恢复手机
236
+ * @param {string} phone - 恢复手机
237
+ */
238
+ async setRecoveryPhone(phone) {
239
+ return this.post('/recovery/phone', {
240
+ phone
241
+ });
242
+ }
243
+
244
+ /**
245
+ * 设置安全问题
246
+ * @param {Object[]} questions - 安全问题列表
247
+ */
248
+ async setSecurityQuestions(questions) {
249
+ return this.post('/recovery/questions', {
250
+ questions
251
+ });
252
+ }
253
+ }
254
+
255
+ // 创建默认实例
256
+ const securityApi = new SecurityApiClient();
257
+
258
+ /**
259
+ * Security SDK - 国际化 i18n
260
+ */
261
+
262
+ const SUPPORTED_LANGUAGES = ['en', 'zh', 'ja', 'ko'];
263
+ const messages = {
264
+ zh: {
265
+ loading: '加载中...',
266
+ security: '安全中心',
267
+ riskControl: '风控中心',
268
+ // 风险等级
269
+ riskLow: '低风险',
270
+ riskMedium: '中风险',
271
+ riskHigh: '高风险',
272
+ riskCritical: '极高风险',
273
+ // 风险类型
274
+ riskLogin: '登录异常',
275
+ riskTransaction: '交易风险',
276
+ riskAccount: '账户安全',
277
+ riskDevice: '设备异常',
278
+ riskBehavior: '行为异常',
279
+ riskContent: '内容违规',
280
+ // 状态
281
+ statusNormal: '正常',
282
+ statusWarning: '警告',
283
+ statusBlocked: '已拦截',
284
+ statusReview: '人工审核',
285
+ // 设备指纹
286
+ deviceFingerprint: '设备指纹',
287
+ deviceInfo: '设备信息',
288
+ trustedDevices: '信任设备',
289
+ currentDevice: '当前设备',
290
+ newDevice: '新设备',
291
+ // 操作
292
+ verify: '验证',
293
+ block: '拦截',
294
+ allow: '放行',
295
+ review: '审核',
296
+ appeal: '申诉',
297
+ // 安全设置
298
+ securitySettings: '安全设置',
299
+ loginProtection: '登录保护',
300
+ paymentProtection: '支付保护',
301
+ antiTheft: '防盗保护',
302
+ // 验证
303
+ captcha: '验证码',
304
+ smsCode: 'SMS验证',
305
+ emailCode: '邮箱验证',
306
+ twoFactor: '两步验证',
307
+ // 提示
308
+ riskDetected: '检测到风险',
309
+ pleaseVerify: '请完成验证',
310
+ verifySuccess: '验证成功',
311
+ blocked: '操作已拦截'
312
+ },
313
+ en: {
314
+ loading: 'Loading...',
315
+ security: 'Security Center',
316
+ riskControl: 'Risk Control',
317
+ riskLow: 'Low Risk',
318
+ riskMedium: 'Medium Risk',
319
+ riskHigh: 'High Risk',
320
+ riskCritical: 'Critical',
321
+ riskLogin: 'Login Anomaly',
322
+ riskTransaction: 'Transaction Risk',
323
+ riskAccount: 'Account Security',
324
+ riskDevice: 'Device Anomaly',
325
+ riskBehavior: 'Behavior Anomaly',
326
+ riskContent: 'Content Violation',
327
+ statusNormal: 'Normal',
328
+ statusWarning: 'Warning',
329
+ statusBlocked: 'Blocked',
330
+ statusReview: 'Under Review',
331
+ deviceFingerprint: 'Device Fingerprint',
332
+ deviceInfo: 'Device Info',
333
+ trustedDevices: 'Trusted Devices',
334
+ currentDevice: 'Current Device',
335
+ newDevice: 'New Device',
336
+ verify: 'Verify',
337
+ block: 'Block',
338
+ allow: 'Allow',
339
+ review: 'Review',
340
+ appeal: 'Appeal',
341
+ securitySettings: 'Security Settings',
342
+ loginProtection: 'Login Protection',
343
+ paymentProtection: 'Payment Protection',
344
+ antiTheft: 'Anti-Theft',
345
+ captcha: 'CAPTCHA',
346
+ smsCode: 'SMS Code',
347
+ emailCode: 'Email Code',
348
+ twoFactor: '2FA',
349
+ riskDetected: 'Risk Detected',
350
+ pleaseVerify: 'Please verify',
351
+ verifySuccess: 'Verified',
352
+ blocked: 'Action blocked'
353
+ },
354
+ ja: {
355
+ loading: '読み込み中...',
356
+ security: 'セキュリティセンター',
357
+ riskControl: 'リスクコントロール',
358
+ riskLow: '低リスク',
359
+ riskMedium: '中リスク',
360
+ riskHigh: '高リスク',
361
+ riskCritical: '重大',
362
+ riskLogin: 'ログイン異常',
363
+ riskTransaction: '取引リスク',
364
+ riskAccount: 'アカウントセキュリティ',
365
+ riskDevice: 'デバイス異常',
366
+ riskBehavior: '動作異常',
367
+ riskContent: 'コンテンツ違反',
368
+ statusNormal: '正常',
369
+ statusWarning: '警告',
370
+ statusBlocked: 'ブロック済み',
371
+ statusReview: '審査中',
372
+ deviceFingerprint: 'デバイス指紋',
373
+ deviceInfo: 'デバイス情報',
374
+ trustedDevices: '信頼済みデバイス',
375
+ currentDevice: '現在のデバイス',
376
+ newDevice: '新しいデバイス',
377
+ verify: '確認',
378
+ block: 'ブロック',
379
+ allow: '許可',
380
+ review: '審査',
381
+ appeal: '異議申し立て',
382
+ securitySettings: 'セキュリティ設定',
383
+ loginProtection: 'ログイン保護',
384
+ paymentProtection: '支払い保護',
385
+ antiTheft: '盗難防止',
386
+ captcha: 'キャプチャ',
387
+ smsCode: 'SMSコード',
388
+ emailCode: 'メールコード',
389
+ twoFactor: '2段階認証',
390
+ riskDetected: 'リスクが検出されました',
391
+ pleaseVerify: '確認してください',
392
+ verifySuccess: '確認成功',
393
+ blocked: 'アクションがブロックされました'
394
+ },
395
+ ko: {
396
+ loading: '로딩 중...',
397
+ security: '보안 센터',
398
+ riskControl: '위험 관리',
399
+ riskLow: '낮은 위험',
400
+ riskMedium: '중간 위험',
401
+ riskHigh: '높은 위험',
402
+ riskCritical: '치명적',
403
+ riskLogin: '로그인 이상',
404
+ riskTransaction: '거래 위험',
405
+ riskAccount: '계정 보안',
406
+ riskDevice: '기기 이상',
407
+ riskBehavior: '동작 이상',
408
+ riskContent: '콘텐츠 위반',
409
+ statusNormal: '정상',
410
+ statusWarning: '경고',
411
+ statusBlocked: '차단됨',
412
+ statusReview: '검토 중',
413
+ deviceFingerprint: '기기 지문',
414
+ deviceInfo: '기기 정보',
415
+ trustedDevices: '신뢰할 수 있는 기기',
416
+ currentDevice: '현재 기기',
417
+ newDevice: '새 기기',
418
+ verify: '확인',
419
+ block: '차단',
420
+ allow: '허용',
421
+ review: '검토',
422
+ appeal: '이의 제기',
423
+ securitySettings: '보안 설정',
424
+ loginProtection: '로그인 보호',
425
+ paymentProtection: '결제 보호',
426
+ antiTheft: '도난 방지',
427
+ captcha: '보안 문자',
428
+ smsCode: 'SMS 코드',
429
+ emailCode: '이메일 코드',
430
+ twoFactor: '2단계 인증',
431
+ riskDetected: '위험 감지됨',
432
+ pleaseVerify: '확인해주세요',
433
+ verifySuccess: '확인 성공',
434
+ blocked: '작업이 차단되었습니다'
435
+ }
436
+ };
437
+ let currentLanguage = 'zh';
438
+ function setLanguage(lang) {
439
+ if (SUPPORTED_LANGUAGES.includes(lang)) currentLanguage = lang;
440
+ }
441
+ function getLanguage() {
442
+ return currentLanguage;
443
+ }
444
+ function t(key, params) {
445
+ const msgs = messages[getLanguage()] || messages.zh;
446
+ let text = msgs[key] || key;
447
+ if (params) {
448
+ Object.keys(params).forEach(k => {
449
+ text = text.replace(new RegExp(`\\{${k}\\}`, 'g'), params[k]);
450
+ });
451
+ }
452
+ return text;
453
+ }
454
+
455
+ /**
456
+ * Security SDK - 设备指纹 (隐私合规增强版)
457
+ *
458
+ * ⚠️ 设备指纹属于 essential 级别(安全必需),但收集深度据 consent 策略分级:
459
+ * - essential: 仅收集基础安全信息(UA, 屏幕, 时区)
460
+ * - functional: 收集增强信息(Canvas, WebGL, 插件等)
461
+ * - analytics: 完整指纹信息
462
+ *
463
+ * 遵循 DNT (Do Not Track) 信号
464
+ */
465
+
466
+ const SDK_NAME = 'security-sdk';
467
+
468
+ /**
469
+ * 设备指纹生成器
470
+ */
471
+ class DeviceFingerprintClass {
472
+ constructor() {
473
+ this.cachedFingerprint = null;
474
+ this.components = {};
475
+ }
476
+
477
+ /**
478
+ * 获取设备指纹
479
+ * @param {object} options - 选项
480
+ * @param {boolean} options.respectDNT - 是否尊重 DNT 信号 (默认 true)
481
+ * @param {boolean} options.minimal - 是否仅收集最小信息集 (默认 false)
482
+ */
483
+ async getFingerprint(options = {}) {
484
+ const {
485
+ respectDNT = true,
486
+ minimal = false
487
+ } = options;
488
+ if (this.cachedFingerprint) {
489
+ return this.cachedFingerprint;
490
+ }
491
+
492
+ // 检查 DNT (Do Not Track) 信号
493
+ if (respectDNT && typeof navigator !== 'undefined' && navigator.doNotTrack === '1') {
494
+ logger.debug(`[${SDK_NAME}] DNT 信号已检测,使用最小化指纹`);
495
+ await this.collectMinimalComponents();
496
+ } else if (minimal) {
497
+ await this.collectMinimalComponents();
498
+ } else {
499
+ await this.collectComponents();
500
+ }
501
+ const fingerprintData = JSON.stringify(this.components);
502
+ const hash = await this.hash(fingerprintData);
503
+ this.cachedFingerprint = hash;
504
+ return hash;
505
+ }
506
+
507
+ /**
508
+ * 获取指纹组件
509
+ */
510
+ getComponents() {
511
+ return this.components;
512
+ }
513
+
514
+ /**
515
+ * 收集最小化组件 — essential 级别
516
+ * 仅包含安全验证所必需的基础信息,不含高侵入性指纹
517
+ */
518
+ async collectMinimalComponents() {
519
+ if (typeof window === 'undefined') {
520
+ this.components = {
521
+ server: true
522
+ };
523
+ return;
524
+ }
525
+ this.components = {
526
+ // 基础安全信息
527
+ screenWidth: screen.width,
528
+ screenHeight: screen.height,
529
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
530
+ timezoneOffset: new Date().getTimezoneOffset(),
531
+ language: navigator.language,
532
+ platform: navigator.platform
533
+ // 不收集 Canvas、WebGL、插件等高侵入性指纹
534
+ };
535
+ }
536
+
537
+ /**
538
+ * 收集完整设备信息组件
539
+ * 据 ConsentManager 状态分级收集
540
+ */
541
+ async collectComponents() {
542
+ if (typeof window === 'undefined') {
543
+ this.components = {
544
+ server: true
545
+ };
546
+ return;
547
+ }
548
+ consentManager.init();
549
+ const hasFunctional = consentManager.hasConsent('functional');
550
+ const hasAnalytics = consentManager.hasConsent('analytics');
551
+
552
+ // === essential 层 — 始终收集 ===
553
+ this.components = {
554
+ language: navigator.language,
555
+ platform: navigator.platform,
556
+ screenWidth: screen.width,
557
+ screenHeight: screen.height,
558
+ screenDepth: screen.colorDepth,
559
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
560
+ timezoneOffset: new Date().getTimezoneOffset(),
561
+ doNotTrack: navigator.doNotTrack
562
+ };
563
+
564
+ // === functional 层 — 需要 functional 同意 ===
565
+ if (hasFunctional) {
566
+ Object.assign(this.components, {
567
+ userAgent: navigator.userAgent,
568
+ languages: navigator.languages?.join(','),
569
+ screenPixelRatio: window.devicePixelRatio,
570
+ hardwareConcurrency: navigator.hardwareConcurrency,
571
+ deviceMemory: navigator.deviceMemory,
572
+ touchSupport: this.getTouchSupport(),
573
+ localStorage: this.hasLocalStorage(),
574
+ sessionStorage: this.hasSessionStorage(),
575
+ indexedDB: this.hasIndexedDB()
576
+ });
577
+ }
578
+
579
+ // === analytics 层 — 需要 analytics 同意 ===
580
+ if (hasAnalytics) {
581
+ const canvas = await this.getCanvasFingerprint();
582
+ const webgl = this.getWebGLInfo();
583
+ const plugins = this.getPlugins();
584
+ Object.assign(this.components, {
585
+ canvas,
586
+ webgl,
587
+ plugins
588
+ });
589
+ }
590
+ }
591
+
592
+ /**
593
+ * Canvas指纹
594
+ */
595
+ async getCanvasFingerprint() {
596
+ try {
597
+ const canvas = document.createElement('canvas');
598
+ const ctx = canvas.getContext('2d');
599
+ if (!ctx) return null;
600
+ canvas.width = 200;
601
+ canvas.height = 50;
602
+ ctx.textBaseline = 'alphabetic';
603
+ ctx.fillStyle = '#f60';
604
+ ctx.fillRect(125, 1, 62, 20);
605
+ ctx.fillStyle = '#069';
606
+ ctx.font = '11pt Arial';
607
+ ctx.fillText('QuantaBit <canvas> 1.0', 2, 15);
608
+ ctx.fillStyle = 'rgba(102, 204, 0, 0.7)';
609
+ ctx.font = '18pt Arial';
610
+ ctx.fillText('QuantaBit <canvas> 1.0', 4, 45);
611
+ const dataUrl = canvas.toDataURL();
612
+ return await this.hash(dataUrl);
613
+ } catch (e) {
614
+ return null;
615
+ }
616
+ }
617
+
618
+ /**
619
+ * WebGL信息
620
+ */
621
+ getWebGLInfo() {
622
+ try {
623
+ const canvas = document.createElement('canvas');
624
+ const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
625
+ if (!gl) return null;
626
+ const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
627
+ return {
628
+ vendor: gl.getParameter(gl.VENDOR),
629
+ renderer: debugInfo ? gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL) : null,
630
+ version: gl.getParameter(gl.VERSION)
631
+ };
632
+ } catch (e) {
633
+ return null;
634
+ }
635
+ }
636
+
637
+ /**
638
+ * 触摸支持
639
+ */
640
+ getTouchSupport() {
641
+ return {
642
+ maxTouchPoints: navigator.maxTouchPoints || 0,
643
+ touchEvent: 'ontouchstart' in window,
644
+ touchPoints: navigator.msMaxTouchPoints || 0
645
+ };
646
+ }
647
+
648
+ /**
649
+ * 插件列表
650
+ */
651
+ getPlugins() {
652
+ const plugins = [];
653
+ for (let i = 0; i < navigator.plugins.length; i++) {
654
+ plugins.push({
655
+ name: navigator.plugins[i].name,
656
+ filename: navigator.plugins[i].filename
657
+ });
658
+ }
659
+ return plugins.slice(0, 10);
660
+ }
661
+
662
+ /**
663
+ * 存储检测
664
+ */
665
+ hasLocalStorage() {
666
+ try {
667
+ localStorage.setItem('test', 'test');
668
+ localStorage.removeItem('test');
669
+ return true;
670
+ } catch (e) {
671
+ return false;
672
+ }
673
+ }
674
+ hasSessionStorage() {
675
+ try {
676
+ sessionStorage.setItem('test', 'test');
677
+ sessionStorage.removeItem('test');
678
+ return true;
679
+ } catch (e) {
680
+ return false;
681
+ }
682
+ }
683
+ hasIndexedDB() {
684
+ return !!window.indexedDB;
685
+ }
686
+
687
+ /**
688
+ * 哈希函数
689
+ */
690
+ async hash(str) {
691
+ const encoder = new TextEncoder();
692
+ const data = encoder.encode(str);
693
+ const hashBuffer = await crypto.subtle.digest('SHA-256', data);
694
+ return Array.from(new Uint8Array(hashBuffer)).map(b => b.toString(16).padStart(2, '0')).join('');
695
+ }
696
+
697
+ /**
698
+ * 清除缓存的指纹
699
+ */
700
+ clearCache() {
701
+ this.cachedFingerprint = null;
702
+ this.components = {};
703
+ }
704
+
705
+ /**
706
+ * 获取隐私说明 — 当前指纹收集的数据项说明
707
+ * 可用于向用户展示透明度信息
708
+ */
709
+ getPrivacyDisclosure() {
710
+ consentManager.init();
711
+ const levels = [];
712
+ levels.push({
713
+ level: 'essential',
714
+ items: ['Screen resolution', 'Timezone', 'Language', 'Platform'],
715
+ description: 'Basic device information for security verification.',
716
+ descriptionZh: '用于安全验证的基础设备信息。'
717
+ });
718
+ if (consentManager.hasConsent('functional')) {
719
+ levels.push({
720
+ level: 'functional',
721
+ items: ['User agent', 'Hardware specs', 'Touch support', 'Storage availability'],
722
+ description: 'Enhanced device information for better experience.',
723
+ descriptionZh: '增强型设备信息,用于改善使用体验。'
724
+ });
725
+ }
726
+ if (consentManager.hasConsent('analytics')) {
727
+ levels.push({
728
+ level: 'analytics',
729
+ items: ['Canvas fingerprint', 'WebGL renderer', 'Browser plugins'],
730
+ description: 'Advanced fingerprinting for fraud prevention.',
731
+ descriptionZh: '高级指纹信息,用于反欺诈保护。'
732
+ });
733
+ }
734
+ return levels;
735
+ }
736
+ }
737
+ const deviceFingerprint = new DeviceFingerprintClass();
738
+
739
+ /**
740
+ * 便捷函数 — 获取设备指纹(遵循隐私设置)
741
+ */
742
+ async function getDeviceFingerprint(options = {}) {
743
+ return deviceFingerprint.getFingerprint(options);
744
+ }
745
+
746
+ /**
747
+ * Security SDK - Context Provider
748
+ */
749
+
750
+ const SecurityContext = /*#__PURE__*/createContext(null);
751
+ function SecurityProvider({
752
+ children,
753
+ apiUrl,
754
+ token,
755
+ language = 'zh',
756
+ onRiskDetected,
757
+ onBlocked,
758
+ onError
759
+ }) {
760
+ const [riskLevel, setRiskLevel] = useState('low');
761
+ const [deviceId, setDeviceId] = useState(null);
762
+ const [trustedDevices, setTrustedDevices] = useState([]);
763
+ const [riskEvents, setRiskEvents] = useState([]);
764
+ const [verificationRequired, setVerificationRequired] = useState(null);
765
+ const [loading, setLoading] = useState(false);
766
+ const [error, setError] = useState(null);
767
+ useEffect(() => {
768
+ if (apiUrl) securityApi.setBaseUrl(apiUrl);
769
+ if (token) securityApi.setToken(token);
770
+ if (language) setLanguage(language);
771
+
772
+ // 初始化设备指纹
773
+ initDeviceFingerprint();
774
+ }, [apiUrl, token, language]);
775
+ const initDeviceFingerprint = async () => {
776
+ const fp = await getDeviceFingerprint();
777
+ setDeviceId(fp);
778
+ };
779
+ const handleError = useCallback(err => {
780
+ setError(err.message);
781
+ onError?.(err);
782
+ }, [onError]);
783
+
784
+ // 风险检测
785
+ const checkRisk = useCallback(async (action, data = {}) => {
786
+ setLoading(true);
787
+ try {
788
+ const result = await securityApi.checkRisk({
789
+ action,
790
+ device_id: deviceId,
791
+ ...data
792
+ });
793
+ setRiskLevel(result.risk_level || 'low');
794
+ if (result.blocked) {
795
+ onBlocked?.(result);
796
+ return {
797
+ allowed: false,
798
+ reason: result.reason
799
+ };
800
+ }
801
+ if (result.verification_required) {
802
+ setVerificationRequired(result.verification_type);
803
+ onRiskDetected?.(result);
804
+ return {
805
+ allowed: false,
806
+ verification: result.verification_type
807
+ };
808
+ }
809
+ return {
810
+ allowed: true
811
+ };
812
+ } catch (err) {
813
+ handleError(err);
814
+ return {
815
+ allowed: true
816
+ }; // 风控服务异常时默认放行
817
+ } finally {
818
+ setLoading(false);
819
+ }
820
+ }, [deviceId, handleError, onBlocked, onRiskDetected]);
821
+
822
+ // 完成验证
823
+ const completeVerification = useCallback(async (type, code) => {
824
+ setLoading(true);
825
+ try {
826
+ const result = await securityApi.verify({
827
+ type,
828
+ code,
829
+ device_id: deviceId
830
+ });
831
+ if (result.success) {
832
+ setVerificationRequired(null);
833
+ }
834
+ return result;
835
+ } catch (err) {
836
+ handleError(err);
837
+ throw err;
838
+ } finally {
839
+ setLoading(false);
840
+ }
841
+ }, [deviceId, handleError]);
842
+
843
+ // 加载信任设备
844
+ const loadTrustedDevices = useCallback(async () => {
845
+ try {
846
+ const result = await securityApi.getTrustedDevices();
847
+ const devices = result.devices || result.data || result || [];
848
+ setTrustedDevices(devices);
849
+ return devices;
850
+ } catch (err) {
851
+ handleError(err);
852
+ }
853
+ }, [handleError]);
854
+
855
+ // 移除信任设备
856
+ const removeDevice = useCallback(async deviceIdToRemove => {
857
+ try {
858
+ await securityApi.removeDevice(deviceIdToRemove);
859
+ await loadTrustedDevices();
860
+ } catch (err) {
861
+ handleError(err);
862
+ }
863
+ }, [handleError, loadTrustedDevices]);
864
+
865
+ // 加载风险事件
866
+ const loadRiskEvents = useCallback(async (params = {}) => {
867
+ try {
868
+ const result = await securityApi.getRiskEvents(params);
869
+ const events = result.items || result.data || result || [];
870
+ setRiskEvents(events);
871
+ return events;
872
+ } catch (err) {
873
+ handleError(err);
874
+ }
875
+ }, [handleError]);
876
+ const value = {
877
+ riskLevel,
878
+ deviceId,
879
+ trustedDevices,
880
+ riskEvents,
881
+ verificationRequired,
882
+ loading,
883
+ error,
884
+ checkRisk,
885
+ completeVerification,
886
+ loadTrustedDevices,
887
+ removeDevice,
888
+ loadRiskEvents,
889
+ api: securityApi
890
+ };
891
+ return /*#__PURE__*/React.createElement(SecurityContext.Provider, {
892
+ value: value
893
+ }, children);
894
+ }
895
+ function useSecurity() {
896
+ const context = useContext(SecurityContext);
897
+ if (!context) {
898
+ throw new Error('useSecurity must be used within a SecurityProvider');
899
+ }
900
+ return context;
901
+ }
902
+
903
+ /**
904
+ * Security SDK - RiskBadge 组件
905
+ * 风险等级徽章
906
+ */
907
+
908
+ const RISK_CONFIG = {
909
+ low: {
910
+ color: '#52c41a',
911
+ bg: '#f6ffed',
912
+ label: 'riskLow',
913
+ icon: '✓'
914
+ },
915
+ medium: {
916
+ color: '#faad14',
917
+ bg: '#fffbe6',
918
+ label: 'riskMedium',
919
+ icon: '⚠'
920
+ },
921
+ high: {
922
+ color: '#ff4d4f',
923
+ bg: '#fff2f0',
924
+ label: 'riskHigh',
925
+ icon: '⚠'
926
+ },
927
+ critical: {
928
+ color: '#cf1322',
929
+ bg: '#ffccc7',
930
+ label: 'riskCritical',
931
+ icon: '✕'
932
+ }
933
+ };
934
+ function RiskBadge({
935
+ level = 'low',
936
+ showIcon = true,
937
+ size = 'normal',
938
+ // 'small' | 'normal' | 'large'
939
+ className = ''
940
+ }) {
941
+ const config = RISK_CONFIG[level] || RISK_CONFIG.low;
942
+ return /*#__PURE__*/React.createElement("span", {
943
+ className: `risk-badge risk-${level} size-${size} ${className}`,
944
+ style: {
945
+ color: config.color,
946
+ background: config.bg,
947
+ borderColor: config.color
948
+ }
949
+ }, showIcon && /*#__PURE__*/React.createElement("span", {
950
+ className: "risk-icon"
951
+ }, config.icon), /*#__PURE__*/React.createElement("span", {
952
+ className: "risk-label"
953
+ }, t(config.label)));
954
+ }
955
+
956
+ /**
957
+ * Security SDK - VerificationModal 组件
958
+ * 验证弹窗
959
+ */
960
+
961
+ function VerificationModal({
962
+ type = 'captcha',
963
+ // 'captcha' | 'sms' | 'email' | 'twoFactor'
964
+ onSuccess,
965
+ onCancel,
966
+ className = ''
967
+ }) {
968
+ const {
969
+ completeVerification,
970
+ loading
971
+ } = useSecurity();
972
+ const [code, setCode] = useState('');
973
+ const [error, setError] = useState(null);
974
+ const handleSubmit = async e => {
975
+ e.preventDefault();
976
+ setError(null);
977
+ if (!code.trim()) {
978
+ setError('请输入验证码');
979
+ return;
980
+ }
981
+ try {
982
+ const result = await completeVerification(type, code);
983
+ if (result.success) {
984
+ onSuccess?.(result);
985
+ } else {
986
+ setError(result.message || '验证失败');
987
+ }
988
+ } catch (err) {
989
+ setError(err.message);
990
+ }
991
+ };
992
+ const getTitle = () => {
993
+ switch (type) {
994
+ case 'sms':
995
+ return t('smsCode');
996
+ case 'email':
997
+ return t('emailCode');
998
+ case 'twoFactor':
999
+ return t('twoFactor');
1000
+ default:
1001
+ return t('captcha');
1002
+ }
1003
+ };
1004
+ return /*#__PURE__*/React.createElement("div", {
1005
+ className: `verification-modal-overlay ${className}`
1006
+ }, /*#__PURE__*/React.createElement("div", {
1007
+ className: "verification-modal"
1008
+ }, /*#__PURE__*/React.createElement("button", {
1009
+ className: "modal-close",
1010
+ onClick: onCancel
1011
+ }, "\u2715"), /*#__PURE__*/React.createElement("div", {
1012
+ className: "modal-icon"
1013
+ }, "\uD83D\uDD10"), /*#__PURE__*/React.createElement("h3", null, t('riskDetected')), /*#__PURE__*/React.createElement("p", null, t('pleaseVerify')), /*#__PURE__*/React.createElement("form", {
1014
+ onSubmit: handleSubmit
1015
+ }, /*#__PURE__*/React.createElement("div", {
1016
+ className: "form-group"
1017
+ }, /*#__PURE__*/React.createElement("label", null, getTitle()), /*#__PURE__*/React.createElement("input", {
1018
+ type: "text",
1019
+ value: code,
1020
+ onChange: e => setCode(e.target.value),
1021
+ placeholder: "\u8BF7\u8F93\u5165\u9A8C\u8BC1\u7801",
1022
+ autoFocus: true,
1023
+ maxLength: 6
1024
+ })), error && /*#__PURE__*/React.createElement("div", {
1025
+ className: "form-error"
1026
+ }, error), /*#__PURE__*/React.createElement("div", {
1027
+ className: "form-actions"
1028
+ }, /*#__PURE__*/React.createElement("button", {
1029
+ type: "button",
1030
+ className: "btn-cancel",
1031
+ onClick: onCancel
1032
+ }, "\u53D6\u6D88"), /*#__PURE__*/React.createElement("button", {
1033
+ type: "submit",
1034
+ className: "btn-primary",
1035
+ disabled: loading
1036
+ }, loading ? t('loading') : t('verify'))))));
1037
+ }
1038
+
1039
+ /**
1040
+ * Security SDK - 加密工具
1041
+ */
1042
+
1043
+ class Utf8EncoderFallback {
1044
+ encode(value) {
1045
+ const utf8 = unescape(encodeURIComponent(String(value)));
1046
+ const bytes = new Uint8Array(utf8.length);
1047
+ for (let index = 0; index < utf8.length; index += 1) {
1048
+ bytes[index] = utf8.charCodeAt(index);
1049
+ }
1050
+ return bytes;
1051
+ }
1052
+ }
1053
+ class Utf8DecoderFallback {
1054
+ decode(value) {
1055
+ const bytes = value instanceof Uint8Array ? value : new Uint8Array(value);
1056
+ let binary = '';
1057
+ for (const byte of bytes) {
1058
+ binary += String.fromCharCode(byte);
1059
+ }
1060
+ return decodeURIComponent(escape(binary));
1061
+ }
1062
+ }
1063
+ function createTextEncoder() {
1064
+ return typeof globalThis.TextEncoder === 'function' ? new globalThis.TextEncoder() : new Utf8EncoderFallback();
1065
+ }
1066
+ function createTextDecoder() {
1067
+ return typeof globalThis.TextDecoder === 'function' ? new globalThis.TextDecoder() : new Utf8DecoderFallback();
1068
+ }
1069
+
1070
+ /**
1071
+ * 加密工具类
1072
+ */
1073
+ class CryptoUtilsClass {
1074
+ constructor() {
1075
+ this.encoder = createTextEncoder();
1076
+ this.decoder = createTextDecoder();
1077
+ }
1078
+
1079
+ /**
1080
+ * 生成随机字节
1081
+ */
1082
+ getRandomBytes(length) {
1083
+ return crypto.getRandomValues(new Uint8Array(length));
1084
+ }
1085
+
1086
+ /**
1087
+ * 生成随机16进制字符串
1088
+ */
1089
+ getRandomHex(length) {
1090
+ return Array.from(this.getRandomBytes(length)).map(b => b.toString(16).padStart(2, '0')).join('');
1091
+ }
1092
+
1093
+ /**
1094
+ * 生成UUID
1095
+ */
1096
+ generateUUID() {
1097
+ return crypto.randomUUID?.() || 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
1098
+ const r = Math.random() * 16 | 0;
1099
+ return (c === 'x' ? r : r & 0x3 | 0x8).toString(16);
1100
+ });
1101
+ }
1102
+
1103
+ /**
1104
+ * 计算SHA-256哈希
1105
+ */
1106
+ async sha256(data) {
1107
+ const buffer = typeof data === 'string' ? this.encoder.encode(data) : data;
1108
+ const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);
1109
+ return Array.from(new Uint8Array(hashBuffer)).map(b => b.toString(16).padStart(2, '0')).join('');
1110
+ }
1111
+
1112
+ /**
1113
+ * 计算HMAC-SHA256
1114
+ */
1115
+ async hmacSha256(key, message) {
1116
+ const keyBuffer = typeof key === 'string' ? this.encoder.encode(key) : key;
1117
+ const messageBuffer = typeof message === 'string' ? this.encoder.encode(message) : message;
1118
+ const cryptoKey = await crypto.subtle.importKey('raw', keyBuffer, {
1119
+ name: 'HMAC',
1120
+ hash: 'SHA-256'
1121
+ }, false, ['sign']);
1122
+ const signature = await crypto.subtle.sign('HMAC', cryptoKey, messageBuffer);
1123
+ return Array.from(new Uint8Array(signature)).map(b => b.toString(16).padStart(2, '0')).join('');
1124
+ }
1125
+
1126
+ /**
1127
+ * AES-GCM 加密
1128
+ */
1129
+ async encryptAES(plaintext, keyHex) {
1130
+ const keyBuffer = this.hexToBytes(keyHex);
1131
+ const iv = this.getRandomBytes(12);
1132
+ const plaintextBuffer = this.encoder.encode(plaintext);
1133
+ const cryptoKey = await crypto.subtle.importKey('raw', keyBuffer, 'AES-GCM', false, ['encrypt']);
1134
+ const ciphertext = await crypto.subtle.encrypt({
1135
+ name: 'AES-GCM',
1136
+ iv
1137
+ }, cryptoKey, plaintextBuffer);
1138
+
1139
+ // 返回 iv + ciphertext 的 base64
1140
+ const combined = new Uint8Array(iv.length + ciphertext.byteLength);
1141
+ combined.set(iv);
1142
+ combined.set(new Uint8Array(ciphertext), iv.length);
1143
+ return this.bytesToBase64(combined);
1144
+ }
1145
+
1146
+ /**
1147
+ * AES-GCM 解密
1148
+ */
1149
+ async decryptAES(cipherBase64, keyHex) {
1150
+ const keyBuffer = this.hexToBytes(keyHex);
1151
+ const combined = this.base64ToBytes(cipherBase64);
1152
+ const iv = combined.slice(0, 12);
1153
+ const ciphertext = combined.slice(12);
1154
+ const cryptoKey = await crypto.subtle.importKey('raw', keyBuffer, 'AES-GCM', false, ['decrypt']);
1155
+ const plaintext = await crypto.subtle.decrypt({
1156
+ name: 'AES-GCM',
1157
+ iv
1158
+ }, cryptoKey, ciphertext);
1159
+ return this.decoder.decode(plaintext);
1160
+ }
1161
+
1162
+ /**
1163
+ * 生成AES密钥
1164
+ */
1165
+ generateAESKey() {
1166
+ return this.getRandomHex(32); // 256位
1167
+ }
1168
+
1169
+ /**
1170
+ * 生成RSA密钥对
1171
+ */
1172
+ async generateRSAKeyPair() {
1173
+ const keyPair = await crypto.subtle.generateKey({
1174
+ name: 'RSA-OAEP',
1175
+ modulusLength: 2048,
1176
+ publicExponent: new Uint8Array([1, 0, 1]),
1177
+ hash: 'SHA-256'
1178
+ }, true, ['encrypt', 'decrypt']);
1179
+ const publicKey = await crypto.subtle.exportKey('spki', keyPair.publicKey);
1180
+ const privateKey = await crypto.subtle.exportKey('pkcs8', keyPair.privateKey);
1181
+ return {
1182
+ publicKey: this.bytesToBase64(new Uint8Array(publicKey)),
1183
+ privateKey: this.bytesToBase64(new Uint8Array(privateKey))
1184
+ };
1185
+ }
1186
+
1187
+ /**
1188
+ * 生成ECDSA密钥对(用于签名)
1189
+ */
1190
+ async generateECDSAKeyPair() {
1191
+ const keyPair = await crypto.subtle.generateKey({
1192
+ name: 'ECDSA',
1193
+ namedCurve: 'P-256'
1194
+ }, true, ['sign', 'verify']);
1195
+ const publicKey = await crypto.subtle.exportKey('spki', keyPair.publicKey);
1196
+ const privateKey = await crypto.subtle.exportKey('pkcs8', keyPair.privateKey);
1197
+ return {
1198
+ publicKey: this.bytesToBase64(new Uint8Array(publicKey)),
1199
+ privateKey: this.bytesToBase64(new Uint8Array(privateKey))
1200
+ };
1201
+ }
1202
+
1203
+ /**
1204
+ * ECDSA签名
1205
+ */
1206
+ async signECDSA(message, privateKeyBase64) {
1207
+ const privateKeyBuffer = this.base64ToBytes(privateKeyBase64);
1208
+ const messageBuffer = this.encoder.encode(message);
1209
+ const privateKey = await crypto.subtle.importKey('pkcs8', privateKeyBuffer, {
1210
+ name: 'ECDSA',
1211
+ namedCurve: 'P-256'
1212
+ }, false, ['sign']);
1213
+ const signature = await crypto.subtle.sign({
1214
+ name: 'ECDSA',
1215
+ hash: 'SHA-256'
1216
+ }, privateKey, messageBuffer);
1217
+ return this.bytesToBase64(new Uint8Array(signature));
1218
+ }
1219
+
1220
+ /**
1221
+ * ECDSA验签
1222
+ */
1223
+ async verifyECDSA(message, signatureBase64, publicKeyBase64) {
1224
+ const publicKeyBuffer = this.base64ToBytes(publicKeyBase64);
1225
+ const messageBuffer = this.encoder.encode(message);
1226
+ const signatureBuffer = this.base64ToBytes(signatureBase64);
1227
+ const publicKey = await crypto.subtle.importKey('spki', publicKeyBuffer, {
1228
+ name: 'ECDSA',
1229
+ namedCurve: 'P-256'
1230
+ }, false, ['verify']);
1231
+ return crypto.subtle.verify({
1232
+ name: 'ECDSA',
1233
+ hash: 'SHA-256'
1234
+ }, publicKey, signatureBuffer, messageBuffer);
1235
+ }
1236
+
1237
+ // ============ 工具方法 ============
1238
+
1239
+ hexToBytes(hex) {
1240
+ const bytes = new Uint8Array(hex.length / 2);
1241
+ for (let i = 0; i < bytes.length; i++) {
1242
+ bytes[i] = parseInt(hex.substr(i * 2, 2), 16);
1243
+ }
1244
+ return bytes;
1245
+ }
1246
+ bytesToHex(bytes) {
1247
+ return Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');
1248
+ }
1249
+ bytesToBase64(bytes) {
1250
+ return btoa(String.fromCharCode(...bytes));
1251
+ }
1252
+ base64ToBytes(base64) {
1253
+ const binary = atob(base64);
1254
+ const bytes = new Uint8Array(binary.length);
1255
+ for (let i = 0; i < binary.length; i++) {
1256
+ bytes[i] = binary.charCodeAt(i);
1257
+ }
1258
+ return bytes;
1259
+ }
1260
+ }
1261
+ const cryptoUtils = new CryptoUtilsClass();
1262
+
1263
+ /**
1264
+ * Security SDK - API签名
1265
+ */
1266
+
1267
+
1268
+ /**
1269
+ * API签名器
1270
+ * 用于API请求的签名验证
1271
+ */
1272
+ class ApiSignerClass {
1273
+ constructor(config = {}) {
1274
+ this.secretKey = config.secretKey || '';
1275
+ this.algorithm = config.algorithm || 'hmac-sha256';
1276
+ this.timestampTolerance = config.timestampTolerance || 300; // 5分钟
1277
+ this.nonceStore = new Set();
1278
+ this.nonceMaxAge = 600000; // 10分钟
1279
+ }
1280
+ configure(config) {
1281
+ Object.assign(this, config);
1282
+ }
1283
+
1284
+ /**
1285
+ * 生成签名
1286
+ * @param {Object} params - 请求参数
1287
+ * @param {string} method - HTTP方法
1288
+ * @param {string} path - 请求路径
1289
+ * @returns {Object} 签名信息
1290
+ */
1291
+ async sign(params = {}, method = 'GET', path = '/') {
1292
+ const timestamp = Math.floor(Date.now() / 1000).toString();
1293
+ const nonce = cryptoUtils.getRandomHex(16);
1294
+
1295
+ // 构建待签名字符串
1296
+ const stringToSign = this.buildStringToSign(params, method, path, timestamp, nonce);
1297
+
1298
+ // 计算签名
1299
+ const signature = await cryptoUtils.hmacSha256(this.secretKey, stringToSign);
1300
+ return {
1301
+ timestamp,
1302
+ nonce,
1303
+ signature
1304
+ };
1305
+ }
1306
+
1307
+ /**
1308
+ * 验证签名
1309
+ * @param {Object} params - 请求参数
1310
+ * @param {string} method - HTTP方法
1311
+ * @param {string} path - 请求路径
1312
+ * @param {string} timestamp - 时间戳
1313
+ * @param {string} nonce - 随机数
1314
+ * @param {string} signature - 签名
1315
+ * @returns {boolean} 是否有效
1316
+ */
1317
+ async verify(params, method, path, timestamp, nonce, signature) {
1318
+ // 检查时间戳
1319
+ const now = Math.floor(Date.now() / 1000);
1320
+ if (Math.abs(now - parseInt(timestamp)) > this.timestampTolerance) {
1321
+ return false;
1322
+ }
1323
+
1324
+ // 检查nonce是否已使用(防重放)
1325
+ if (this.nonceStore.has(nonce)) {
1326
+ return false;
1327
+ }
1328
+
1329
+ // 重新计算签名
1330
+ const stringToSign = this.buildStringToSign(params, method, path, timestamp, nonce);
1331
+ const expectedSignature = await cryptoUtils.hmacSha256(this.secretKey, stringToSign);
1332
+
1333
+ // 时间安全的比较
1334
+ if (signature !== expectedSignature) {
1335
+ return false;
1336
+ }
1337
+
1338
+ // 记录nonce
1339
+ this.nonceStore.add(nonce);
1340
+ setTimeout(() => this.nonceStore.delete(nonce), this.nonceMaxAge);
1341
+ return true;
1342
+ }
1343
+
1344
+ /**
1345
+ * 构建待签名字符串
1346
+ */
1347
+ buildStringToSign(params, method, path, timestamp, nonce) {
1348
+ // 参数排序
1349
+ const sortedParams = Object.keys(params).sort().map(key => `${key}=${params[key]}`).join('&');
1350
+
1351
+ // 拼接
1352
+ return [method.toUpperCase(), path, timestamp, nonce, sortedParams].join('\n');
1353
+ }
1354
+
1355
+ /**
1356
+ * 创建签名请求头
1357
+ */
1358
+ async createAuthHeaders(params, method, path) {
1359
+ const {
1360
+ timestamp,
1361
+ nonce,
1362
+ signature
1363
+ } = await this.sign(params, method, path);
1364
+ return {
1365
+ 'X-Timestamp': timestamp,
1366
+ 'X-Nonce': nonce,
1367
+ 'X-Signature': signature
1368
+ };
1369
+ }
1370
+ }
1371
+ const apiSigner = new ApiSignerClass();
1372
+
1373
+ /**
1374
+ * Security SDK - 类型定义
1375
+ */
1376
+
1377
+ // 风险等级
1378
+ const RiskLevel = {
1379
+ NONE: 'none',
1380
+ LOW: 'low',
1381
+ MEDIUM: 'medium',
1382
+ HIGH: 'high',
1383
+ CRITICAL: 'critical'
1384
+ };
1385
+
1386
+ // 安全事件类型
1387
+ const SecurityEventType = {
1388
+ LOGIN: 'login',
1389
+ LOGOUT: 'logout',
1390
+ PASSWORD_CHANGE: 'password_change',
1391
+ MFA_ENABLED: 'mfa_enabled',
1392
+ MFA_DISABLED: 'mfa_disabled',
1393
+ PERMISSION_CHANGE: 'permission_change',
1394
+ SUSPICIOUS_ACTIVITY: 'suspicious_activity',
1395
+ BRUTE_FORCE: 'brute_force',
1396
+ DATA_EXPORT: 'data_export',
1397
+ API_ACCESS: 'api_access'
1398
+ };
1399
+
1400
+ // 加密算法
1401
+ const EncryptionAlgorithm = {
1402
+ AES_256_GCM: 'aes-256-gcm',
1403
+ AES_256_CBC: 'aes-256-cbc',
1404
+ RSA_OAEP: 'rsa-oaep',
1405
+ ECDH: 'ecdh'
1406
+ };
1407
+
1408
+ // 签名算法
1409
+ const SignatureAlgorithm = {
1410
+ HMAC_SHA256: 'hmac-sha256',
1411
+ RSA_SHA256: 'rsa-sha256',
1412
+ ECDSA_P256: 'ecdsa-p256',
1413
+ ED25519: 'ed25519'
1414
+ };
1415
+
1416
+ // 设备信任状态
1417
+ const DeviceTrustStatus = {
1418
+ TRUSTED: 'trusted',
1419
+ UNKNOWN: 'unknown',
1420
+ BLOCKED: 'blocked'
1421
+ };
1422
+
1423
+ /**
1424
+ * @quantabit/security-sdk
1425
+ *
1426
+ * QuantaBit Security Module SDK
1427
+ *
1428
+ * Features:
1429
+ * - Encryption/Decryption (AES, RSA, ECDSA)
1430
+ * - API signature verification
1431
+ * - Device fingerprinting
1432
+ * - Anti-fraud risk control
1433
+ * - Security audit logs
1434
+ */
1435
+
1436
+ const sha256 = (...args) => cryptoUtils.sha256(...args);
1437
+ const hmacSha256 = (...args) => cryptoUtils.hmacSha256(...args);
1438
+ const encryptAES = (...args) => cryptoUtils.encryptAES(...args);
1439
+ const decryptAES = (...args) => cryptoUtils.decryptAES(...args);
1440
+ const generateAESKey = (...args) => cryptoUtils.generateAESKey(...args);
1441
+ const getFingerprint = (...args) => deviceFingerprint.getFingerprint(...args);
1442
+
1443
+ export { ApiSignerClass, CryptoUtilsClass, DeviceFingerprintClass, DeviceTrustStatus, EncryptionAlgorithm, RiskBadge, RiskLevel, SUPPORTED_LANGUAGES, SecurityApiClient, SecurityEventType, SecurityProvider, SignatureAlgorithm, VerificationModal, apiSigner, cryptoUtils, decryptAES, deviceFingerprint, encryptAES, generateAESKey, getDeviceFingerprint, getFingerprint, getLanguage, hmacSha256, messages, securityApi, setLanguage, sha256, t, useSecurity };
1444
+ //# sourceMappingURL=index.esm.js.map