asc-notarization

asc-notarization

熱門

使用 xcodebuild 與 asc 來歸檔、匯出以及公證 macOS 應用程式。當你需要透過 Developer ID 簽署與 Apple 公證,將 macOS 應用程式發布至 App Store 以外的管道時使用。

948星標
50分支
更新於 2026/7/31
SKILL.md
唯讀
名稱
asc-notarization
描述

使用 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 憑證)。

修復損壞的信任設定

codesignxcodebuild 報錯出現 "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