PlainApp 安全性深度剖析

PlainApp 如何在本地 Wi-Fi 上保護您的資料——附開源程式碼佐證。

為什麼本地網路安全很重要?

當您使用應用程式從電腦瀏覽器管理 Android 手機時,您的簡訊、照片、聯絡人和檔案都會透過 Wi-Fi 網路傳輸。大多數應用程式會以可讀的明文傳送這些資料。同一網路上的任何人都能看到。

您可能會想:「這是我家的 Wi-Fi,誰會偷看?」但請考慮:

  • 公共 Wi-Fi — 咖啡廳、機場、飯店——附近任何人都能擷取流量
  • 共用網路 — 室友、訪客,或被入侵的物聯網裝置
  • 路由器漏洞 — 過時的韌體存在已知的安全漏洞

如果應用程式透過 HTTP 以明文傳送您的簡訊,任何人只要使用 Wireshark 等免費工具就能讀取。這不是理論——實際操作極為容易。

大多數手機管理應用程式正是這樣做的。在使用它們的網頁介面時,打開 Chrome DevTools(F12 → Network 分頁),您就能以純 JSON 格式讀取每個 API 呼叫——簡訊內容、檔案路徑、聯絡人姓名,一覽無遺。

PlainApp 有何不同

PlainApp 採用多層加密與驗證機制。以下用淺顯的語言說明每一層的作用。

Security Architecture Comparison
1

GraphQL API——只請求您需要的資料

大多數應用程式使用舊式 REST API:一個資源對應一個 URL,不管您是否需要都會回傳所有資料。PlainApp 使用 GraphQL——一種現代化的方式,瀏覽器只請求確切需要的資料,不多不少。

為什麼這很重要:

  • 減少資料暴露 — 如果您只需要檔案名稱,那就只傳送檔案名稱
  • 單一端點 — 只有一個 /graphql URL 而非數十個,減少了攻擊面
  • 逐查詢權限 — 每個查詢都會檢查自己的權限(例如,讀取簡訊需要 READ_SMS 權限,即使您已經登入)
2

加密 API 呼叫(XChaCha20-Poly1305)

這是 PlainApp 與大多數競爭對手之間最大的差異。

每一個 API 請求和回應——包括 HTTP 和 WebSocket 流量——都使用 XChaCha20-Poly1305 加密,HTTP 和 HTTPS 模式均如此。這是 WireGuard VPN、Cloudflare 和 Google Tink 都在使用的現代 AEAD 加密演算法。

簡單來說:

  1. 1您的瀏覽器建立一個請求(例如「顯示我的簡訊」)
  2. 2附加一個時間戳記和隨機 nonce,用於防重放保護
  3. 3用 XChaCha20-Poly1305 將整個請求體加密成不可讀的二進位資料
  4. 4加密後的二進位資料直接在網路上傳輸——不轉 base64,不包 JSON,純二進位
  5. 5只有您的手機能解密和驗證

即使有人攔截了流量,他們看到的只是無意義的二進位資料——而不是可讀的 JSON。

Encrypted API Flow

關於加密技術:

  • 256 位元金鑰(強度極高)
  • 192 位元 nonce(防止某些影響其他加密演算法的攻擊類型)
  • 內建竄改偵測——如果任何人在傳輸中修改資料,解密將會失敗
  • Android 端:由 Google Tink 驅動
  • Web 端:由 @noble/ciphers 驅動(一個經過良好審計的 JavaScript 加密函式庫)
3

數位簽章(Ed25519)——裝置間通訊

當兩台 PlainApp 裝置互相通訊時(例如手機對手機聊天),僅加密還不夠——每台裝置需要驗證訊息確實來自對方,而非偽造的。

時間戳記

接收端裝置使用發送方的公鑰驗證簽章,並拒絕時間戳記超過 5 分鐘的請求。這同時防止了偽造和重放攻擊。

4

安全裝置配對(ECDH 金鑰交換)

當兩台 PlainApp 裝置互相配對時(例如兩支手機),它們需要一組共用加密金鑰。但透過網路傳送金鑰就失去了意義。

PlainApp 使用 ECDH(Elliptic Curve Diffie-Hellman)金鑰交換來解決這個問題——這與 TLS、Apple 的 Secure Enclave 和 WebAuthn 使用的是相同的數學原理:

  1. 1每台裝置產生一組金鑰對(公鑰 + 私鑰)
  2. 2它們只交換各自的公鑰
  3. 3每台裝置將自己的私鑰與對方的公鑰結合
  4. 4雙方得到相同的共享密鑰——而密鑰從未在網路上傳輸
