Case Study · 跨領域作品 · 桌面應用

Kaizei

Personal Finance OS — 台美股投資 / 智能記帳 / 雙式帳本

角色:獨力開發
時程:2024–2026
狀態:上線(v2.4.17)
月成本:$0(Cloudflare + Supabase 免費 tier)
v2.4.17當前版本
AES-256GCM 零知識加密
310kPBKDF2 iterations
0TypeScript strict 錯誤
Kaizei 官方網站 hero — 零知識加密帳本
Kaizei 官方網站(kaizei.pages.dev)── 零知識加密是核心訴求,非附加功能。

痛點

個人理財軟體的兩個結構性問題:(1) 多裝置同步必然牽涉雲端,但把 API key 跟交易紀錄交給第三方 server形同把鑰匙交出去; (2) 主流 Electron 應用安全做得草率,CSP 缺失、Node.js 整合一打開、API key 平文存 config 檔。

Kaizei 的設計目標:所有功能(台 / 美股自動更新、雙式記帳、報表、Gemini 分析)都做齊,但server 物理上無法讀取使用者資料, 而且把桌面端的 OS 級 / sandbox 級防護都做到位。

系統架構

桌面 + 邊緣 + 物件儲存的三層分離。Server 只看密文,認證與解密在使用者裝置完成。

  1. 1 · 使用者主密碼

    本機輸入主密碼,永不離開使用者裝置。透過 Web Crypto 衍生兩把獨立金鑰。

  2. 2 · 雙金鑰衍生(PBKDF2 310,000 iterations)

    authKey(送 server 做身份驗證)與 encKey(留在裝置、加 / 解密 vault 用)。兩者由同一密碼但不同 salt 衍生,互不可推導。

  3. 3 · 本機 AES-256-GCM 加密

    vault 資料(API keys、設定、敏感欄位)以 encKey 加密成 ciphertext 後才送雲端。Server 收到的是已加密的 binary blob。

  4. 4 · Cloudflare Worker(Hono + 自寫 JWT)

    Worker 用 SHA-256(authKey + server pepper) 比對使用者身份、發 30 天 HS256 JWT。即使 JWT 被竊,攻擊者拿到的仍是 server 也讀不懂的密文。

  5. 5 · Supabase(PostgreSQL + RLS)

    RLS 設成無 public policy ── 只有 Worker 用 service_role 可寫。GitHub Actions 每日 02:00 UTC ping 一次防止免費 tier 暫停。

Kaizei 桌面 app 主畫面
圖:Kaizei 桌面 app 主畫面。台 / 美股即時報價、近 6 個月收支趨勢、支出分類、最近交易整合於單一儀表板。所有顯示資料於本機 AES-256-GCM 解密後渲染,雲端僅儲存密文。

設計亮點 1 ── 零知識加密 vault

最關鍵的設計:server 物理上無法解密使用者資料。即使 server 完全被入侵、DB 被脫庫、攻擊者拿到管理員權限, 撈出來的仍是 AES-GCM ciphertext,沒有使用者主密碼就無法還原成明文。

User Device Cloudflare Worker · Supabase Master Password never leaves device PBKDF2 (310,000) → authKey + encKey AES-256-GCM encrypts vault locally encKey stays on device authKey + ciphertext Worker (Hono + JWT) SHA-256(authKey + pepper) Supabase (PG + RLS) stores: email · authHash · salt + AES-GCM ciphertext only server CANNOT decrypt (no encKey on server)
圖:零知識加密流程。authKey 用於身份驗證、encKey 永不離開使用者裝置。即使 server 被完全入侵,攻擊者拿到的也只是 AES-GCM 密文。

具體實作細節:

  • PBKDF2 310,000 iterations(OWASP 2023 建議下限)由主密碼 + 兩組獨立 salt 衍生 authKey 與 encKey
  • Server pepper 額外加在 authKey hash,即使 DB salt 外洩也無法離線爆破
  • JWT 30 天到期,洩漏的 JWT 仍只能看到密文
  • Web Crypto API 全程用瀏覽器 / Electron 原生 crypto,無第三方加密庫信任問題

