macOS App 签名与公证流程详解及一键自动化

8 阅读3分钟

一、签名证书申请

  •   注册 Apple Developer Program(年费 $99),⚠️务必登录账号所有人的 Apple 账号,才能操作申请这个证书。 image.png
  •    在 Apple Developer 开发证书申请后台,创建以下证书:
  •   Developer ID Application:用于签名应用。
  •   Developer ID Installer:用于签名安装包。
  •   macOS  App 证书 和  iOS App 开发是两套证书,有些证书名字很相似,注意做好区分。
  •   下载并安装相关证书,⚠️****证书信任采用默认设置,信任等级要保持一致。 image.png

二、签名前的准备工作

在 macOS 中,应用的代码签名和打包结构有严格要求,不正确的库放置位置会导致签名验证失败或运行时崩溃。以下是苹果对 macOS 应用打包结构的要求及解决方案:

1.确保应用结构符合苹果的 macOS 签名规范

macOS 应用 .app 包格式(本质是目录),标准结构如下:

YourApp.app/
├── Contents/
│   ├── Info.plist               # 应用元数据(必选)
│   ├── PkgInfo                  # 包类型信息(可选)
│   ├── MacOS/                   # 可执行文件目录
│   │   └── YourApp              # 主程序(必选)
│   ├── Resources/               # 资源文件(图标、nib 等)
│   ├── Frameworks/              # 动态框架目录(存放 .framework)
│   │   ├── Framework1.framework
│   │   └── Framework2.framework
│   └── Libraries/               # 动态库目录(存放 .dylib,较少使用)
│       └── libYourLibrary.dylib
└── _CodeSignature/              # 签名信息目录(由 codesign 自动生成)
    └── CodeResources

2.关键目录的作用

2.1  Frameworks/

  •   存放应用依赖的动态框架(.framework),这些框架会被应用动态加载。
  •   签名要求:框架必须单独签名,且其内部的二进制文件、资源文件也需递归签名。

2.2  Libraries/

  •   存放独立的动态库(.dylib),但苹果推荐优先使用 .framework 格式。
  •   注意:若使用 .dylib,需确保路径正确配置(如 @rpath)。

2.3  MacOS/

  •   主程序可执行文件必须位于此目录,否则系统无法找到入口点。

3.检查 YourApp.app 的 Info.plist 配置情况

其中必须包含以下关键字段:

CFBundleName   YourApp
CFBundleExecutable      YourApp
CFBundlePackageType  APP
CFBundleIdentifier    com.yourcompany.aippt

4.检查库依赖

  •   使用 otool -L 查看依赖库
otool -L YourApp.app/Contents/MacOS/YourApp

