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 版本。

前置檢查:驗證簽署身分

在開始封存(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",可能是憑證設定了自訂的信任覆蓋(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