asc-notarization

asc-notarization

热门

使用 xcodebuild 和 asc 归档、导出并公证 macOS 应用。适用于需要使用 Developer ID 签名和 Apple 公证,将 macOS 应用打包分发至 App Store 之外的场景。

948Star
50Fork
更新于 2026/7/31
SKILL.md
只读
名称
asc-notarization
描述

使用 xcodebuild 和 asc 归档、导出并公证 macOS 应用。适用于需要使用 Developer ID 签名和 Apple 公证,将 macOS 应用打包分发至 App Store 之外的场景。

macOS 应用公证(Notarization)

当需要对 macOS 应用进行公证(Notarization)以便在 App Store 之外分发时,请使用此 Skill。

前提条件

  • 已安装 Xcode 且配置好命令行工具(command line tools)。
  • 已配置身份认证(通过 asc auth loginASC_* 环境变量)。
  • 本地 Keychain(钥匙串)中存在有效的 Developer ID Application 证书。
  • 应用的 Xcode 项目能够正常编译构建 macOS 版本。

预检:验证签名身份

在开始归档之前,请确认本地存在有效的 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" 错误,可能是证书被设置了自定义信任覆盖,导致信任链中断:

# 检查是否存在自定义信任设置
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。

第一步:归档(Archive)

xcodebuild archive \
  -scheme "YourMacScheme" \
  -configuration Release \
  -archivePath /tmp/YourApp.xcarchive \
  -destination "generic/platform=macOS"

第二步:使用 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 签名和安全时间戳的 .app 包。

验证导出结果

codesign -dvvv "/tmp/YourAppExport/YourApp.app" 2>&1 | grep -E "Authority|Timestamp"

确认以下要点:

  • 证书链(Authority)以 "Developer ID Application" 开头
  • 存在有效的安全时间戳(Timestamp)

第三步:打包成 ZIP 以供公证

ditto -c -k --keepParent "/tmp/YourAppExport/YourApp.app" "/tmp/YourAppExport/YourApp.zip"

第四步:提交公证

异步提交(无需等待)

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

第五步:查看公证结果

查看状态

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

第六步:钉合公证凭证(Staple,可选)

公证成功后,将公证凭证钉合(Staple)到应用中,以便应用在离线状态下也能正常运行:

xcrun stapler staple "/tmp/YourAppExport/YourApp.app"

如果是以 DMG 或 PKG 形式分发,请在生成容器镜像后再进行钉合:

# 生成 DMG 镜像
hdiutil create -volname "YourApp" -srcfolder "/tmp/YourAppExport/YourApp.app" -ov -format UDZO "/tmp/YourApp.dmg"
xcrun stapler staple "/tmp/YourApp.dmg"

支持的文件格式

格式 使用场景
.zip 最简单的方式;直接对已签名的 .app 包打包成 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"

常见原因:嵌套的二进制文件未签名、缺少 Hardened Runtime(硬化运行时)、嵌入的动态库缺少安全时间戳。

注意事项

  • asc notarization 相关命令基于 Apple Notary API v2,而非 xcrun notarytool
  • 身份认证复用 asc 其他命令相同的 API Key 凭证。
  • 文件直接流式上传至 Apple 的 S3 存储桶(不会在本地内存中进行全量缓存)。
  • 超过 5 GB 的大文件会自动采用分块并行上传(multipart upload)。
  • 随时可以使用 --help 检查相关命令行参数标志:asc notarization submit --help