import { app, safeStorage } from 'electron' import path from 'path' import fs from 'fs' import crypto from 'crypto' import { createLogger } from '../utils/logger' const logger = createLogger('KeyService') const KEY_FILE = 'encryption.key.enc' const LEGACY_KEY_FILE = 'encryption.key' export class KeyService { private key: string | null = null /** * 获取或创建主密钥 * 使用 Electron safeStorage 加密存储,替代明文存储 */ getMasterKey(): string { if (this.key) return this.key const userDataPath = app.getPath('userData') const keyPath = path.join(userDataPath, KEY_FILE) const legacyKeyPath = path.join(userDataPath, LEGACY_KEY_FILE) // 1. 尝试读取新的加密格式密钥 if (fs.existsSync(keyPath)) { try { const encrypted = fs.readFileSync(keyPath) this.key = safeStorage.decryptString(encrypted) logger.info('Master key loaded from encrypted storage') return this.key } catch (error) { logger.error('Failed to decrypt master key, generating new one:', error) } } // 2. 迁移旧的明文密钥(向后兼容) if (fs.existsSync(legacyKeyPath)) { try { this.key = fs.readFileSync(legacyKeyPath, 'utf8').trim() // 迁移到加密存储 this.saveEncryptedKey(this.key) // 安全删除旧文件(覆盖后删除) this.secureDelete(legacyKeyPath) logger.info('Migrated master key from plaintext to encrypted storage') return this.key } catch (error) { logger.error('Failed to migrate legacy key:', error) } } // 3. 生成新密钥 this.key = crypto.randomBytes(32).toString('hex') this.saveEncryptedKey(this.key) logger.info('Generated new master key with encrypted storage') return this.key } // 使用 safeStorage 加密保存密钥 private saveEncryptedKey(key: string): void { const keyPath = path.join(app.getPath('userData'), KEY_FILE) const encrypted = safeStorage.encryptString(key) fs.writeFileSync(keyPath, encrypted, { mode: 0o600 }) } // 安全删除文件(先覆盖再删除) private secureDelete(filePath: string): void { try { const stats = fs.statSync(filePath) const size = stats.size // 用随机数据覆盖 const randomData = crypto.randomBytes(size) fs.writeFileSync(filePath, randomData) // 再用零覆盖 fs.writeFileSync(filePath, Buffer.alloc(size, 0)) // 最后删除 fs.unlinkSync(filePath) } catch (error) { logger.error('Failed to securely delete file:', error) } } // 清除密钥(登出时) clearKey(): void { this.key = null } } // 全局单例 export const keyService = new KeyService()