用 Developer ID 自主分發意味著什麼
將 macOS 應用程式交付給使用者,大致有兩條路。一條是透過 Mac App Store (MAS),另一條是由開發者自行製作 .dmg(或 .app)檔案,讓使用者從網站或 GitHub 等地方下載的直接分發 (direct distribution)。
直接分發有明顯的優勢:不必等待 App Store 審核,沒有支付手續費,可以隨時以自己想要的方式發布更新。但相應地,原本由 App Store 代勞的事情——程式碼簽署、公證 (notarization)、自動更新——都需要開發者自行建置。
如果不建置這些,macOS 的安全機制 Gatekeeper 會阻止應用程式啟動。使用者第一次開啟應用程式時會看到類似「無法開啟此 App,因為它來自身份不明的開發者」的警告,大多數使用者就此放棄安裝。要讓應用程式像正規分發的應用程式那樣雙按即可開啟,就必須用 Developer ID 憑證簽署應用程式,並獲得 Apple 的公證。
本系列介紹的正是這套一次性準備流程。好消息是,這裡涉及的設定大多只需做一次,即可在所有後續發布中重複使用。
本系列將完成的內容
共三篇,逐步建置以下內容:
- (第 1 篇,本文) Developer ID Application 憑證 + 公證用憑據
- (第 2 篇) 用於 Sparkle 自動更新的 EdDSA 簽署金鑰
- (第 3 篇) 託管更新 Feed 的公開儲存庫 + 收尾建置設定
系列結束時,你應該已經準備好以下內容。現在先瀏覽一下清單,每篇逐一完成即可。
- macOS 鑰匙圈 (Keychain) 中的
Developer ID Application憑證 - 存儲在鑰匙圈中的公證用憑據設定檔
- 用於 Sparkle 更新簽署的 EdDSA 金鑰對(公開金鑰 + 私密金鑰)
- 私密金鑰備份到安全位置
- 用於託管更新 Feed (appcast) 的公開 GitHub 儲存庫 + GitHub Pages
- 建置設定檔 (
ExportOptions.plist) 與應用程式端設定
範例應用程式 — FocusTimer
本系列以虛構的 macOS 應用程式 FocusTimer(一款管理專注時間的簡單計時器應用程式)為例。指令和路徑中出現的 FocusTimer、Bundle Identifier com.example.FocusTimer、網域名稱 example.com、憑證名稱、Team ID 等均為範例值。實際操作時請替換為你自己的應用程式名稱和帳戶資訊。
本文基於 Xcode 26 和 Sparkle 2.x(自動更新框架,第 2 篇中會用到)編寫。Apple 時常調整介面佈局和選單位置,若按鈕名稱略有不同,整體流程不變。
前提條件 — 命令列工具
首先安裝建置和發布自動化所需的兩個命令列工具。前提是已安裝 macOS 套件管理器 Homebrew。
brew install gh create-dmg
gh— GitHub 官方 CLI,稍後用於建立 GitHub Release。create-dmg— 用於製作分發用.dmg磁碟映像檔的工具,同時產生引導使用者將應用程式拖入Applications資料夾的介面。
雖然現在還用不到,但發布自動化腳本通常會在開頭檢查這些工具是否存在,找不到就立即終止,因此提前安裝好。
第 1 步 — 確認 Apple Developer Program
要申請 Developer ID 憑證並對應用程式進行公證,需要 Apple Developer Program 會員資格。個人帳戶每年收費 $99。
如果已加入,只需確認狀態是否為活躍即可。
- 訪問 developer.apple.com/account
- 在 Membership details 部分確認狀態為 Active
- 在同一頁面記下你的 Team ID(範例中為
ABCDE12345),後續步驟中會反覆用到。
若尚未加入,會員資格審批通常需要約一天時間。審批完成前無法申請憑證,建議優先處理。
第 2 步 — 申請 Developer ID Application 憑證
Developer ID Application 憑證是對分發用 .app 和 .dmg 進行簽署時使用的憑證。macOS Gatekeeper 會將用此憑證簽署的應用程式識別為「已知開發者製作的應用程式」。
Apple 還有一種用於對
.pkg安裝套件簽署的 Developer ID Installer 憑證,兩者不同。本系列以.dmg方式分發,因此只涉及 Application 憑證。
申請流程
最簡單的方式是透過 Xcode 操作。
- 啟動 Xcode → 選單 Xcode → Settings… (
⌘,) - 選擇 Accounts 標籤 → 在左側清單中點按你的 Apple ID
- 點按右下角的 Manage Certificates… 按鈕
- 在新彈出的視窗左下角點按
+按鈕 - 從選單中選擇 Developer ID Application
- 一兩秒後新憑證出現在清單中,點按 Done
如此申請的憑證會自動儲存到 macOS 鑰匙圈 (Keychain) 中。憑證與對應的私密金鑰成對儲存,有了這把私密金鑰才能進行簽署。
確認申請結果
在終端機執行以下指令,確認憑證是否已正確安裝。
security find-identity -v -p codesigning | grep "Developer ID Application"
如果輸出如下一行,則表示成功。
1) A1B2C3D4E5F6... "Developer ID Application: Gildong Hong (ABCDE12345)"
引號內的字串是憑證的正式名稱。Gildong Hong 是註冊在 Apple 帳戶中的姓名,括號內的 ABCDE12345 是第 1 步記下的 Team ID。這個名稱在後續自動化程式碼簽署時會原樣使用,請再次核對。
憑證續期
Developer ID 憑證的有效期限為 5 年。臨近到期時,Xcode 的 Manage Certificates 清單中會顯示 Expired。屆時按照相同步驟重新申請新憑證即可。
好消息是,已用舊憑證簽署並分發的應用程式不會在憑證到期時立即失效。只有之後新建的建置才需要用新憑證簽署。因此無需過分擔心到期問題。
第 3 步 — 註冊用於公證的 App 專用密碼
什麼是公證 (notarization)
公證是在分發前將應用程式上傳至 Apple 伺服器進行惡意軟體掃描的流程。通過掃描後,Apple 會頒發「公證票據」,應用程式附帶此票據後,Gatekeeper 才會無警告地開啟應用程式。如果說簽署證明「誰製作了它」,那麼公證就是「Apple 已掃描過一次」的獨立證明流程。
公證提交使用 Apple 的 notarytool 指令,每次提交都會要求輸入 Apple ID 密碼。為避免每次手動輸入,需要建立一個 App 專用密碼 (App-Specific Password) 並提前存入鑰匙圈。
3-1. 申請 App 專用密碼
App 專用密碼是一種 16 碼密碼,用於替代主 Apple ID 密碼,僅供特定用途使用。
- 訪問 appleid.apple.com → 使用加入了 Apple Developer Program 的 Apple ID 登入(範例中為
[email protected]) - 登入與安全性 (Sign-In and Security) → 選擇 App 專用密碼 (App-Specific Passwords)
- 點按
+按鈕 → 輸入密碼名稱(如focustimer-notarize) - 點按 建立 (Create) → 再次輸入 Apple ID 密碼
- 螢幕上顯示
abcd-efgh-ijkl-mnop格式的 16 碼密碼。
關閉此頁面後將無法再次查看該密碼。 在進入下一步之前,請先將其複製到密碼管理工具等安全位置。
3-2. 存入 notarytool 設定檔
將申請到的密碼儲存為鑰匙圈設定檔。執行以下指令前,請將 --password 的值替換為剛才獲得的實際密碼。
xcrun notarytool store-credentials "focustimer-notarize" \
--apple-id "[email protected]" \
--team-id "ABCDE12345" \
--password "abcd-efgh-ijkl-mnop"
- 第一個參數
"focustimer-notarize"— 為此設定檔指定的名稱,之後公證時將透過此名稱載入憑據。 --apple-id— Apple Developer Program 帳戶的電子郵件--team-id— 第 1 步中的 Team ID--password— 3-1 中申請的 App 專用密碼
出現如下輸出即為成功。
Credentials saved to Keychain.
憑據已存入鑰匙圈,App 專用密碼的原始文字不再需要保留。(但若計劃在其他電腦上也進行建置,建議保存在密碼管理工具中以備用。)
3-3. 驗證
確認已儲存的設定檔是否實際可用。
xcrun notarytool history --keychain-profile "focustimer-notarize"
若出現 Successfully received submission history. 的訊息,則表示正常。其下的提交歷程可能為空(因為尚未公證過任何內容,這是正常的),也可能有之前的記錄。
關鍵陷阱 — Apple ID 與 GitHub 帳戶是不同的
這是首次設定直接分發時最容易卡住的地方。
- Apple Developer Program 帳戶 — 用於申請憑證和公證(範例:
[email protected]) - GitHub 帳戶 — 第 3 篇中用於託管更新檔案(範例:
[email protected])
兩者通常使用不同的電子郵件。特別注意:notarytool store-credentials 的 --apple-id 必須填寫 Apple Developer 帳戶電子郵件。若填寫 GitHub 帳戶電子郵件,認證會失敗,而且錯誤訊息不夠友善,難以找到原因。
若兩個帳戶的電子郵件容易混淆,建議記錄下哪個是 Apple 用、哪個是 GitHub 用。這一區別在本系列中會反覆出現。
第 1 篇小結
跟到這裡,你現在已經準備好以下內容:
- ✅ 發布自動化用命令列工具(
gh、create-dmg) - ✅ 活躍狀態的 Apple Developer Program 會員資格
- ✅ 存儲在鑰匙圈中的 Developer ID Application 憑證
- ✅ 存儲在鑰匙圈中的公證用憑據設定檔(
focustimer-notarize)
至此,簽署和公證應用程式的準備工作已完成。但幾乎沒有應用程式只發布一次就結束。你需要不斷推出修復錯誤、增加功能的新版本。如果是 App Store 應用程式,自動更新由 App Store 代勞;而直接分發則需要自行建置這一機制。
下一篇將為 macOS 應用程式事實上的標準自動更新框架 Sparkle 建立 EdDSA 簽署金鑰。這是獨立於憑證之外、專門用於驗證更新檔案的機制。