使用 xcodebuild 與 asc 來歸檔、匯出以及公證 macOS 應用程式。當你需要透過 Developer ID 簽署與 Apple 公證,將 macOS 應用程式發布至 App Store 以外的管道時使用。
macOS 應用程式公證
當你需要公證 macOS 應用程式以在 App Store 以外的管道發布時,請使用此 Skill。
前置條件
- 已安裝 Xcode 並已設定 Command Line Tools。
- 已完成身份驗證設定(執行
asc auth login或設定ASC_*環境變數)。 - 本地 Keychain(鑰匙圈)中已存在有效的 Developer ID Application 憑證。
- 該應用程式的 Xcode 專案可正常針對 macOS 進行建置(Build)。
行前檢查:驗證簽署身份
在進行歸檔(Archive)之前,請先確認本地存在有效的 Developer ID Application 身份:
security find-identity -v -p codesigning | grep "Developer ID Application"
如果未找到任何身份,請至 https://developer.apple.com/account/resources/certificates/add 建立一個(App Store Connect API 目前不支援建立 Developer ID 憑證)。
修復損壞的信任設定
若 codesign 或 xcodebuild 報錯出現 "Invalid trust settings" 或 "errSecInternalComponent",可能是憑證包含了自訂的信任覆寫,進而破壞了憑證鏈(Certificate Chain):
# 檢查是否有自訂信任設定
security dump-trust-settings 2>&1 | grep -A1 "Developer ID"
# 如果存在覆寫,請匯出憑證並將其移除
security find-certificate -c "Developer ID Application" -p ~/Library/Keychains/login.keychain-db > /tmp/devid-cert.pem
security remove-trusted-cert /tmp/devid-cert.pem
驗證憑證鏈
修復信任設定後,請確認憑證鏈是否完整無損:
codesign --deep --force --options runtime --sign "Developer ID Application: YOUR NAME (TEAM_ID)" /path/to/any.app 2>&1
簽署資訊必須完整顯示以下憑證鏈:Developer ID Application → Developer ID Certification Authority → Apple Root CA。
步驟 1:歸檔(Archive)
xcodebuild archive \
-scheme "YourMacScheme" \
-configuration Release \
-archivePath /tmp/YourApp.xcarchive \
-destination "generic/platform=macOS"
步驟 2:使用 Developer ID 匯出
建立用於 Developer ID 發布的 ExportOptions plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>developer-id</string>
<key>signingStyle</key>
<string>automatic</string>
<key>teamID</key>
<string>YOUR_TEAM_ID</string>
</dict>
</plist>
匯出 Archive:
xcodebuild -exportArchive \
-archivePath /tmp/YourApp.xcarchive \
-exportPath /tmp/YourAppExport \
-exportOptionsPlist ExportOptions.plist
執行後會產生一個已透過 Developer ID Application 簽署並附帶安全時間戳記(Secure Timestamp)的 .app Bundle。
驗證匯出結果
codesign -dvvv "/tmp/YourAppExport/YourApp.app" 2>&1 | grep -E "Authority|Timestamp"
請確認:
- Authority 憑證鏈開頭為 "Developer ID Application"
- 存在 Timestamp(時間戳記)
步驟 3:建立用於公證的 ZIP 檔
ditto -c -k --keepParent "/tmp/YourAppExport/YourApp.app" "/tmp/YourAppExport/YourApp.zip"
步驟 4:提交公證
異步提交(Fire-and-forget)
asc notarization submit --file "/tmp/YourAppExport/YourApp.zip"
等待公證結果
asc notarization submit --file "/tmp/YourAppExport/YourApp.zip" --wait
自訂輪詢(Polling)
asc notarization submit --file "/tmp/YourAppExport/YourApp.zip" --wait --poll-interval 30s --timeout 1h
步驟 5:檢查結果
公證狀態
asc notarization status --id "SUBMISSION_ID" --output table
開發者日誌(用於排查失敗原因)
asc notarization log --id "SUBMISSION_ID"
取得 Log URL 以檢視詳細問題資訊:
curl -sL "LOG_URL" | python3 -m json.tool
列出過往的提交紀錄
asc notarization list --output table
asc notarization list --limit 5 --output table
步驟 6:裝釘票證(Staple,選用)
公證成功後,將公證票證(Ticket)裝釘(Staple)至應用程式,讓應用程式能在離線狀態下順利執行:
xcrun stapler staple "/tmp/YourAppExport/YourApp.app"
若使用 DMG 或 PKG 格式發布,請在建立容器(Container)檔案後進行裝釘:
# 建立 DMG
hdiutil create -volname "YourApp" -srcfolder "/tmp/YourAppExport/YourApp.app" -ov -format UDZO "/tmp/YourApp.dmg"
xcrun stapler staple "/tmp/YourApp.dmg"
支援的檔案格式
| 格式 | 使用場景 |
|---|---|
.zip |
最簡單;將已簽署的 .app Bundle 壓縮為 ZIP 檔 |
.dmg |
磁碟影像檔,方便使用者拖曳安裝 |
.pkg |
安裝套件(需使用 Developer ID Installer 憑證) |
PKG 檔公證
若要公證 .pkg 檔案,你需要 Developer ID Installer 憑證(此憑證獨立於 Developer ID Application)。此類型的憑證無法透過 App Store Connect API 建立,請至 https://developer.apple.com/account/resources/certificates/add 手動新增。
為套件進行簽署:
productsign --sign "Developer ID Installer: YOUR NAME (TEAM_ID)" unsigned.pkg signed.pkg
接著提交公證:
asc notarization submit --file signed.pkg --wait
常見問題與疑難排解
匯出時出現 "Invalid trust settings"
Developer ID 憑證中包含自訂的信任覆寫設定。請參考前述「行前檢查」小節將其移除。
出現 "The binary is not signed with a valid Developer ID certificate"
應用程式使用了 Development 或 App Store 憑證進行簽署。請在 ExportOptions.plist 中確認 method 設定為 developer-id 並重新匯出。
出現 "The signature does not include a secure timestamp"
若使用手動 codesign 指令,請加上 --timestamp 參數;或改用 xcodebuild -exportArchive,它會自動加入安全時間戳記。
大型檔案上傳逾時
設定較長的上傳逾時時間:
ASC_UPLOAD_TIMEOUT=5m asc notarization submit --file ./LargeApp.zip --wait
公證結果顯示 "Invalid",但簽署狀態看起來無誤
擷取開發者日誌以檢視具體錯誤原因:
asc notarization log --id "SUBMISSION_ID"
常見原因包括:巢狀二進位檔(Nested binaries)未簽署、未啟用強化執行階段(Hardened Runtime),或內嵌的函式庫缺乏時間戳記。
注意事項
asc notarization指令底層使用的是 Apple Notary API v2,而非xcrun notarytool。- 身份驗證與其他
asc指令共用相同的 API Key。 - 檔案會以串流(Streaming)方式直接上傳至 Apple 的 S3 儲存桶(無需先緩衝完整檔案)。
- 超過 5 GB 的檔案會自動採用分段上傳(Multipart upload)。
- 隨時可以使用
--help參數來確認可用 Flag:例如asc notarization submit --help。