ECDH Pairing Flow
5

加密 URL——隱藏檔案路徑

這是大多數人不會注意到的細節:URL 路徑也會洩漏資訊。

當您下載檔案時,URL 會告訴伺服器您想要哪個檔案。在許多應用程式中,URL 看起來像這樣:

/fs?path=/sdcard/DCIM/Camera/photo_2024.jpg

任何監聽流量的人(或查看瀏覽器歷史紀錄的人)都能準確看到您存取了哪個檔案,以及您手機的資料夾結構。

PlainApp 會加密 URL 中的檔案路徑:

/fs?id=AxK9f2mQ7vR3xP8nWz...

id 參數是使用 XChaCha20-Poly1305 加密的檔案路徑,加密金鑰稱為 URL Token。預設情況下,這個金鑰是永久性的,即使重新啟動 App 也不會改變,因此分享過的連結始終有效。沒有金鑰,任何人都無法猜測真實路徑、列舉您的檔案,或偽造下載 URL。

URL Encryption Comparison
6

HTTPS 搭配自簽憑證

PlainApp 在您的手機上產生自簽 TLS 憑證。這會建立一條加密的 HTTPS 通道——與銀行和網站使用的技術相同。

憑證使用:

  • ECDSA 搭配 P-256 曲線(與主要網站相同)
  • SHA256 簽章
  • 儲存在應用程式的私有目錄中

結合應用層的 XChaCha20 加密,為您提供兩層獨立的加密保護。破解其中一層,若不同時破解另一層,仍無法取得資料。

7

登入保護

PlainApp 限制登入嘗試次數,以防止密碼暴力破解:

  • 每個 IP 位址每 60 秒最多 5 次嘗試
  • 超過後,連線將被拒絕
  • 過期的速率限制紀錄會自動清除

HTTP 與 HTTPS:一段誠實的說明

PlainApp 同時提供 HTTP 和 HTTPS 模式。以下是它們的真實差異:

HTTP 模式HTTPS 模式
檔案路徑 URL已加密(XChaCha20)已加密(XChaCha20)
API 呼叫已加密(XChaCha20)已加密(XChaCha20 + TLS)
檔案下載傳輸中未加密由 TLS 加密
適合誰初學者(無瀏覽器 SSL 警告)注重隱私的使用者

兩種模式都使用 XChaCha20-Poly1305 加密 API 呼叫——無論使用 HTTP 或 HTTPS,您的簡訊、聯絡人和其他資料始終是加密的。

HTTP 模式存在的原因是自簽憑證會觸發瀏覽器警告(「您的連線不安全」)。對於技術背景較少的使用者,這個警告令人困惑且不安。HTTP 避免了這個問題。

然而,HTTP 模式不會加密檔案傳輸。如果您在共用或公共網路上,請務必使用 HTTPS。

建議:盡可能使用 HTTPS。接受瀏覽器的自簽憑證警告——對於本地網路應用程式來說,這是正常且預期的。

8

供應鏈安全——更少的相依套件,更低的風險

一個許多使用者不會想到的安全威脅:供應鏈攻擊。當應用程式使用數百個第三方函式庫時,其中任何一個都可能被入侵——注入惡意程式碼來竊取資料、挖掘加密貨幣,或開啟後門。

這在 JavaScript 生態系統中尤其危險。近年來,event-stream、ua-parser-js 和 colors 等熱門 npm 套件被劫持,將惡意程式碼注入數百萬個專案。如果手機管理應用程式的網頁介面引入了數百個 JS 套件,每一個都是潛在的攻擊媒介。

PlainApp 採取刻意的做法:盡可能減少相依套件,在合理的情況下自行撰寫程式碼。

Android 應用程式(plain-app)

  • 不使用依賴注入框架(沒有 Hilt,沒有 Dagger)——使用簡單的 singleton
  • 加密僅由 3 個知名函式庫處理:Google Tink、Bouncy Castle 和內建的 Java Cryptography Extension
  • 伺服器執行於 Ktor(JetBrains 官方的 Kotlin 框架)——不使用冷門的第三方伺服器函式庫

網頁介面(plain-desktop)

僅有 28 個執行時相依套件——遠少於一般網頁應用程式。數項通常需要 npm 套件的功能都是從零開始建構:

