返回 oh-my-ppt
credentials.ts
根目录 / src / main / ipc / runtime / credentials.ts
1 import { safeStorage } from 'electron'
2 import log from 'electron-log/main.js'
3
4 const ENCRYPTED_API_KEY_PREFIX = 'enc:v1:'
5
6 export type RuntimeCredentials = {
7 encryptApiKey(apiKey: string): string
8 decryptApiKey(rawValue: unknown): string
9 }
10
11 export function createRuntimeCredentials(): RuntimeCredentials {
12 const encryptApiKey = (apiKey: string): string => {
13 const trimmed = apiKey.trim()
14 if (trimmed.length === 0) return ''
15 if (!safeStorage.isEncryptionAvailable()) {
16 log.warn('[settings] safeStorage unavailable, fallback to plaintext api key storage')
17 return trimmed
18 }
19 try {
20 const encrypted = safeStorage.encryptString(trimmed).toString('base64')
21 return `${ENCRYPTED_API_KEY_PREFIX}${encrypted}`
22 } catch (error) {
23 const message = error instanceof Error ? error.message : String(error)
24 log.error('[settings] api key encrypt failed', { message })
25 throw new Error('API Key 加密失败,请检查系统钥匙串状态后重试。')
26 }
27 }
28
29 const decryptApiKey = (rawValue: unknown): string => {
30 if (typeof rawValue !== 'string') return ''
31 const raw = rawValue.trim()
32 if (!raw) return ''
33 if (!raw.startsWith(ENCRYPTED_API_KEY_PREFIX)) return raw
34 if (!safeStorage.isEncryptionAvailable()) {
35 log.warn('[settings] safeStorage unavailable, cannot decrypt encrypted api key')
36 return ''
37 }
38 try {
39 const encrypted = raw.slice(ENCRYPTED_API_KEY_PREFIX.length)
40 return safeStorage.decryptString(Buffer.from(encrypted, 'base64'))
41 } catch (error) {
42 const message = error instanceof Error ? error.message : String(error)
43 log.error('[settings] api key decrypt failed', { message })
44 return ''
45 }
46 }
47
48 return { encryptApiKey, decryptApiKey }
49 }
50
50 lines TYPESCRIPT