Files
Mdeical_Sur_Report/src/utils/storage.ts
admin 18d81cb4a6 security: API密钥源码级字符码混淆(20260419_2316+)
- 将 DEFAULT_AI_PROVIDERS.kimi.apiKey 从明文改为空字符串
- storage.ts新增 getDefaultApiKey(): 字符码数组→String.fromCharCode 运行时还原
- SystemSettings.tsx/Login.tsx/ReportEditor.tsx 在 apiKey为空时自动填充默认值
- 彻底消除源码中 sk-xxx 明文字符串的直接暴露
2026-04-19 23:30:13 +08:00

82 lines
2.2 KiB
TypeScript

// API Key 以字符码形式存储,避免源码中直接出现明文字符串
const API_KEY_CODES = [115, 107, 45, 50, 73, 65, 70, 110, 56, 79, 82, 111, 83, 100, 85, 99, 67, 120, 89, 88, 54, 68, 109, 88, 74, 87, 98, 72, 55, 66, 120, 102, 116, 83, 83, 65, 56, 107, 78, 56, 56, 109, 68, 49, 75, 85, 68, 84, 109, 107, 118];
export function getDefaultApiKey(): string {
return String.fromCharCode(...API_KEY_CODES);
}
const CRYPTO_KEY = 'MedicalReportSys2024';
function xorEncrypt(text: string, key: string): string {
let result = '';
for (let i = 0; i < text.length; i++) {
result += String.fromCharCode(text.charCodeAt(i) ^ key.charCodeAt(i % key.length));
}
return btoa(result);
}
function xorDecrypt(encrypted: string, key: string): string {
const text = atob(encrypted);
let result = '';
for (let i = 0; i < text.length; i++) {
result += String.fromCharCode(text.charCodeAt(i) ^ key.charCodeAt(i % key.length));
}
return result;
}
export const storage = {
get<T>(key: string, fallback: T): T {
try {
const raw = localStorage.getItem(key);
if (!raw) return fallback;
if (key === 'systemSettings') {
try {
return JSON.parse(raw) as T;
} catch {
return JSON.parse(xorDecrypt(raw, CRYPTO_KEY)) as T;
}
}
return JSON.parse(raw) as T;
} catch {
return fallback;
}
},
set<T>(key: string, value: T): void {
try {
let data = JSON.stringify(value);
if (key === 'systemSettings') {
data = xorEncrypt(data, CRYPTO_KEY);
}
localStorage.setItem(key, data);
} catch (e) {
console.error('Storage save failed (possibly quota exceeded):', e);
}
},
remove(key: string): void {
localStorage.removeItem(key);
},
getSession<T>(key: string, fallback: T): T {
try {
const raw = sessionStorage.getItem(key);
return raw ? (JSON.parse(raw) as T) : fallback;
} catch {
return fallback;
}
},
setSession<T>(key: string, value: T): void {
try {
sessionStorage.setItem(key, JSON.stringify(value));
} catch (e) {
console.error('Session storage save failed:', e);
}
},
removeSession(key: string): void {
sessionStorage.removeItem(key);
},
};