使用 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 版本。
前置檢查:驗證簽署身分
在開始封存(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",可能是憑證設定了自訂的信任覆蓋(trust overrides),導致信任鏈中斷:
# 檢查是否有自訂信任設定
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>
匯出封存檔:
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:提交公證
送出即完(非同步)
asc notarization submit --file "/tmp/YourAppExport/YourApp.zip"
等待公證結果
asc notarization submit --file "/tmp/YourAppExport/YourApp.zip" --wait
自訂輪詢參數
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"
取得日誌 URL 以查看詳細問題:
curl -sL "LOG_URL" | python3 -m json.tool
列出歷史提交紀錄
asc notarization list --output table
asc notarization list --limit 5 --output table
步驟 6:釘貼公證票證(Staple,選用)
公證成功後,將公證票證(ticket)釘貼至應用程式,確保其可在離線狀態下正常運作:
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 套件 |
.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 金鑰。 - 檔案會以串流(Streaming)方式直接上傳至 Apple 的 S3 儲存桶,無需將完整檔案暫存於記憶體或磁碟中。
- 超過 5 GB 的檔案會自動採用分段上傳(Multipart Upload)。
- 隨時可以使用
--help來確認參數選項:asc notarization submit --help。






