asc-notarization

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

macOS Notarization

macOS 公证

Use this skill when you need to notarize a macOS app for distribution outside the App Store.
当你需要为非App Store渠道分发的macOS应用进行公证时,可使用本方法。

Preconditions

前置条件

  • Xcode installed and command line tools configured.
  • Auth is configured (
    asc auth login
    or
    ASC_*
    env vars).
  • A Developer ID Application certificate in the local keychain.
  • The app's Xcode project builds for macOS.
  • 已安装Xcode并配置好命令行工具。
  • 已完成身份验证配置(使用
    asc auth login
    ASC_*
    环境变量)。
  • 本地钥匙串中存在Developer ID Application证书。
  • 应用的Xcode项目可构建macOS版本。

Preflight: Verify Signing Identity

预检:验证签名身份

Before archiving, confirm a valid Developer ID Application identity exists:
bash
security find-identity -v -p codesigning | grep "Developer ID Application"
If no identity is found, create one at https://developer.apple.com/account/resources/certificates/add (the App Store Connect API does not support creating Developer ID certificates).
在归档前,确认存在有效的Developer ID Application身份:
bash
security find-identity -v -p codesigning | grep "Developer ID Application"
如果未找到该身份,请访问https://developer.apple.com/account/resources/certificates/add创建(App Store Connect API不支持创建Developer ID证书)。

Fix Broken Trust Settings

修复信任设置问题

If
codesign
or
xcodebuild
fails with "Invalid trust settings" or "errSecInternalComponent", the certificate may have custom trust overrides that break the chain:
bash
undefined
如果
codesign
xcodebuild
命令执行失败,提示“Invalid trust settings”或“errSecInternalComponent”,则该证书可能存在破坏信任链的自定义信任覆盖设置:
bash
undefined

Check for custom trust settings

检查自定义信任设置

security dump-trust-settings 2>&1 | grep -A1 "Developer ID"
security dump-trust-settings 2>&1 | grep -A1 "Developer ID"

If overrides exist, export the cert and remove them

如果存在覆盖设置,导出证书并移除它们

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
undefined
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
undefined

Verify Certificate Chain

验证证书链

After fixing trust settings, verify the chain is intact:
bash
codesign --deep --force --options runtime --sign "Developer ID Application: YOUR NAME (TEAM_ID)" /path/to/any.app 2>&1
The signing must show the chain: Developer ID Application → Developer ID Certification Authority → Apple Root CA.
修复信任设置后,验证证书链是否完整:
bash
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。

Step 1: Archive

步骤1:归档

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

Step 2: Export with Developer ID

步骤2:使用Developer ID导出

Create an ExportOptions plist for Developer ID distribution:
xml
<?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>
Export the archive:
bash
xcodebuild -exportArchive \
  -archivePath /tmp/YourApp.xcarchive \
  -exportPath /tmp/YourAppExport \
  -exportOptionsPlist ExportOptions.plist
This produces a
.app
bundle signed with Developer ID Application and a secure timestamp.
创建用于Developer ID分发的ExportOptions.plist文件:
xml
<?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>
导出归档文件:
bash
xcodebuild -exportArchive \
  -archivePath /tmp/YourApp.xcarchive \
  -exportPath /tmp/YourAppExport \
  -exportOptionsPlist ExportOptions.plist
此操作会生成一个经过Developer ID Application签名并带有安全时间戳的
.app
包。

Verify the Export

验证导出结果

bash
codesign -dvvv "/tmp/YourAppExport/YourApp.app" 2>&1 | grep -E "Authority|Timestamp"
Confirm:
  • Authority chain starts with "Developer ID Application"
  • A Timestamp is present
bash
codesign -dvvv "/tmp/YourAppExport/YourApp.app" 2>&1 | grep -E "Authority|Timestamp"
确认以下内容:
  • 信任链以“Developer ID Application”开头
  • 存在时间戳信息

Step 3: Create a ZIP for Notarization

步骤3:创建用于公证的ZIP包

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

Step 4: Submit for Notarization

步骤4:提交公证申请

Fire-and-forget

提交后无需等待

bash
asc notarization submit --file "/tmp/YourAppExport/YourApp.zip"
bash
asc notarization submit --file "/tmp/YourAppExport/YourApp.zip"

Wait for result

等待结果返回

bash
asc notarization submit --file "/tmp/YourAppExport/YourApp.zip" --wait
bash
asc notarization submit --file "/tmp/YourAppExport/YourApp.zip" --wait

Custom polling

自定义轮询

bash
asc notarization submit --file "/tmp/YourAppExport/YourApp.zip" --wait --poll-interval 30s --timeout 1h
bash
asc notarization submit --file "/tmp/YourAppExport/YourApp.zip" --wait --poll-interval 30s --timeout 1h

Step 5: Check Results

步骤5:查看公证结果

Status

查看状态

bash
asc notarization status --id "SUBMISSION_ID" --output table
bash
asc notarization status --id "SUBMISSION_ID" --output table

Developer Log (for failures)

开发者日志(用于排查失败问题)

bash
asc notarization log --id "SUBMISSION_ID"
Fetch the log URL to see detailed issues:
bash
curl -sL "LOG_URL" | python3 -m json.tool
bash
asc notarization log --id "SUBMISSION_ID"
获取日志URL查看详细问题:
bash
curl -sL "LOG_URL" | python3 -m json.tool