Trade-off

  • 主密碼遺失 = 資料無法救回。沒有後門 = 沒有「忘記密碼」選項。對使用者教育要做足
  • 每次解鎖延遲 ~ 200-400ms(PBKDF2 設計如此)。為了安全的可接受成本
  • 同步衝突解決受限:server 看不懂內容,無法做欄位級 merge,只能整包覆蓋(last-write-wins)

設計亮點 2 ── 桌面端深層防護

零知識保護「server 看不到」這條線。Electron 桌面端則需要另一套縱深防護避免本機被攻:

  1. OS 金鑰庫整合

    Windows DPAPI / macOS Keychain 對本機儲存的 API key(即便已是 vault 的一部分)做第二層OS-level 加密,與使用者帳號 / 硬體綁定。

  2. Electron sandbox 全開

    sandbox: true + nodeIntegration: false + contextIsolation: true。Renderer 無 Node.js 直接存取,main process 透過 IPC 嚴格白名單。

  3. CSP 強制 + DOMPurify

    Production build 自動移除 'unsafe-inline'。所有可能含 HTML 的內容(從 GitHub Releases 抓的 changelog、使用者輸入備註)強制走 DOMPurify。

Kaizei 股票追蹤畫面
圖:股票模組。台 / 美股即時報價,所有 API key 由 OS 金鑰庫加密保護。
Kaizei 帳本畫面
圖:雙式記帳模組。每筆交易記錄在本地後加密同步到雲端 vault。

設計亮點 3 ── 資料管道與供應鏈防護

  1. Excel 匯入 ReDoS 防護

    檔案大小硬限制 20 MB(阻擋 ReDoS attack vector)+ 匯入前自動快照(最多 5 份本地備份)+ 一鍵還原無需密碼。

  2. TypeScript strict mode 零容忍

    v2.4.17 全面啟用 strict: true,修正 32 個既存型別錯誤達 0 errors 基線。型別安全 = 編譯期消除整類 bug。

  3. Dependabot 每週掃描

    npm 套件漏洞每週自動掃描 + 自動 PR。Secret Scanning + Push Protection 防 secret 誤推送。

  4. 公開 release mirror(auditable binaries)

    App 主 repo 私有,但 release 同步至公開 yu8812/kaizei-releases,使用者可以驗證二進位檔的 hash 與 release notes。

Kaizei 官網更新紀錄
圖:官網「更新紀錄」段。透過 GitHub Releases API 抓取公開 release mirror 的版本歷史,使用者可一目了然每版本的安全性更新。

技術棧

ElectronReactViteTypeScript strict Cloudflare WorkersHono v4 Supabase (PostgreSQL + RLS) Web Crypto · AES-256-GCMPBKDF2 HS256 JWT (custom) Tailwind CSS GitHub Actions CI/CD
Kaizei 官網功能特色
圖:官網「核心特色」段。三大支柱(隱私 / 結算 / AI)的視覺呈現,與本案例研究的設計亮點對應。

反思 / 未來方向

  1. 無後門設計與「忘記密碼」之間的張力 ── 主密碼遺失 = 資料無法救回是零知識架構的必然代價。可選的中間方案(Shamir Secret Sharing 三選二恢復、社交回復)會增加實作複雜度與信任假設。值得探討的設計命題。
  2. Electron 桌面應用的真實攻擊面評估 ── 多層防護(sandbox + CSP + OS keychain + AES)做了,但對應的 threat model 是否過 / 不足,需要對應實證攻擊測試(如 sandbox escape 漏洞研究)。
  3. 跨機器 vault 同步的衝突解決 ── 目前 last-write-wins。能否在不破壞零知識的前提下做欄位級 CRDT merge?這是密碼學 + 分散式系統的有趣交叉問題。

延伸閱讀