一、签名证书申请
- 注册 Apple Developer Program(年费 $99),⚠️务必登录账号所有人的 Apple 账号,才能操作申请这个证书。
- 在 Apple Developer 开发证书申请后台,创建以下证书:
- Developer ID Application:用于签名应用。
- Developer ID Installer:用于签名安装包。
- macOS App 证书 和 iOS App 开发是两套证书,有些证书名字很相似,注意做好区分。
- 下载并安装相关证书,⚠️****证书信任采用默认设置,信任等级要保持一致。
二、签名前的准备工作
在 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"
执行结果
四、签名流程详解
创建一个签名管理的文件夹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 文件,按流程安装即可。
参考文档