可以列出可执行文件依赖的所有库及其路径。检查输出中是否存在指向 /usr/lib/usr/local/lib、或其他非应用目录的路径。如果有,说明有库没有正确包含在应用包中。 ⚠️注意:这里只是初步扫描,并不是很准确,是否引用三方库,需要代码确认。

  •   检查嵌入框架和插件:对应用包内的每个可执行文件(如 Contents/Frameworks 和 Contents/PlugIns 中的 .dylib/.so/*.node 等),同样使用 otool -L 检查。例如:
otool -L YourApp.app/Contents/Frameworks/*.dylib

确认所有依赖都指向包内路径(通常以 @rpath@loader_path 或 @executable_path 开头)并且实际存在于应用包中。

5.检查网络配置,尽量关闭VPN,代理等

因代码签名时,系统会向苹果的时间戳服务器(timestamp.apple.com)请求时间戳,用于验证签名的有效性和时间。可能被防火墙、代理或网络环境拦截,无法访问苹果的时间戳服务器。

三、签名流程—脚本自动化

创建一个签名管理的文件夹MacSign,将【待签名.app】文件放进去该目录。 在MacSign目录下,通过文本编辑器,创建名为 sign.command文件:

#!/bin/bash
printf "\033c"
{ set +e; unset SHELL_SESSION_HISTORY; } >/dev/null 2>&1
# ===================== 配置 =============================
CERT_NAME="Developer ID Application: Shenzhen Pixel Bloom Technology Co., Ltd. (7UXDYFGRA9)"
APPLE_ID="wyk125@163.com"
TEAM_ID="xxxxxxxxxx"
NOTARY_PASSWORD="xxxx-xxxx-xxxx-xxxx"
APP_DIR="$HOME/MacSign"
INPUT_APP="待签名.app"
OUTPUT_DMG="签名完成.dmg"
# =======================================================
cd "$APP_DIR" || exit 1
# 主界面
echo "=========================================================="
echo "🚀 macOS App 签名与公证一键自动化"
echo "=========================================================="
echo "📦 输入:${INPUT_APP}"
echo "📀 输出:${OUTPUT_DMG}"
echo "=========================================================="

echo -n -e "\n1️⃣  正在给 APP 签名..."
codesign --force --deep --options runtime --sign "$CERT_NAME" "$INPUT_APP" >/dev/null 2>&1 && echo "✅"

echo -n "2️⃣  验证签名有效性..."
codesign --verify --deep --strict "$INPUT_APP" >/dev/null 2>&1 && echo "✅"

echo -n "3️⃣  生成 DMG 安装包..."
hdiutil create -volname "签名完成" -srcfolder "$INPUT_APP" -ov -format UDZO "$OUTPUT_DMG" >/dev/null 2>&1 && echo "✅"

echo -n "4️⃣  给 DMG 签名..."
codesign --sign "$CERT_NAME" "$OUTPUT_DMG" >/dev/null 2>&1 && echo "✅"

# 5️⃣ 公证 
echo -e "\n5️⃣  提交苹果公证(请等待)..."
xcrun notarytool submit "$OUTPUT_DMG" --apple-id "$APPLE_ID" --team-id "$TEAM_ID" --password "$NOTARY_PASSWORD" --wait 2>&1 \
| sed 's/and initiating connection/\nand initiating connection/'
# 公证结果
if [ $? -eq 0 ]; then echo -e "✅ 公证成功"; else echo -e "❌ 公证失败"; sleep 1; fi

# 6️⃣ 绑定凭证
echo -n -e "\n6️⃣  绑定公证凭证..."
xcrun stapler staple "$OUTPUT_DMG" >/dev/null 2>&1 && echo "✅"

# 完成提示
echo -e "\n=========================================================="
echo " ✅ 全部操作完成!"
echo " 📀 成品文件:${APP_DIR}/${OUTPUT_DMG}"
echo "=========================================================="

# 🔥 绝杀:按回车 → 瞬间关闭终端(系统来不及输出任何日志)
read -rs -t 3600
osascript -e 'tell application "Terminal" to quit window 1' >/dev/null 2>&1 & exit 0

⚠️配置信息需要改成自己公司的,才可正常签名。

双击sign.command文件,弹起终端窗口,脚本自动化处理所有流程。

说明:因新系统对拖动触发脚本做了限制,自动操作捕获输入变量异常,为了简化处理,采用固定输入和固定输出。也可能是我未配置正确,欢迎熟悉的朋友赐教下, 我们一起完善下!

INPUT_APP="待签名.app"

OUTPUT_DMG="签名完成.dmg"

执行结果

image.png

四、签名流程详解

创建一个签名管理的文件夹MacSign,将【AiPPT.app】文件放进去该目录。

1.先对【AiPPT.app】进行代码签名

1.1清理旧签名(可选)

codesign --remove-signature AiPPT.app

1.2递归签名依赖项(签名内部文件)

Developer ID Application 需要换成自己公司的

sudo codesign -f -o runtime -s "Developer ID Application: Shenzhen Pixel Bloom Technology Co., Ltd. (7UXDYFGRA9)" -v AiPPT.app --deep  --verbose=4

三方库一般不用独立签名,重复签名可能会引起签名冲突等不可控的异常问题。 特殊情况下,才单独对内部关键文件签名,后对.app 签名

sudo codesign -f -o runtime -s "Developer ID Application: Shenzhen Pixel Bloom Technology Co., Ltd. (7UXDYFGRA9)" -v AiPPT.app/Contents/Libraries/bydm.dylib  --verbose=4

1.3验证代码签名

codesign --verify --deep --strict --verbose=4 AiPPT.app

提示如下,则代码签名成功

AiPPT.app: valid on disk

AiPPT.app: satisfies its Designated Requirement

2.再对【AiPPT.dmg】进行包签名

2.1创建 .dmg 文件

hdiutil create -volname "AiPPT" -srcfolder "AiPPT.app" -ov -format UDZO "AiPPT.dmg"

2.2对dmg签名

codesign --sign "Developer ID Application: Shenzhen Pixel Bloom Technology Co., Ltd. (7UXDYFGRA9)" AiPPT.dmg

2.3验证dmg代码签名

codesign --verify --deep --strict --verbose=4 AiPPT.dmg

提示如下,则代码签名成功

AiPPT.app: valid on disk AiPPT.app: satisfies its Designated Requirement

3.对【AiPPT.dmg】进行签名公证

3.1对 .dmg 本身进行公证

⚠️公证信息需要改成自己公司的,才可正常公证。

xcrun notarytool submit AiPPT.dmg \
  --apple-id "wyk125@163.com" \
  --team-id "xxxxxxxxx" \
  --password "xxxx-xxxx-xxxx-xxxx" \
  --wait

3.2装订公证票据

将已公证的 .dmg 文件装订票据,以标记该文件已被公证,可离线使用:

xcrun stapler staple AiPPT.dmg

4.对签名进行验证

4.1验证APP签名合法性,Gatekeeper验公证结果


 spctl --assess --type execute --verbose=4 AiPPT.dmg

正确的提示信息如下:

AiPPT.app: accepted source=Notarized Developer ID

4.2获取签名的信息

spctl -a -vv /Users/wangyongkang/MacSign/AiPPT.dmg

成功获取信息,提示如下:

/Users/wangyongkang/MacSign/AiPPT.app: accepted source=Notarized Developer ID origin=Developer ID Application: Shenzhen Pixel Bloom Technology Co., Ltd. (7UXDYFGRA9)

5.完成以上签名流程,就可分发 .dmg 安装包

✅ 签名有效  

✅ 已通过 Apple 公证  

✅ 已正确 stapled(嵌入公证票据)  

✅ Gatekeeper 认可为安全应用

点击签名后的 .dmg 文件,按流程安装即可。

image.png

参考文档

苹果官方文档:developer.apple.com/developer-i…