mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-14 08:16:56 +08:00
Dev Crypto (#730)
* feat: remove admin mode * feat: bugfix * feat(crypto): 添加RSA-OAEP + AES-GCM混合加密服务 - 实现CryptoService加密服务,支持RSA-OAEP-2048 + AES-256-GCM混合加密 - 集成数据库层加密,自动加密存储敏感字段(API密钥、私钥等) - 支持环境变量DATA_ENCRYPTION_KEY配置数据加密密钥 - 适配SQLite数据库加密存储(从PostgreSQL移植) - 保持Hyperliquid代理钱包处理兼容性 - 更新.gitignore以正确处理crypto模块代码 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: tinkle-community <tinklefund@gmail.com> * feat(scripts): 添加加密环境一键设置脚本 - setup_encryption.sh: 一键生成RSA密钥对+数据加密密钥+JWT密钥 - generate_rsa_keys.sh: 专业的RSA-2048密钥对生成工具 - generate_data_key.sh: 生成AES-256数据加密密钥和JWT认证密钥 - ENCRYPTION_README.md: 详细的加密系统说明文档 - 支持自动检测现有密钥并只生成缺失的密钥 - 完善的权限管理和安全验证 - 兼容macOS和Linux的跨平台支持 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: tinkle-community <tinklefund@gmail.com> * feat(api): 添加加密API端点和Gin框架集成 - 新增CryptoHandler处理加密相关API请求 - 提供/api/crypto/public-key端点获取RSA公钥 - 提供/api/crypto/decrypt端点解密敏感数据 - 适配Gin框架的HTTP处理器格式 - 集成CryptoService到API服务器 - 支持前端加密数据传输和解密 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: tinkle-community <tinklefund@gmail.com> * feat(web): 添加前端加密服务和两阶段密钥输入组件 - CryptoService: Web Crypto API集成,支持RSA-OAEP加密 - TwoStageKeyModal: 安全的两阶段私钥输入组件,支持剪贴板混淆 - 完善国际化翻译支持加密相关UI文本 - 修复TypeScript类型错误和编译问题 - 支持前端敏感数据加密传输到后端 - 增强用户隐私保护和数据安全 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: tinkle-community <tinklefund@gmail.com> * feat(auth): 增强JWT认证安全性 - 优先使用环境变量JWT_SECRET而不是数据库配置 - 支持通过.env文件安全配置JWT认证密钥 - 保留数据库配置作为回退机制 - 改进JWT密钥来源日志显示 - 增强系统启动时的安全配置检查 - 支持运行时动态JWT密钥切换 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: tinkle-community <tinklefund@gmail.com> * feat(docker): 集成加密环境变量到Docker部署 - 添加DATA_ENCRYPTION_KEY环境变量传递到容器 - 添加JWT_SECRET环境变量支持 - 挂载secrets目录使容器可访问RSA密钥文件 - 确保容器内加密服务正常工作 - 解决容器启动失败和加密初始化问题 - 完善Docker Compose加密环境配置 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: tinkle-community <tinklefund@gmail.com> * feat(start): 集成自动加密环境检测和设置 - 增强check_encryption()函数检测JWT_SECRET和DATA_ENCRYPTION_KEY - 自动运行setup_encryption.sh当检测到缺失密钥时 - 改进加密状态显示,包含RSA+AES+JWT全套加密信息 - 优化用户体验,提供清晰的加密配置反馈 - 支持一键设置完整加密环境 - 确保容器启动前加密环境就绪 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: tinkle-community <tinklefund@gmail.com> * feat: format fix * fix(security): 修复前端模型和交易所配置敏感数据明文传输 - 在handleSaveModelConfig中对API密钥进行RSA-OAEP加密 - 在handleSaveExchangeConfig中对API密钥、Secret密钥和Aster私钥进行加密 - 只有非空敏感数据才进行加密处理 - 添加加密失败错误处理和用户友好提示 - 增加encryptionFailed翻译键的中英文支持 - 使用用户ID和会话ID作为加密上下文增强安全性 这修复了之前敏感数据在网络传输中以明文形式发送的安全漏洞。 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: tinkle-community <tinklefund@gmail.com> * fix(crypto): 修复后端加密服务集成和缺失的加密端点 - 添加Server结构体缺少的cryptoService字段 - 实现handleUpdateModelConfigsEncrypted处理器用于模型配置加密传输 - 修复handleUpdateExchangeConfigsEncrypted中的函数调用 - 在前端API中添加updateModelConfigsEncrypted方法 - 统一RSA密钥路径从secrets/rsa_key改为keys/rsa_private.key - 确保前端可以使用加密端点安全传输敏感数据 - 兼容原有加密通信模式和二段输入私钥功能 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: tinkle-community <tinklefund@gmail.com> --------- Co-authored-by: icy <icyoung520@gmail.com> Co-authored-by: tinkle-community <tinklefund@gmail.com>
This commit is contained in:
@@ -206,6 +206,44 @@ export const translations = {
|
||||
'API wallet private key - Get from https://www.asterdex.com/en/api-wallet (only used locally for signing, never transmitted)',
|
||||
asterUsdtWarning:
|
||||
'Important: Aster only tracks USDT balance. Please ensure you use USDT as margin currency to avoid P&L calculation errors caused by price fluctuations of other assets (BNB, ETH, etc.)',
|
||||
|
||||
// Exchange names
|
||||
hyperliquidExchangeName: 'Hyperliquid',
|
||||
asterExchangeName: 'Aster DEX',
|
||||
|
||||
// Secure input
|
||||
secureInputButton: 'Secure Input',
|
||||
secureInputReenter: 'Re-enter Securely',
|
||||
secureInputClear: 'Clear',
|
||||
secureInputHint:
|
||||
'Captured via secure two-step input. Use "Re-enter Securely" to update this value.',
|
||||
|
||||
// Two Stage Key Modal
|
||||
twoStageModalTitle: 'Secure Key Input',
|
||||
twoStageModalDescription:
|
||||
'Use a two-step flow to enter your {length}-character private key safely.',
|
||||
twoStageStage1Title: 'Step 1 · Enter the first half',
|
||||
twoStageStage1Placeholder: 'First 32 characters (include 0x if present)',
|
||||
twoStageStage1Hint:
|
||||
'Continuing copies an obfuscation string to your clipboard as a diversion.',
|
||||
twoStageStage1Error: 'Please enter the first part before continuing.',
|
||||
twoStageNext: 'Next',
|
||||
twoStageProcessing: 'Processing…',
|
||||
twoStageCancel: 'Cancel',
|
||||
twoStageStage2Title: 'Step 2 · Enter the rest',
|
||||
twoStageStage2Placeholder: 'Remaining characters of your private key',
|
||||
twoStageStage2Hint:
|
||||
'Paste the obfuscation string somewhere neutral, then finish entering your key.',
|
||||
twoStageClipboardSuccess:
|
||||
'Obfuscation string copied. Paste it into any text field once before completing.',
|
||||
twoStageClipboardReminder:
|
||||
'Remember to paste the obfuscation string before submitting to avoid clipboard leaks.',
|
||||
twoStageClipboardManual:
|
||||
'Automatic copy failed. Copy the obfuscation string below manually.',
|
||||
twoStageBack: 'Back',
|
||||
twoStageSubmit: 'Confirm',
|
||||
twoStageInvalidFormat:
|
||||
'Invalid private key format. Expected {length} hexadecimal characters (optional 0x prefix).',
|
||||
testnetDescription:
|
||||
'Enable to connect to exchange test environment for simulated trading',
|
||||
securityWarning: 'Security Warning',
|
||||
@@ -321,6 +359,7 @@ export const translations = {
|
||||
exchangeNotExist: 'Exchange does not exist',
|
||||
deleteExchangeConfigFailed: 'Failed to delete exchange configuration',
|
||||
saveSignalSourceFailed: 'Failed to save signal source configuration',
|
||||
encryptionFailed: 'Failed to encrypt sensitive data',
|
||||
|
||||
// Login & Register
|
||||
login: 'Sign In',
|
||||
@@ -684,6 +723,35 @@ export const translations = {
|
||||
faqGetHelp: 'Where can I get help?',
|
||||
faqGetHelpAnswer:
|
||||
'Check GitHub Discussions, join our Telegram Community, or open an issue on GitHub.',
|
||||
|
||||
// Two-Stage Key Modal
|
||||
twoStageKey: {
|
||||
title: 'Two-Stage Private Key Input',
|
||||
stage1Description:
|
||||
'Enter the first {length} characters of your private key',
|
||||
stage2Description:
|
||||
'Enter the remaining {length} characters of your private key',
|
||||
stage1InputLabel: 'First Part',
|
||||
stage2InputLabel: 'Second Part',
|
||||
characters: 'characters',
|
||||
processing: 'Processing...',
|
||||
nextButton: 'Next',
|
||||
cancelButton: 'Cancel',
|
||||
backButton: 'Back',
|
||||
encryptButton: 'Encrypt & Submit',
|
||||
obfuscationCopied: 'Obfuscation data copied to clipboard',
|
||||
obfuscationInstruction:
|
||||
'Paste something else to clear clipboard, then continue',
|
||||
obfuscationManual: 'Manual obfuscation required',
|
||||
},
|
||||
|
||||
// Error Messages
|
||||
errors: {
|
||||
privatekeyIncomplete: 'Please enter at least {expected} characters',
|
||||
privatekeyInvalidFormat:
|
||||
'Invalid private key format (should be 64 hex characters)',
|
||||
privatekeyObfuscationFailed: 'Clipboard obfuscation failed',
|
||||
},
|
||||
},
|
||||
zh: {
|
||||
// Header
|
||||
@@ -887,6 +955,41 @@ export const translations = {
|
||||
'API 钱包私钥 - 从 https://www.asterdex.com/zh-CN/api-wallet 获取(仅在本地用于签名,不会被传输)',
|
||||
asterUsdtWarning:
|
||||
'重要提示:Aster 仅统计 USDT 余额。请确保您使用 USDT 作为保证金币种,避免其他资产(BNB、ETH等)的价格波动导致盈亏统计错误',
|
||||
|
||||
// Exchange names
|
||||
hyperliquidExchangeName: 'Hyperliquid',
|
||||
asterExchangeName: 'Aster DEX',
|
||||
|
||||
// Secure input
|
||||
secureInputButton: '安全输入',
|
||||
secureInputReenter: '重新安全输入',
|
||||
secureInputClear: '清除',
|
||||
secureInputHint:
|
||||
'已通过安全双阶段输入设置。若需修改,请点击"重新安全输入"。',
|
||||
|
||||
// Two Stage Key Modal
|
||||
twoStageModalTitle: '安全私钥输入',
|
||||
twoStageModalDescription: '使用双阶段流程安全输入长度为 {length} 的私钥。',
|
||||
twoStageStage1Title: '步骤一 · 输入前半段',
|
||||
twoStageStage1Placeholder: '前 32 位字符(若有 0x 前缀请保留)',
|
||||
twoStageStage1Hint:
|
||||
'继续后会将扰动字符串复制到剪贴板,用于迷惑剪贴板监控。',
|
||||
twoStageStage1Error: '请先输入第一段私钥。',
|
||||
twoStageNext: '下一步',
|
||||
twoStageProcessing: '处理中…',
|
||||
twoStageCancel: '取消',
|
||||
twoStageStage2Title: '步骤二 · 输入剩余部分',
|
||||
twoStageStage2Placeholder: '剩余的私钥字符',
|
||||
twoStageStage2Hint: '将扰动字符串粘贴到任意位置后,再完成私钥输入。',
|
||||
twoStageClipboardSuccess:
|
||||
'扰动字符串已复制。请在完成前在任意文本处粘贴一次以迷惑剪贴板记录。',
|
||||
twoStageClipboardReminder:
|
||||
'记得在提交前粘贴一次扰动字符串,降低剪贴板泄漏风险。',
|
||||
twoStageClipboardManual: '自动复制失败,请手动复制下面的扰动字符串。',
|
||||
twoStageBack: '返回',
|
||||
twoStageSubmit: '确认',
|
||||
twoStageInvalidFormat:
|
||||
'私钥格式不正确,应为 {length} 位十六进制字符(可选 0x 前缀)。',
|
||||
testnetDescription: '启用后将连接到交易所测试环境,用于模拟交易',
|
||||
securityWarning: '安全提示',
|
||||
saveConfiguration: '保存配置',
|
||||
@@ -981,6 +1084,7 @@ export const translations = {
|
||||
exchangeNotExist: '交易所不存在',
|
||||
deleteExchangeConfigFailed: '删除交易所配置失败',
|
||||
saveSignalSourceFailed: '保存信号源配置失败',
|
||||
encryptionFailed: '加密敏感数据失败',
|
||||
|
||||
// Login & Register
|
||||
login: '登录',
|
||||
@@ -1325,6 +1429,31 @@ export const translations = {
|
||||
faqGetHelp: '在哪里可以获得帮助?',
|
||||
faqGetHelpAnswer:
|
||||
'查看 GitHub Discussions、加入 Telegram 社区或在 GitHub 上提出 issue。',
|
||||
|
||||
// Two-Stage Key Modal
|
||||
twoStageKey: {
|
||||
title: '两阶段私钥输入',
|
||||
stage1Description: '请输入私钥的前 {length} 位字符',
|
||||
stage2Description: '请输入私钥的后 {length} 位字符',
|
||||
stage1InputLabel: '第一部分',
|
||||
stage2InputLabel: '第二部分',
|
||||
characters: '位字符',
|
||||
processing: '处理中...',
|
||||
nextButton: '下一步',
|
||||
cancelButton: '取消',
|
||||
backButton: '返回',
|
||||
encryptButton: '加密并提交',
|
||||
obfuscationCopied: '混淆数据已复制到剪贴板',
|
||||
obfuscationInstruction: '请粘贴其他内容清空剪贴板,然后继续',
|
||||
obfuscationManual: '需要手动混淆',
|
||||
},
|
||||
|
||||
// Error Messages
|
||||
errors: {
|
||||
privatekeyIncomplete: '请输入至少 {expected} 位字符',
|
||||
privatekeyInvalidFormat: '私钥格式无效(应为64位十六进制字符)',
|
||||
privatekeyObfuscationFailed: '剪贴板混淆失败',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1333,7 +1462,15 @@ export function t(
|
||||
lang: Language,
|
||||
params?: Record<string, string | number>
|
||||
): string {
|
||||
let text = translations[lang][key as keyof (typeof translations)['en']] || key
|
||||
// Handle nested keys like 'twoStageKey.title'
|
||||
const keys = key.split('.')
|
||||
let value: any = translations[lang]
|
||||
|
||||
for (const k of keys) {
|
||||
value = value?.[k]
|
||||
}
|
||||
|
||||
let text = typeof value === 'string' ? value : key
|
||||
|
||||
// Replace parameters like {count}, {gap}, etc.
|
||||
if (params) {
|
||||
|
||||
Reference in New Issue
Block a user