軟體加密原理:為什麼數位簽章
換句話說,數位簽章不是萬靈丹,但它是整個軟體信任鏈中最基礎、也最容易被使用者忽略的一環。少了它,後面所有的防毒掃描、沙箱隔離、權限控管,都建立在一个「假設檔案來源可信」的脆弱前提上。
二、密碼學基礎:對稱式加密、非對稱式加密與雜湊函數
要聽懂數位簽章的原理,得先搞懂三種基礎工具:對稱式加密、非對稱式加密,以及雜湊函數。這三者經常被混為一談,但它們的角色完全不同。
對稱式加密:快速,但金鑰分配很麻煩
對稱式加密指的是「加密與解密使用同一把金鑰」。經典例子包括 AES、ChaCha20。它的優點是速度快、適合大量資料,你手機裡的訊息加密、硬碟加密、HTTPS 連線中的資料傳輸,底層幾乎都是對稱式加密。
但它有個致命缺點:金鑰怎麼安全地交給對方?如果雙方從未見面,要如何在公開的網路上協商出一把只有彼此知道的金鑰?這個問題在密碼學史上困擾了非常久,直到非對稱式加密出現才有了優雅的解法。
非對稱式加密:公鑰與私鑰的雙鑰匙設計
非對稱式加密(又稱公開金鑰密碼學)使用一對數學上相關、但無法從其中一個推導出另一個的金鑰:
常見的演算法包括 RSA(基于大數分解困難度)、ECDSA(基于橢圓曲線離散對數問題)、Ed25519(Edwards 曲線的高速變體)。RSA 的密鑰長度通常為 2048 或 4096 位元,橢圓曲線則只要 256 位元左右就能達到相近安全性,因此在新式系統中越來越常見。
這裡有個常見的誤解:很多人以為「非對稱加密比較安全,所以應該全部用它」。實際上非對稱加密的運算成本遠高於對稱加密,而且能加密的資料長度受限(例如 RSA-2048 最多只能加密約 245 位元組)。所以真實世界的協定(如 TLS)幾乎都是混搭使用:用非對稱加密協商出一把臨時對稱金鑰,後續大量資料再用對稱加密傳輸。
雜湊函數:數位簽章的「指紋」技術
雜湊函數(Hash Function)可以把任意長度的輸入,轉換成固定長度的輸出,這個輸出稱為「訊息摘要(Message Digest)」或「雜湊值」。好的密碼學雜湊函數具備三個特性:
單向性:從摘要無法反推原始內容。
抗碰撞性:很難找到兩個不同輸入產生相同摘要。
雪崩效應:輸入改動一個位元,輸出會有天翻地覆的變化。
目前主流的雜湊演算法是 SHA-256(SHA-2 家族)與 SHA-3。MD5 與 SHA-1 因為已被證實可產生碰撞,早已不該用於安全用途——這點很重要,後面談憑證時會再提到。
工具類型
使用的金鑰
主要用途
常見演算法
對稱式加密
同一把金鑰
大量資料加密
AES、ChaCha20
非對稱式加密
公鑰/私鑰
金鑰交換、少量資料加密
RSA、ECDH
雜湊函數
不使用金鑰
完整性檢查、摘要
SHA-256、SHA-3
數位簽章
私鑰簽、公鑰驗
身分認證、不可否認性
RSA-PSS、ECDSA、Ed25519
三、數位簽章的原理拆解:從簽章到驗章的完整流程
有了前面三個工具,我們終於可以拆解數位簽章的實際運作。請注意一個關鍵觀念:數位簽章並不是把整份檔案用私鑰加密。這個誤解非常普遍,但它會讓你完全誤解簽章的效能與用途。
為什麼是「先雜湊、再簽名」?
假設你要簽署一個 500 MB 的安裝檔。如果直接用私鑰對整個檔案做非對稱運算,會遇到兩個問題:第一,RSA 這類演算法一次能處理的資料量有嚴格上限;第二,非對稱運算速度慢,對 500 MB 資料簽章可能要花上好幾分鐘甚至更久。
所以實務上的做法是:
用發行者的私鑰對這個「摘要」進行簽章運算,產生簽章值。
把原始檔案與簽章值一起發佈。
驗證端則是反向操作:收到檔案後,自己重新計算一次 SHA-256 摘要;同時用發行者的公鑰對簽章值進行驗證運算,還原出當初被簽署的摘要;最後比對兩個摘要是否一致。一致,代表檔案自簽章之後從未被修改;不一致,代表檔案已被竄改,或者簽章根本是偽造的。
這個設計的巧妙之處在於:非對稱運算只用在 32 位元組的摘要上,成本極低;而完整性檢查則交給快速的雜湊函數處理。效能與安全兼顧。
數位簽章 vs 數位加密:方向相反的两件事
很多教學文章會說「用私鑰加密就是簽章、用公鑰加密就是保密」,這種說法雖然方便記憶,但並不完全精確,而且容易造成混淆。比較正確的理解是:
兩者的金鑰使用方向恰好相反,目的也完全不同。簽章不提供機密性——任何拿到公鑰的人都能驗證,也就意味著任何人都能看到被簽署的內容。如果你需要同時保密與認證,得兩者並用。
數位簽章提供的三項保證
一個正確實作的數位簽章,能為軟體發佈帶來三項密碼學保證:
反過來說,簽章不保證的事情也必須講清楚:它不保證軟體沒有漏洞、不保證軟體不含惡意行為、不保證程式碼品質。它只保證「這份檔案確實是某個持有特定私鑰的人所發佈,且內容自簽署後未被更動」。這個區別是後面談「迷思」時的關鍵。
四、憑證、CA 與信任鏈:簽章背後還有一層信任
到目前為止,我們假設「你已經拿到了發行者的公鑰」。但現實中,你要怎麼確認手上這把公鑰真的屬於微軟、屬於 Google、屬於你下載的那套軟體的公司?如果攻擊者在中間替你換掉公鑰,你驗證簽章時依然會「成功」——只是驗證的是攻擊者偽造的簽章。
解決這個問題的機制,就是公開金鑰基礎建設(PKI)與數位憑證(Digital Certificate)。
X.509 憑證:把公鑰與身分綁在一起
X.509 憑證本質上是一份經過簽署的數位文件,內容包含:憑證持有者的名稱、公鑰、有效期限、用途限制,以及簽發這張憑證的憑證機構(CA)的簽章。因為這份文件本身也被簽章了,所以任何人只要信任該 CA,就能透過驗證 CA 的簽章來確認憑證內容未被竄改。
換句話說,憑證解決了「公鑰怎麼安全地交到你手上」這個問題:不是靠 email 傳、不是靠網站公布,而是靠一個你已經信任的第三方背書。
根憑證、中介憑證與信任鏈
實務上,CA 不會直接用根憑證簽發所有終端憑證,而是建立階層結構:
驗證時,系統會沿著「終端憑證 → 中介憑證 → 根憑證」一路往上驗,確認每一層的簽章都正確、每一張憑證都在有效期內、用途符合、且沒有被吊销。這整條路徑就是所謂的憑證鏈(Certificate Chain)。只要鏈上任何一環出問題,整個驗證就會失敗。
憑證吊销:CRL 與 OCSP
憑證可能因為私鑰外洩、公司更名、裝置遺失等原因需要提前失效。這時 CA 會將該憑證列入憑證吊销清單(CRL),或透過 OCSP 協定提供即時查詢。作業系統在驗證軟體簽章時,通常也會一併檢查吊销狀態——這也是為什麼有些老舊軟體的簽章明明「看起來還在有效期內」,卻仍然驗證失敗。
五、軟體發行中的實際應用:四大平台的簽章機制
理論講完了,接下來看實作。不同作業系統對軟體簽章的要求與實作方式差異很大,理解這些差異,對判斷下載檔案是否可信非常有幫助。
Windows:Authenticode 與 SmartScreen
Windows 的程式碼簽章機制稱為 Authenticode,使用 X.509 憑證對 PE 格式的執行檔(.exe、.dll、.sys 等)簽章。使用者可以在檔案的「內容 → 數位簽章」頁籤看到簽署者名稱與時間戳。
值得注意的是憑證等級:一般組織驗證(OV)憑證與延伸驗證(EV)憑證。EV 憑證的審核流程更嚴格,過去曾能讓 SmartScreen 立即建立信譽,但微軟後來調整了政策,現在所有新簽章憑證都必須累積下載信譽,才能避免使用者看到「Windows 已保護您的電腦」的藍色警告。
此外,Windows 11 對核心模式驅動程式的要求越來越嚴,微軟的 WHQL / 驅動程式簽章政策,以及近年推動的 Windows Defender Application Control(WDAC),都讓「未簽章程式」在企業環境中幾乎無法執行。
macOS:Gatekeeper、公證與 codesign
蘋果的機制更為封閉但設計相當完整。macOS 應用程式使用 codesign 工具進行簽章,簽章內容涵蓋整個 App Bundle 的所有檔案。使用者可以用 codesign -dv --verbose=4 或 spctl -a -vv 指令檢查簽章與公證狀態。
自 macOS 10.15 Catalina 起,蘋果要求所有在官方通路外散佈的應用程式,除了開發者 ID 簽章外,還必須經過公證(Notarization):開發者把打包好的 App 上傳給蘋果的自動化系統掃描,確認沒有明顯惡意行為後,蘋果會頒發一張「公證票據(Notarization Ticket)」。Gatekeeper 在首次啟動時會檢查這張票據,沒有票據的 App 會被阻擋。
這套機制的好處是提高了惡意軟體的成本,缺點是開發者必須付年費、且對蘋果的審查政策有一定依賴。對使用者而言,看到「無法打開,因為無法驗證開發者」的訊息時,通常代表這個 App 沒有簽章或未經公證——這時就該提高警覺,而不是無腦按下「仍要打開」。
Linux:GPG 簽章與套件庫信任
Linux 世界的簽章文化歷史最悠久,也最分散。主流發行版的做法大致如下:
Release 檔案會以 GPG 簽章產生 InRelease 或 Release.gpg,系統的 apt-key(新版改用 /etc/apt/trusted.gpg.d/ 或 signed-by 機制)負責驗證。個別 .deb 套件本身的簽章檢查相對寬鬆,主要依賴雜湊值與套件庫層級的簽章。rpm --checksig 可以驗證。系統安裝時會比對 /etc/pki/rpm-gpg/ 下的公鑰。pacman-key 管理信任網路(Web of Trust)。Linux 使用者若從第三方 PPA、AUR 或官方網站下載 .deb / .rpm / .AppImage,務必自行比對官方公布的 SHA-256 雜湊值或 GPG 簽章。這也是為什麼多數專案會在官網放上 SHA256SUMS 與 SHA256SUMS.asc 兩個檔案。
行動裝置:APK 簽章與 App Store 機制
Android 的 APK 從第一代就要求簽章,但早期採用的是 v1(JAR Signing),只驗證個別檔案,有著名的「Janus 漏洞」可繞過。Android 7.0 引入 v2(APK Signature Scheme v2),對整個 APK 做完整性簽章;Android 9 引入 v3,支援金鑰輪替;Android 11 之後則有 v4 與增量簽章。
Google Play 另外推行 Play App Signing,讓 Google 代管開發者的簽章金鑰,開發者上傳的是「上傳金鑰」簽過的 App Bundle,再由 Google 用「應用程式簽章金鑰」重新簽章後發佈。這提高了金鑰安全性,但也讓開發者對 Google 的依賴加深。
iOS 則是另一套邏輯:App 必須由 Apple 的開發者憑證簽章,並經過 App Store 審查;企業內部散佈則使用企業憑證,但這也成為惡意軟體濫用的管道之一,蘋果近年已大幅收緊。
六、常見迷思與破解手法:有簽章就安全嗎?
談到這裡,必須潑一盆冷水。數位簽章是必要條件,卻不是充分條件。以下幾個迷思,是筆者在論壇上最常看到、也最需要澄清的。
迷思一:「有簽章就代表軟體安全」
錯。簽章只證明「這是某人發佈的、內容沒被改」,不證明「這個人寫的程式沒有惡意行為」。歷史上有太多案例是攻擊者取得了合法憑證,或買了便宜憑證,然後用它在惡意軟體上簽章。二〇一〇年代的 Stuxnet 使用了被盜的 Realtek 憑證;NotPetya 透過被入侵的 M.E.Doc 會計軟體更新機制散佈;二〇二二年的 3CX 供應鏈事件,攻擊者同樣是從合法簽章的更新檔下手。
更極端的例子是「簽章即服務」的黑市:某些憑證發行機構的審核流程鬆散,攻擊者可以用空殼公司申請到憑證,替惡意程式簽章,藉此繞過部分安全軟體的警告。
迷思二:「檔案簽章無效,一定是病毒」
也不一定。簽章驗證失敗的可能原因很多:憑證過期但未加時間戳、憑證被吊销、憑證鏈缺少中介憑證、系統的根憑證資料庫太舊、檔案在下載過程中被截斷、甚至只是壓縮軟體重新打包時破壞了簽章區塊。實務上,很多老牌免費軟體的簽章問題,是「憑證到期後沒更新」而不是「被植入木馬」。這並不代表可以鬆懈,但也不該一看到警告就斷定有毒。
迷思三:「時間戳不重要」
時間戳(Timestamp)其實是軟體簽章能否長期有效的關鍵。程式碼簽章憑證通常只有一到三年的效期,但軟體的壽命往往更長。如果沒有時間戳,憑證一過期,所有舊版軟體的簽章驗證都會失敗,使用者會被迫升級或面對大量警告。
加上時間戳後(遵循 RFC 3161 標準),簽章會附帶一個由時間戳權威機構(TSA)簽署的證明,記載「這個簽章在某個時間點確實存在」。如此一來,即使簽章憑證日後過期或被吊销,只要驗證時能證明簽章發生在有效期內,驗證仍然有效。這是為什麼專業的簽章流程一定會串接時間戳伺服器。
迷思四:「簽章被偷了也沒差,換一張就好」
事實正好相反。私鑰外洩是軟體發行者最嚴重的資安事件之一。攻擊者可以用你的名義簽署任何東西,並且讓它通過全世界數億台電腦的簽章驗證。修復流程包括:立即向 CA 申請吊销憑證、向微軟/蘋果回報以加入黑名單、發布安全公告、全面更換金鑰、稽核外洩期間的所有簽章紀錄。整個過程可能耗時數週,而且商譽損失難以估計。
這也是為什麼現代開發團隊會把簽章金鑰放在硬體安全模組(HSM)或雲端金鑰管理服務中,而不是放在工程師的筆電或 CI 環境變數裡。二〇二二年 NVIDIA 遭駭事件中,攻擊者竊取了程式碼簽章憑證,導致該公司必須緊急吊销並重新簽署多個驅動程式與工具。
七、一般使用者如何自我保護:實用檢查清單
看到這裡,你可能會想:「我又不是資安專家,怎麼可能每次下載都檢查這些?」確實,一般使用者不需要理解橢圓曲線數學,但以下幾個動作,可以在幾秒鐘內大幅降低風險。
檢查項目
怎麼做
出現異常時的處理
檔案的數位簽章
codesign -dv 或 spctl -a -vv沒有簽章或簽署者不明,先不要執行
簽署者名稱
核對是否與官方網站公布的公司名稱一致
名稱拼寫怪異、空殼公司名,提高警覺
官方雜湊值
certutil -hashfile(Windows)或 shasum -a 256(macOS / Linux)計算,與官網公布值比對不一致代表檔案被改過,立刻刪除
下載來源
聚合型下載站、Google 廣告導向頁面,避免使用
檔案大小與版本
與官網公布的檔案大小、版本號比對
明顯偏大或偏小,可能被重新打包
防毒與信譽服務
上傳到 VirusTotal 之類的多引擎掃描服務(注意:上傳即公開,機密檔案勿用)
多家引擎同時告警,直接放棄
另外有幾個行為習慣,比任何技術檢查都重要:
八、給軟體開發者的建議:把簽章當成一級公民
如果你是開發者,或是正在維護開源專案,以下幾點是實務上最容易出錯、也最值得投資的地方。
第一,金鑰保管要高於一切。簽章私鑰不該出現在原始碼控管、不該放在 CI 的環境變數明文裡、不該存在開發者的本機硬碟。比較好的做法是使用雲端 KMS(如 AWS KMS、Azure Key Vault、Google Cloud KMS)搭配簽章服務,或使用 HSM 與硬體金鑰(如 YubiKey)。權限採最小化原則,簽章動作要有稽核紀錄。
第二,一定要加時間戳。很多開發者只做了簽章卻忘了時間戳,導致憑證一過期,所有舊版本的驗證就全部失敗。串接 TSA 的成本很低,帶來的長期效益卻很高。
第三,把簽章納入 CI/CD 流程並自動化。手工簽章容易出錯,也容易在趕版時被略過。理想流程是:建置 → 測試 → 自動雜湊 → 自動簽章 → 自動上傳 → 公布雜湊值與簽章檔。整個過程可重現、可稽核。
第四,公布可驗證的雜湊值與簽章檔。即使你已經替安裝檔簽章,仍建議額外提供 SHA256SUMS 與其 GPG 簽章,讓使用者可以用獨立管道驗證。這是開源社群長期以來的良好慣例。
第五,建立吊销與事件應變計畫。先想好「如果私鑰外洩,我們多久能吊销、多久能重新簽章、怎麼通知使用者」的流程。平時演練一次,遠比事發時手忙腳亂好。
九、結語:簽章是信任的起點,不是終點
回到我們開頭的問題:為什麼數位簽章這麼重要?因為在一個任何位元都能被完美複製、任何檔案都可能被中途替換的數位世界裡,簽章是唯一能讓「來源」與「完整性」這兩個概念在數學上站得住腳的機制。它讓作業系統能在你雙擊檔案之前,替你先問一句:「這是誰做的?有沒有被動過?」
但我們也必須清楚它的邊界。簽章不保證軟體沒有漏洞、不保證開發者沒有惡意、不保證憑證沒有被盜用。它只是把「完全未知」變成「有名字、有紀錄、可追溯」——而這個轉變,正是現代軟體生態得以運作的基礎。從 Windows 的 Authenticode、macOS 的公證機制、Linux 的 GPG 套件庫,到 Android 與 iOS 的應用程式簽章,背後都是同一套密碼學原理的不同實作。
對一般使用者而言,最實際的行動是:養成檢查簽章的習慣、只從官方管道下載、拒絕關閉系統保護。對開發者而言,則是把金鑰保管、時間戳、自動化簽章流程當成產品品質的一部分,而不是交差了事的行政步驟。
下次當你在「雅寶社區 · 頂客論壇」看到有人分享軟體時,不妨多問一句:「這個檔案有數位簽章嗎?簽署者是誰?」這個簡單的動作,可能就是你與一次資安事件之間的距離。數位信任不是天生的,它是由一層又一層的密碼學機制、以及每一個願意多檢查一次的使用者,共同堆疊出來的。