所有專案
03SAVote校園選舉系統2025–2026上線中

可驗證資格的匿名投票系統。

國立彰化師範大學學生會的電子投票系統。學生以校園 SSO 登入確認資格,瀏覽器在本機產生秘密值並註冊 commitment;投票時於瀏覽器產生零知識證明,伺服器驗證後將選票存入不含學號與 commitment 的資料表。

我的角色 團隊專案(GDG on Campus NCUE 與學生會資訊部)。我建立專案並撰寫初版系統規格,負責校園 SSO 登入、commitment 註冊、部署腳本與電路建置流程、管理端的 Keycloak 登入與權限,以及選舉公告、使用說明與驗票中心(後由隊友改為公開開票結果頁)等頁面。

零知識證明系統(BN128 曲線)
Groth16
零知識證明系統(BN128 曲線)
電路內使用的雜湊函數
Poseidon
電路內使用的雜湊函數
每場選舉一組金鑰,開票時才解密
RSA-2048
每場選舉一組金鑰,開票時才解密
個登入入口,選民與管理員分離
2
個登入入口,選民與管理員分離
投票亭:選好候選人後,在瀏覽器裡產生零知識證明

01

要解決的問題

  • 資格與選票分離

    系統必須確認資格,但不能將「投票者」與「投票內容」綁在一起。

  • 結果可驗證

    隱私與可驗證性必須同時成立,而非僅仰賴對伺服器的信任。

  • 一人一票

    每位選民在每場選舉只能投一次,重複投票必須被拒絕。

  • 選民與管理員分離

    學生使用校園 SSO,管理員使用學生會的 Keycloak;管理介面不提供任何投票功能。

02

系統架構

身分驗證採中心化的校園 SSO,選票匿名性則由零知識證明與加密保障。下圖為目前程式碼的實際流程。

校園 SSO 登入伺服器存學號的 SHA-256
資格檢查對照選舉人名冊
瀏覽器產生秘密值只存在使用者端
註冊 commitmentPoseidon(學號雜湊, 秘密值)
產生證明Web Worker 跑 Groth16;選票用 RSA-OAEP 加密
伺服器驗證snarkjs 驗證證明、檢查沒投過
同一筆交易金鑰標記已用+寫入選票
開票選舉結束後用私鑰解密計票

← 左右滑動看完整流程 →

使用技術

前端
ReactViteTailwind CSSZustand
後端
NestJSPrismaPostgreSQL
零知識證明
CircomsnarkjsGroth16Poseidon
身分與部署
OIDCKeycloakDockerNginx

03

主要功能

  • 校園 SSO 登入

    學生以學校帳號登入,伺服器僅保存學號雜湊。

  • 匿名身分註冊

    瀏覽器產生秘密值,僅將 commitment 提交給伺服器。

  • 投票亭

    可選擇候選人或投空白票;證明於背景執行緒產生,不影響操作。

  • 公告與開票結果

    選舉公告、使用說明與公開的開票結果頁。

  • 管理員權限

    以 Keycloak 登入;超級管理員可新增、刪除或提升其他管理員。

  • 選舉與名冊管理

    建立選舉與候選人(可鎖定)、匯入選舉人名冊、監看投票與抽籤。

04

技術細節

  1. 04.1

    commitment:證明知道秘密,而不揭露秘密

    註冊時伺服器只取得 Poseidon(學號雜湊, 秘密值) 的結果。投票時瀏覽器產生 Groth16 證明,證明自己知道此 commitment 背後的兩個值;伺服器能驗證證明,卻無從得知秘密值。

    瀏覽器(只在你這邊)

    學號雜湊
    秘密值
    Poseidon(…) = ?
    Web Worker 產生 Groth16 證明
    commitment證明

    伺服器看得到的

    • commitment
    • 證明…
    • 秘密值
  2. 04.2

    身分與選票分表儲存

    驗證通過後,「標記投票金鑰已使用」與「寫入選票」在同一筆交易中完成。選票表僅存放加密內容與證明,不含學號與 commitment。

    • 選票於瀏覽器以該場選舉的 RSA-2048 公鑰(OAEP、SHA-256)加密,開票時才以私鑰解密。
    • 送出失敗與成功的回應相同,避免從回應推知驗證細節。
    同一筆資料庫交易

    UserVoteKey

    學號雜湊commitment已投票
    9f2c…1873…false
    沒有關聯欄位

    Vote

    加密選票證明
    Qm8x…{…}
    Zk3p…{…}

    欄位與數值為示意。

規格與現行實作的差異

專案文件的設計是在電路中加入 Merkle Tree 成員證明與 nullifier 以防重複投票;目前上線的電路僅證明 commitment 的兩個原始值,資格與是否已投票改由伺服器查表確認。整體為中心化身分驗證結合零知識證明的混合架構,並非去中心化系統。

05

系統畫面

管理端:選舉管理與候選人鎖定
管理端:選舉管理與候選人鎖定
公開開票結果頁(測試選舉)
公開開票結果頁(測試選舉)
手機版投票流程
手機版投票流程