功能一般應用程式PlainApp
通知音效howler.js / tone.js自製 Web Audio API 合成器
UUID 產生uuid npm 套件手寫的 RFC 4122 實作
檔案上傳uppy / axios自製分塊上傳與佇列
WebRTC 視訊Twilio / Daily.co SDK手寫的 PeerConnection 程式碼
HTTP 客戶端axios / ky原生瀏覽器 fetch

Web 端的加密使用 @noble/ciphers——一個經過良好審計、零相依的 JavaScript 加密函式庫——而非引入龐大臃腫的替代方案。

為什麼這很重要

您加入的每個相依套件都是您無法控制的程式碼。PlainApp 的做法意味著:

  • 惡意程式碼更難藏身
  • 更小的攻擊面
  • 更容易審計(整個程式碼庫是開源的)
  • 不會因為被棄用或劫持的 npm 套件而面臨風險

許多競爭對手的常見問題

這裡不針對特定應用程式。而是關於這個類別中的常見模式:

安全層面PlainApp競爭對手常見做法
API 流量已加密(XChaCha20),HTTP 和 HTTPS 皆然透過 HTTP 傳送純 JSON
WebSocket 流量加密二進位幀(XChaCha20)明文 JSON 或不使用 WebSocket
認證 Token 處理用作加密金鑰,從不放在請求標頭中放在 HTTP 請求標頭中(容易洩露)
檔案 URL加密的路徑 ID暴露明文路徑
金鑰交換ECDH(P-256)
請求簽章Ed25519(僅裝置間通訊)
防重放保護30 秒 + nonce(Web);5 分鐘 + 簽章(裝置間)
登入保護頻率限制 + 雙重確認無限制
資料路由100% 本地,無雲端部分透過雲端路由
相依套件最少量、知名函式庫數百個 npm 套件
原始碼開源(GPL-3.0)大多為閉源

最簡單的檢查方式:在使用應用程式時打開 Chrome DevTools(F12)→ Network 分頁。如果您能以 JSON 格式讀取 API 回應,那麼該應用程式沒有加密。

親自驗證

PlainApp 完全開源。本文中的每項聲明都可以在程式碼中驗證。

github.com/plainhub/plain-app (GPL-3.0)
可驗證的發佈完整性

自動化、可追溯且抗竄改的發佈流程

所有安裝套件都由 GitHub 與 F-Droid 基礎設施自動建置。建置流程可追溯、安全,且不留人工建置介入痕跡。PlainApp 是少數同時提供可驗證建置(SLSA)與 VirusTotal 掃描發佈的 Android 應用之一。

GitHub 與 F-Droid 自動建置

發佈產物由 CI 流程生成,而非本地手動打包。每個產物都可追溯到原始碼提交與可重現建置流程。

SLSA Provenance(第 3 級)+ VirusTotal 掃描

每次發佈都包含 SLSA provenance 證明與 VirusTotal 掃描結果,讓供應鏈可稽核,並幫助使用者在安裝前驗證完整性。

常見問題

使用 HTTP 模式時,PlainApp 真的有加密嗎?

是的。所有 API 呼叫(簡訊、聯絡人、檔案列表等)在 HTTP 和 HTTPS 模式下都使用 XChaCha20-Poly1305 加密。HTTP 模式僅檔案下載未加密。若要完整保護,請使用 HTTPS。

為什麼我的瀏覽器顯示安全警告?

PlainApp 使用自簽 TLS 憑證進行加密。由於它不是由公共憑證授權機構核發的,您的瀏覽器會顯示警告。對於本地網路應用程式來說,這是正常且預期的。點選「進階」然後「繼續」即可。

同一 Wi-Fi 上的人能看到我的資料嗎?

使用 PlainApp 時,不能。API 呼叫使用 XChaCha20-Poly1305 加密,在 HTTPS 模式下檔案傳輸也由 TLS 加密。使用大多數競爭對手的應用程式時,可以——它們的 API 呼叫以純文字 JSON 傳送。

PlainApp 與 VPN 相比如何?

VPN 加密的是您的裝置與 VPN 伺服器之間的流量。PlainApp 加密的是本地網路上手機與瀏覽器之間的流量。兩者用途不同——PlainApp 保護本地裝置管理,而 VPN 保護網際網路流量。

程式碼真的是開源的嗎?

是的。PlainApp 採用 GPL-3.0 授權。完整原始碼可在 github.com/plainhub/plain-app 取得。您可以檢視每個加密實作、從原始碼建構,或做出貢獻。

收回對手機的控制權。

無雲端中間商。沒有月費。只需您的手機和瀏覽器。