安全模型
執行期閘門實際檢查了什麼、為什麼「機器不對」與「檔案遭竄改」這兩種錯誤被刻意設計成看起來一樣,以及每個檔位誠實的能力邊界。
保護並不是一個「要嘛存在、要嘛不存在」的開關——而是插入到每個受保護模組裡的一項執行期檢查,該模組每次被 import 都會跑一次,完全離線,使用的加密材料永遠不會離開它所屬的裝置。
閘門檢查什麼
受保護的程式碼每次執行時,MagicLock 都會在本地依下列順序驗證:
- 授權是真的——它由你的帳號簽發,且簽章能通過驗證。
- 授權仍然有效——未過期,也未遭撤銷。
- 裝置相符——這正是該授權(或產物)所綁定的那台機器。
- 能力在允許範圍內——即將執行的操作,落在授權授予的範圍之內。
- 證明是新鮮的——一次性憑證排除了截取舊憑證並重放的可能性。
只要任何一個步驟失敗,你的受保護程式碼在執行前就會被擋下——不存在「部分放行」或「盡力而為」這種中間狀態。
為什麼「機器不對」與「檔案遭竄改」看起來一樣
VaultLockedError(見 API 參考)在兩種情況下都會被拋出:產物在錯誤的機器上被開啟,以及它的本地狀態遭到變更。這是刻意的設計:如果區分這兩種情況,就等於洩露了驗證失敗「原因」的資訊,而這正是探測弱點的攻擊者最想要得到的那種資訊。不論是哪一種情況,錯誤訊息都完全相同。
防竄改證據,而不只是偵測竄改
加密產物是經過驗證的,而不只是加密而已——只要翻轉一個位元組,驗證就會在解密開始之前失敗。不存在「部分解密一個被修改過的檔案供你檢視」這種情況;它只會直接拒絕執行。
每個檔位實際能抵擋什麼
務必看清楚你正在做的取捨:
- 便捷檔(
.pya)——能擋住隨手複製與隨手檢視原始碼。應用程式執行期間,解密後的位元碼必然存在於處理程序的記憶體中;一個足夠有動機、帶著除錯器並完全控制執行中處理程序的攻擊者,理論上可以把它擷取出來。這個檔位要解決的是「別讓複製變得毫不費力」,而不是對抗記憶體鑑識。 - 編譯強檔(
magiclock build)——完全不出貨明文 Python,授權檢查在建置時就被自動編織進每一個編譯後模組的控制流程,而不是集中在一處可以刪掉的共用檢查背後。它堵住了最簡單的繞過方式(「直接刪掉檢查」),把門檻從「閱讀原始碼」提高到「逐一模組逆向工程一個已編譯的二進位檔」。 - 裝置綁定——把解密與一個由本地硬體/作業系統識別碼衍生出的機器指紋綁在一起。它能抵擋機器之間的隨手複製;但它不是硬體安全元件的替代品,一個資源足夠充裕、完全控制裝置的攻擊者,理論上可能嘗試偽造這個指紋。
MagicLock 的設計目標,是讓複製、竄改與逆向工程的代價顯著提高——而不是宣稱任何純軟體保護,對一個擁有無限時間、完全控制硬體的攻擊者是無法攻破的。如果你的威脅模型需要防範這個等級的對手,那正是硬體層級保護要解決的問題。
簽章與金鑰
授權使用 Ed25519 簽章,並針對你的廠商金鑰進行驗證——撤銷清單也採用同一套簽章機制保護,因此一份過期或偽造的撤銷清單無法被重放回去「取消撤銷」。驗證用的公鑰內嵌在你交付的產物裡;用於簽章的私鑰永遠不會離開授權伺服器。
另請參閱
- 帳號與啟用——離線寬限窗口,以及撤銷會影響什麼、不會影響什麼。
- Python API 參考——每種失敗模式在你的程式碼中會拋出哪個例外。