mirror of
https://wget.la/https://github.com/Wxw-Gu/WechatExplorer
synced 2026-08-17 19:47:08 +08:00
100 lines
3.2 KiB
TypeScript
100 lines
3.2 KiB
TypeScript
import { app, safeStorage } from 'electron'
|
|
import fs from 'fs-extra'
|
|
import path from 'path'
|
|
|
|
export interface StoredImageKeyEntry {
|
|
xorKey: string
|
|
aesKey: string
|
|
updatedAt: number
|
|
}
|
|
|
|
interface StoredImageKeyFile {
|
|
version: 1
|
|
accounts: Record<string, StoredImageKeyEntry>
|
|
}
|
|
|
|
interface StoreReadResult {
|
|
success: boolean
|
|
data?: StoredImageKeyFile
|
|
error?: string
|
|
encryptionAvailable: boolean
|
|
}
|
|
|
|
export class ImageKeyStore {
|
|
private get filePath(): string {
|
|
return path.join(app.getPath('userData'), 'wechat-image-keys.bin')
|
|
}
|
|
|
|
get(accountId: string): StoreReadResult & { entry?: StoredImageKeyEntry } {
|
|
const result = this.read()
|
|
return { ...result, entry: result.data?.accounts[accountId] }
|
|
}
|
|
|
|
save(
|
|
accountId: string,
|
|
entry: Omit<StoredImageKeyEntry, 'updatedAt'>
|
|
): { success: boolean; entry?: StoredImageKeyEntry; error?: string } {
|
|
if (!safeStorage.isEncryptionAvailable()) {
|
|
return { success: false, error: '系统安全存储不可用' }
|
|
}
|
|
const current = this.read()
|
|
if (!current.success && fs.existsSync(this.filePath)) {
|
|
return { success: false, error: '无法读取现有图片密钥配置' }
|
|
}
|
|
const nextEntry = { ...entry, updatedAt: Date.now() }
|
|
const data: StoredImageKeyFile = current.data || { version: 1, accounts: {} }
|
|
data.accounts[accountId] = nextEntry
|
|
const saved = this.write(data)
|
|
return saved.success ? { success: true, entry: nextEntry } : saved
|
|
}
|
|
|
|
clear(accountId: string): { success: boolean; error?: string } {
|
|
const current = this.read()
|
|
if (!current.success) return { success: false, error: current.error }
|
|
if (!current.data?.accounts[accountId]) return { success: true }
|
|
delete current.data.accounts[accountId]
|
|
try {
|
|
if (Object.keys(current.data.accounts).length === 0) fs.removeSync(this.filePath)
|
|
else return this.write(current.data)
|
|
return { success: true }
|
|
} catch {
|
|
return { success: false, error: '无法清除图片密钥配置' }
|
|
}
|
|
}
|
|
|
|
private read(): StoreReadResult {
|
|
const encryptionAvailable = safeStorage.isEncryptionAvailable()
|
|
if (!fs.existsSync(this.filePath)) {
|
|
return {
|
|
success: true,
|
|
data: { version: 1, accounts: {} },
|
|
encryptionAvailable
|
|
}
|
|
}
|
|
if (!encryptionAvailable) {
|
|
return { success: false, error: '系统安全存储不可用', encryptionAvailable }
|
|
}
|
|
try {
|
|
const decrypted = safeStorage.decryptString(fs.readFileSync(this.filePath))
|
|
const data = JSON.parse(decrypted) as StoredImageKeyFile
|
|
if (data.version !== 1 || !data.accounts) throw new Error('invalid image key store')
|
|
return { success: true, data, encryptionAvailable }
|
|
} catch {
|
|
return { success: false, error: '图片密钥安全存储不可读取', encryptionAvailable }
|
|
}
|
|
}
|
|
|
|
private write(data: StoredImageKeyFile): { success: boolean; error?: string } {
|
|
try {
|
|
fs.ensureDirSync(path.dirname(this.filePath))
|
|
fs.writeFileSync(this.filePath, safeStorage.encryptString(JSON.stringify(data)), {
|
|
mode: 0o600
|
|
})
|
|
fs.chmodSync(this.filePath, 0o600)
|
|
return { success: true }
|
|
} catch {
|
|
return { success: false, error: '图片密钥保存失败' }
|
|
}
|
|
}
|
|
}
|