从已签名 App 恢复被删除的 iOS 开发证书

从已签名 App 恢复被删除的 iOS 开发证书

适用场景:本机钥匙串中的 Apple Development 证书被误删(security delete-certificate),
私钥仍然存在,且本机/项目里留有用该证书签名过的产物.app / .ipa)。
本文从这些签名产物中把证书提取回来,与保留的私钥配对,完整恢复签名身份。

原理:为什么能恢复

iOS 代码签名身份(codesign identity)= 证书(public key 载体)+ 私钥,两者缺一不可:

签名身份 = 证书(.cer,含公钥)+ 私钥(本机钥匙串)
  • 已签名的 App 中嵌入了签名时的证书链(叶子证书 + 中间证书 + 根证书),
    codesign --extract-certificates 可将其提取为 DER 格式的证书文件;
  • security delete-certificate 只删除证书,默认不删除私钥(除非加 -t 选项)。
    私钥删除后会保留为"孤儿私钥",只是命令行工具(find-key / dump-keychain
    受 ACL 保护往往枚举不到,但 Keychain Access 图形界面可见;
  • 因此:补回证书文件 → 导入钥匙串 → 自动与保留的私钥配对 → 签名身份完整复原
为什么不用开发者中心下载:免费个人团队(Personal Team)账号在
developer.apple.com 没有 "Certificates, IDs & Profiles" 页面(该页面仅付费
开发者计划可访问);Xcode 也不会"打开就自动下载"服务器证书(只在签名构建时按需
创建)。从签名产物提取是免费账号唯一能"原样复原"的途径。

前置条件

  • [x] 被删证书曾在某次签名中使用过(产物 .app / .ipa 的签名内嵌着它)
  • [x] 私钥仍在钥匙串(用下方 Step 1 确认;通常满足——删证书不删私钥)
  • [x] macOS + Xcode 命令行工具(xcrun / codesign / security / openssl

详细步骤

Step 1 · 确认私钥仍在(关键前提)

图形界面最可靠:

  1. 打开 钥匙串访问(Keychain Access)
  2. 左侧选择 登录 钥匙串
  3. 右上搜索被删证书的名称(如 Apple Development
  4. 若能看到黄色钥匙图标(没有证书配对的私钥)→ 私钥在,可以继续

命令行佐证(注意:受 ACL 保护的私钥可能枚举不到,"搜不到"不代表私钥丢了):

security find-identity -v -p codesigning          # 看当前签名身份(应为 0)
security dump-keychain ~/Library/Keychains/login.keychain-db 2>/dev/null | grep -c "class: 0x00000040"   # 私钥类条目,仅供佐证

Step 2 · 找到用该证书签过名的产物

在项目/本机搜索所有 .app / .ipa

find . -name "*.app" -type d 2>/dev/null | grep -v ".dSYM"
find . -name "*.ipa" 2>/dev/null

逐一查看签名证书,确认哪几个产物用的是被删证书

codesign -dv --verbose=4 <path/to/xxx.app> 2>&1 | grep -E "^Authority="

预期输出(Authority= 行即签名证书链,第一行是叶子证书):

Identifier=com.example.app
Authority=Apple Development: [email protected] (TEAMID12345)   ← 被删的证书
Authority=Apple Worldwide Developer Relations Certification Authority
Authority=Apple Root CA
提示:同一任务可能产生多个签名产物(如命令行部署脚本重签的产物、IDE 自动签名
构建的产物等),每个产物都嵌着签名时用的那张证书——多张证书可能分散在不同
产物里,都值得检查一遍。

Step 3 · 提取签名证书链

进入 .app 目录,对可执行文件(或 .app 目录)执行:

cd <path/to/xxx.app>
codesign -d --extract-certificates ./<可执行文件名>
可执行文件名即 App 主二进制(不确定就 ls 找非资源文件的可执行文件)。
亦可直接对 .app 目录提取,不同 macOS 版本输出路径略有差异,以实际生成为准。

在当前目录生成三个 DER 编码证书(没有扩展名,属正常):

codesign0   ← 叶子证书(签名证书本体,最关键的)
codesign1   ← 中间证书(Apple WWDR)
codesign2   ← 根证书(Apple Root CA,系统一般已有)

Step 4 · 确认提取的证书就是要恢复的那张

openssl x509 -inform der -in codesign0 -noout -subject -fingerprint -sha1

与 Step 2 中 Authority 行的 CN 比对;sha1 Fingerprint 应与被删证书的 SHA-1 一致
(可用 security find-certificate -Z 的历史记录回想确认)。

Step 5 · 导入钥匙串

security add-certificates codesign0    # 叶子证书:必须
security add-certificates codesign1    # 中间证书:若提示"already in default keychain"即系统已有,无碍

默认导入 登录钥匙串(与被删证书原位置一致)。

Step 6 · 验证身份恢复

security find-identity -v -p codesigning

恢复成功时应出现:

1) <SHA1> "Apple Development: [email protected] (TEAMID12345)"
   1 valid identities found

显示 valid identities = 证书已与保留的私钥配对成功,可正常签名部署。


多张证书的恢复

一个签名产物只嵌一张叶子证书(签名时选的那张)。若误删多张,需为每张找到
各自的签名产物,重复 Step 2~6。常见的“多张证书分散来源”:

  • 部署脚本重签的产物(通常自动选用钥匙串里第一张可用证书)
  • IDE 自动签名构建的产物(可能选用另一张证书)

逐一提取导入后,find-identity 会恢复出与删除前一致的签名身份列表。

限制:只能恢复找到签名来源的证书;删除前过多张、但只部分签过名的,
其余证书无法从签名产物复原(只能走 Xcode 重建流程)。

注意事项

  1. 有效期不变:提取导入的证书仍是当初签发的那张,受原有效期限制
    (免费开发者证书常为 1 年,过期需走 Xcode 重建流程)。
  2. codesign0/1/2 是临时文件,保留在 .app 目录内无害;如需清爽可删除。
  3. 私钥仍是安全核心:恢复只补了证书,私钥从未导出;切勿把私钥文件外发。
  4. 命令行枚举不到私钥 ≠ 私钥丢失:以 Keychain Access 图形界面为准。
  5. 私钥也不在(删除时用了 -t,或证书来自其他机器且未迁移私钥),
    本方法无效,只能让 Xcode 在签名构建时重新生成证书(免费账号标准流程)。

与其它恢复途径对比

途径免费账号可用是否"原样复原"备注
开发者中心下载 .cer❌(需付费计划)developer.apple.com/account 无证书页
Xcode 自动恢复❌(重建=新证书新私钥)登录账号后触发一次签名构建即可,但非原证书
从已签名产物提取(本文)证书原样复原,且与保留私钥配对

标签: none

添加新评论