List Previous Submissions

查看历史提交记录

bash
asc notarization list --output table
asc notarization list --limit 5 --output table
bash
asc notarization list --output table
asc notarization list --limit 5 --output table

Step 6: Staple (Optional)

步骤6:绑定公证凭证(可选)

After notarization succeeds, staple the ticket so the app works offline:
bash
xcrun stapler staple "/tmp/YourAppExport/YourApp.app"
For DMG or PKG distribution, staple after creating the container:
bash
undefined
公证成功后,绑定公证凭证,确保应用可离线运行:
bash
xcrun stapler staple "/tmp/YourAppExport/YourApp.app"
如果以DMG或PKG格式分发,请在创建容器后再绑定凭证:
bash
undefined

Create DMG

创建DMG镜像

hdiutil create -volname "YourApp" -srcfolder "/tmp/YourAppExport/YourApp.app" -ov -format UDZO "/tmp/YourApp.dmg" xcrun stapler staple "/tmp/YourApp.dmg"
undefined
hdiutil create -volname "YourApp" -srcfolder "/tmp/YourAppExport/YourApp.app" -ov -format UDZO "/tmp/YourApp.dmg" xcrun stapler staple "/tmp/YourApp.dmg"
undefined

Supported File Formats

支持的文件格式

FormatUse Case
.zip
Simplest; zip a signed
.app
bundle
.dmg
Disk image for drag-and-drop install
.pkg
Installer package (requires Developer ID Installer certificate)
格式使用场景
.zip
最简单的方式;对已签名的
.app
包进行压缩
.dmg
用于拖放安装的磁盘镜像
.pkg
安装包(需要Developer ID Installer证书)

PKG Notarization

PKG包公证

To notarize
.pkg
files, you need a Developer ID Installer certificate (separate from Developer ID Application). This certificate type is not available through the App Store Connect API — create it at https://developer.apple.com/account/resources/certificates/add.
Sign the package:
bash
productsign --sign "Developer ID Installer: YOUR NAME (TEAM_ID)" unsigned.pkg signed.pkg
Then submit:
bash
asc notarization submit --file signed.pkg --wait
要对
.pkg
文件进行公证,你需要Developer ID Installer证书(与Developer ID Application证书是分开的)。该证书无法通过App Store Connect API创建,请访问https://developer.apple.com/account/resources/certificates/add创建。
对安装包进行签名:
bash
productsign --sign "Developer ID Installer: YOUR NAME (TEAM_ID)" unsigned.pkg signed.pkg
然后提交公证申请:
bash
asc notarization submit --file signed.pkg --wait

Troubleshooting

问题排查

"Invalid trust settings" during export

导出时提示“Invalid trust settings”

The Developer ID certificate has custom trust overrides. See the Preflight section above to remove them.
Developer ID证书存在自定义信任覆盖设置,请参考上方的预检部分进行移除。

"The binary is not signed with a valid Developer ID certificate"

“二进制文件未使用有效的Developer ID证书签名”

The app was signed with a Development or App Store certificate. Re-export with
method: developer-id
in ExportOptions.plist.
应用使用了Development或App Store证书进行签名,请在ExportOptions.plist中设置
method: developer-id
后重新导出。

"The signature does not include a secure timestamp"

“签名未包含安全时间戳”

Add
--timestamp
to manual
codesign
calls, or use
xcodebuild -exportArchive
which adds timestamps automatically.
手动调用
codesign
时添加
--timestamp
参数,或使用
xcodebuild -exportArchive
命令,该命令会自动添加时间戳。

Upload timeout for large files

大文件上传超时

Set a longer upload timeout:
bash
ASC_UPLOAD_TIMEOUT=5m asc notarization submit --file ./LargeApp.zip --wait
设置更长的上传超时时间:
bash
ASC_UPLOAD_TIMEOUT=5m asc notarization submit --file ./LargeApp.zip --wait

Notarization returns "Invalid" but signing looks correct

公证返回“Invalid”但签名看似正常

Fetch the developer log for specific issues:
bash
asc notarization log --id "SUBMISSION_ID"
Common causes: unsigned nested binaries, missing hardened runtime, embedded libraries without timestamps.
获取开发者日志查看具体问题:
bash
asc notarization log --id "SUBMISSION_ID"
常见原因:嵌套二进制文件未签名、缺少强化运行时配置、嵌入库未添加时间戳。

Notes

注意事项

  • The
    asc notarization
    commands use the Apple Notary API v2, not
    xcrun notarytool
    .
  • Authentication uses the same API key as other
    asc
    commands.
  • Files are uploaded directly to Apple's S3 bucket with streaming (no full-file buffering).
  • Files over 5 GB use multipart upload automatically.
  • Always use
    --help
    to verify flags:
    asc notarization submit --help
    .
  • asc notarization
    命令使用的是Apple Notary API v2,而非
    xcrun notarytool
  • 身份验证使用与其他
    asc
    命令相同的API密钥。
  • 文件通过流式传输直接上传至Apple的S3存储桶(无需全文件缓冲)。
  • 超过5GB的文件会自动使用分片上传。
  • 请始终使用
    --help
    参数查看可用选项:
    asc notarization submit --help