学习苹果证书签名机制、重签名总结

对于基础的加密相关的概念可以看文章:# 加密、摘要、签名、CA证书、HMAC、CRC全面梳理

一、苹果证书签名机制

一句话:用非对称加密来验证身份,用摘要算法来确保完整性。

大体流程如下:

三个关键角色和他们的密钥:

js 复制代码
┌─────────────────────────────────────────────────────────┐
│  1. 你的 Mac(开发者)                                    │
│     私钥 L  ← 藏在钥匙串里,用来签名 App                  │
│     公钥 L  ← 放进 CSR 里,最终放进证书里                 │
│                                                         │
│  2. 苹果后台(CA 角色)                                   │
│     私钥 A  ← 苹果绝对保密的顶级私钥                       │
│     公钥 A  ← 出厂内置在每台 iPhone/iPad 的系统里          │
│                                                         │
│  3. iPhone / iPad 用户设备                               │
│     公钥 A  ← 系统内置,用来验证苹果签过名的东西            │
└─────────────────────────────────────────────────────────┘

下面我们再分步骤拆解,看看加密和签名具体是怎么运用的。

1. 生成证书请求文件(CSR):(你 Mac 本地)

这是整个流程的起点, 你在Mac的钥匙串里申请CSR时,会生成.certSigningRequest文件,系统会悄悄地做两件事:

js 复制代码
你 Mac 本地操作:

┌──────────────────────────────────────────┐
│  密钥串访问 → 证书助理 → 从证书颁发机构请求证书 │
│                                          │
│  系统后台自动做:                          │
│                                          │
│  1. 生成密钥对                            │
│     ┌───────────┐    ┌───────────┐      │
│     │  私钥 L    │    │  公钥 L    │      │
│     │ (留在本地) │    │ (要发出去) │      │
│     └───────────┘    └─────┬─────┘      │
│                            │             │
│  2. 组装 CSR 文件          ▼             │
│     ┌────────────────────────────┐       │
│     │ CSR 内容:                  │       │
│     │ · 你的邮箱/名称             │       │
│     │ · 公钥 L                   │       │
│     │ · 用私钥 L 对上述内容签名    │       │
│     └────────────────────────────┘       │
│                                          │
│  CSR 证明了:                             │
│  "持有私钥 L 的人,申请让苹果认证公钥 L"   │
└──────────────────────────────────────────┘

用到的技术:
  非对称加密 ✓  (签名部分)
  摘要算法   ✓  (签名前对内容做 SHA-256)

2. 苹果签发证书(苹果服务器):开发证书(.cer)

你把CSR文件上传到苹果开发者网站,苹果作为CA,会验证你的身份(开发者账号),然后用它的私钥A 给你的公钥L (以及其他信息)做一个签名认证,最后打包成一个.cer证书文件发给你。

这个证书证明了"公钥L是经过苹果官方认证的合法开发者公钥"。

js 复制代码
你上传 CSR → 苹果服务器

┌──────────────────────────────────────────────────────┐
│  苹果后台处理:                                       │
│                                                      │
│  1. 验证 CSR 签名                                     │
│     用 CSR 里的公钥 L,验证签名是否合法                 │
│     → 合法说明你确实持有私钥 L                          │
│                                                      │
│  2. 验证开发者身份                                     │
│     检查你的 Apple Developer 账号是否有效               │
│                                                      │
│  3. 签发证书                                         │
│     ┌─────────────────────────────────────┐          │
│     │ 开发证书 .cer 内容:                  │          │
│     │                                     │          │
│     │ · 你的 Team ID / 账号信息            │          │
│     │ · 公钥 L                            │          │
│     │ · 证书类型(开发/发布)               │          │
│     │ · 有效期                             │          │
│     │ · 苹果的签名(私钥A, 上述所有内容)      │          │
│     └─────────────────────────────────────┘          │
│                                                      │
│  你下载 .cer 文件并安装到钥匙串                         │
│  此时钥匙串里的私钥 L 和证书正式配对                    │
└──────────────────────────────────────────────────────┘

证书 .cer 里有什么:
  你的信息 + 公钥L + 苹果签名(私钥A, 你的信息+公钥L)

用到的技术:
  非对称加密 ✓  (苹果用私钥A签名证书)
  摘要算法   ✓  (签名前 SHA-256)

3. 配置描述文件(.mobileprovision):一张临时的"权限通行证"

描述文件则整合了你申请的所有权限。它包含:

  • 你的开发者证书(即包含公钥L)。
  • App ID:指定这个签名能用于哪个App。
  • 设备UDID列表:指定能在哪些设备上运行(仅开发/Ad-Hoc证书)。
  • 授权信息(Entitlements):比如能否使用APNs推送、iCloud等。

它也经过苹果私钥A的完整签名,防止被篡改。

js 复制代码
你在开发者网站配置 App ID、UDID → 苹果生成描述文件

┌─────────────────────────────────────────────────────┐
│  描述文件 .mobileprovision 内容:                     │
│                                                     │
│  ┌─────────────────────────────────────────────┐    │
│  │ · App ID (com.example.yourapp)               │    │
│  │ · 开发者证书链(包含你的 .cer)                │    │
│  │    └── 你的证书里有公钥 L                     │    │
│  │ · 授权设备 UDID 列表(开发证书才有)           │    │
│  │ · 权限 Entitlements(推送、iCloud 等)        │    │
│  │ · 有效期                                      │    │
│  │ · 苹果签名(私钥A, 上述所有内容)                │    │
│  └─────────────────────────────────────────────┘    │
│                                                     │
│  描述文件也经过苹果签名,防止被篡改添加设备或权限       │
└─────────────────────────────────────────────────────┘

描述文件里有什么:
  权限清单 + 你的证书(含公钥L) + 苹果签名(私钥A)

用到的技术:
  非对称加密 ✓  (苹果用私钥A签名整个描述文件)

4.签名 App(Xcode 本地):给APP盖上防伪章

当你用Xcode打包App时,Xcode就会使用存储在钥匙串里的私钥L ,对你App包的每一个二进制文件和资源文件进行数字签名。具体的做法是:

js 复制代码
Xcode 打包 App 时:

┌─────────────────────────────────────────────────────┐
│  Xcode 做的事情:                                     │
│                                                     │
│  1. 从钥匙串取出 私钥 L 和证书                        │
│                                                     │
│  2. 对 App 内每一个可执行文件和资源:                  │
│                                                     │
│     ┌──────────────────────────────────────┐        │
│     │  原始文件(二进制/图片/plist)          │        │
│     │         │                             │        │
│     │         ▼                             │        │
│     │  SHA-256 哈希 → 摘要值                │        │
│     │         │                             │        │
│     │         ▼                             │        │
│     │  私钥 L 签名摘要 → 签名值              │        │
│     │         │                             │        │
│     │         ▼                             │        │
│     │  签名值写入 App 包 _CodeSignature     │        │
│     └──────────────────────────────────────┘        │
│                                                     │
│  3. 把描述文件 .mobileprovision 也打包进 App          │
│                                                     │
│  App 包最终包含:                                     │
│  · 原始代码/资源                                     │
│  · _CodeSignature(每个文件的签名)                   │
│  · embedded.mobileprovision(描述文件)               │
└─────────────────────────────────────────────────────┘

用到的技术:
  摘要算法   ✓  (SHA-256 哈希每个文件)
  非对称加密 ✓  (私钥 L 对摘要签名)

5.iOS 设备验证(安装/启动时):"双锁校验"

当App安装到iOS设备上时,系统会严格地过两道关:

  • 第一道锁:验证描述文件和证书 iOS系统用内置的公钥A ,去验证.mobileprovision描述文件的签名,确认权限未经篡改。然后,从中取出开发者的证书,再次用公钥A 验证证书签名,从而确认"公钥L"是苹果官方认证过的合法开发者身份。

  • 第二道锁:验证App包体完整性 系统用刚刚验证过的合法公钥L ,去解密App包内的数字签名,得到一个"原始摘要"。然后,系统用相同的摘要算法重新计算App文件内容,得到一个"新摘要"。如果"原始摘要"和"新摘要"完全一致,则证明这个App自开发者签名后没有被任何第三方篡改或注入病毒过

关于这套苹果签名体系,还有几个关键细节值得注意:

  • 私钥是核心资产.p12文件就是私钥L的备份(可设置密码保护),它必须被妥善保管,是代码签名能力的核心。一旦泄露,他人就能以你的身份签名App。

  • 双层签名的必要性 :为什么需要苹果的私钥A 和开发者的私钥L双层签名?单纯用私钥L签名,iOS系统无法分辨这个签名来自张三还是李四。引入苹果私钥A的"认证链"后,苹果就完成了对开发者身份的终极背书,从而形成一个完整的信任闭环。

所以你看到的"证书请求文件 -> 开发证书 -> 描述文件 "这一整套流程,本质上就是苹果用自己的私钥A ,为你本地的公钥L 做信用背书,最终让你的私钥L能够有权在App上完成数字签名的完整逻辑。

js 复制代码
用户下载/安装/启动 App 时,iOS 系统自动执行:

┌──────────────────────────────────────────────────────┐
│                                                      │
│  🔓 第一把锁:验证描述文件和证书                        │
│  ┌────────────────────────────────────────────┐      │
│  │                                            │      │
│  │ 1. 取出 App 里的 .mobileprovision          │      │
│  │                                            │      │
│  │ 2. 用系统内置的公钥 A 验证苹果签名            │      │
│  │    签名有效?                                │      │
│  │    ├── YES → 描述文件未被篡改 ✓              │      │
│  │    └── NO  → ❌ 拒绝安装/启动               │      │
│  │                                            │      │
│  │ 3. 检查描述文件内容:                        │      │
│  │    · App ID 是否匹配?                      │      │
│  │    · 设备 UDID 在不在列表里?                │      │
│  │    · 证书有没有过期?                        │      │
│  │    · 权限 Entitlements 是否合法?            │      │
│  │                                            │      │
│  │ 4. 从描述文件里提取开发者证书                 │      │
│  │    用公钥 A 验证证书的苹果签名                │      │
│  │    签名有效 → 公钥 L 是苹果认证过的 ✓         │      │
│  │                                            │      │
│  └────────────────────────────────────────────┘      │
│                         │                            │
│                         ▼                            │
│  🔓 第二把锁:验证 App 代码完整性                       │
│  ┌────────────────────────────────────────────┐      │
│  │                                            │      │
│  │ 1. 从已验证的证书中提取 公钥 L               │      │
│  │                                            │      │
│  │ 2. 对每个被签名的文件:                      │      │
│  │                                            │      │
│  │    当前位置文件 ──SHA-256──► 新摘要          │      │
│  │                                            │      │
│  │    _CodeSignature 里的签名值                │      │
│  │         │                                  │      │
│  │         ▼                                  │      │
│  │    用公钥 L 验证签名 → 得到原始摘要          │      │
│  │                                            │      │
│  │    新摘要 == 原始摘要 ?                     │      │
│  │    ├── YES → 文件未被篡改 ✓                 │      │
│  │    └── NO  → ❌ 拒绝启动(代码被修改过)     │      │
│  │                                            │      │
│  └────────────────────────────────────────────┘      │
│                                                      │
│  两把锁全通过 → App 正常启动 ✅                         │
│  任意一把失败 → App 闪退/拒绝安装 ❌                    │
└──────────────────────────────────────────────────────┘

用到的技术:
  非对称加密 ✓  (公钥A验苹果签名 + 公钥L验代码签名)
  摘要算法   ✓  (SHA-256 校验文件完整性)

6. P12 文件的作用机制

一句话:P12 就是"私钥的搬家箱",让你能把私钥安全地从一台 Mac 搬到另一台 Mac,或者备份到安全的地方。

js 复制代码
┌──────────────────────────────────────────┐
│  私钥 L 极其重要                          │
│                                          │
│  · 没有它 → 无法签名 App                  │
│  · 丢了它 → 永远无法更新这个 App          │
│  · 别人拿到 → 可以冒充你签名              │
│                                          │
│  问题:                                   │
│  · 换电脑了怎么办?                        │
│  · 团队成员怎么共享同一个开发者证书?       │
│  · 怎么备份?                             │
│                                          │
│  答案:P12 文件                           │
└──────────────────────────────────────────┘

P12 文件的内部结构

js 复制代码
┌──────────────────────────────────────────────┐
│           P12 文件内部(PKCS#12 标准)         │
│                                              │
│  ┌────────────────────────────────────┐      │
│  │  1. 开发者证书 (.cer)               │      │
│  │     · 你的信息                      │      │
│  │     · 公钥 L                        │      │
│  │     · 苹果签名(私钥A)               │      │
│  │     ← 这部分本来就是公开的            │      │
│  ├────────────────────────────────────┤      │
│  │  2. 私钥 L (核心机密)               │      │
│  │     · 256 位椭圆曲线私钥             │      │
│  │     · 非常敏感!                     │      │
│  │     ← 关键保护对象                   │      │
│  ├────────────────────────────────────┤      │
│  │  3. 可选:中间 CA 证书链             │      │
│  │     · Apple Worldwide Developer     │      │
│  └────────────────────────────────────┘      │
│                                              │
│  🔐 整个文件用 密码 + 对称加密 保护            │
│                                              │
│  导出时你设置的密码:                           │
│  123456 ──► 密钥派生 ──► AES 密钥              │
│                              │               │
│                              ▼               │
│                  整个 P12 内容被 AES 加密       │
│                  变成 .p12 二进制文件           │
└──────────────────────────────────────────────┘

P12 用了对称加密:

js 复制代码
┌──────────────────────────────────────────────────────┐
│                                                      │
│  P12 保护私钥的机制(对称加密的出场时刻):                │
│                                                      │
│  你设置的密码(比如 "MyPassword123")                  │
│         │                                            │
│         ▼                                            │
│  PBKDF2 密钥派生函数(加盐 + 多轮哈希)                │
│         │                                            │
│         ▼                                            │
│  派生出一把 AES 对称密钥                               │
│         │                                            │
│         ▼                                            │
│  用 AES 加密整个 P12 容器                              │
│  (里面的证书 + 私钥 + 证书链)                         │
│         │                                            │
│         ▼                                            │
│  .p12 文件 = 一堆加密后的二进制数据                    │
│                                                      │
│  没有密码 → 拿不到 AES 密钥 → 解不开 P12               │
│  有密码   → 派生出 AES 密钥 → 解开拿到私钥 L           │
│                                                      │
└──────────────────────────────────────────────────────┘

导入 P12 ------ 另一台 Mac

js 复制代码
把 P12 文件发给另一台 Mac(或同一台重装系统后):

┌──────────────────────────────────────────────┐
│  第二台 Mac 导入 P12                           │
│                                              │
│  1. 双击 .p12 文件                            │
│                                              │
│  2. 钥匙串弹出密码框:                          │
│     "请输入导出时设置的密码"                    │
│              │                               │
│              ▼                               │
│  3. 你输入 "MyPassword123"                    │
│              │                               │
│              ▼                               │
│  4. 系统用 PBKDF2 派生 AES 密钥               │
│              │                               │
│              ▼                               │
│  5. 用 AES 密钥解密 P12 文件                   │
│              │                               │
│              ▼                               │
│  6. 解开后拿到:                               │
│     · 证书(公钥 L + 苹果签名)               │
│     · 私钥 L                                │
│     · 证书链                                 │
│              │                               │
│              ▼                               │
│  7. 安装到这台 Mac 的钥匙串里                  │
│                                              │
│  🔑 钥匙串 - 登录                              │
│  ┌──────────────────────────────────────┐   │
│  │ 📜 iPhone Developer: 张三             │   │
│  │    ├── 公钥 L                         │   │
│  │    └── 私钥 L  ← 成功搬过来了!        │   │
│  └──────────────────────────────────────┘   │
│                                              │
│  现在这台 Mac 也能签名 App 了 ✅               │
└──────────────────────────────────────────────┘

P12 的安全要点

js 复制代码
┌────────────────────────────────────────────────────┐
│                                                    │
│  ✅ 安全的地方:                                    │
│  · P12 文件本身用 AES 加密,算法安全                  │
│  · 密码用 PBKDF2 派生密钥,抗暴力破解                │
│  · 即使 P12 被截获,没密码也打不开                    │
│                                                    │
│  ⚠️ 风险点:                                        │
│  · 密码太弱(123456)→ 暴力破解风险                  │
│  · P12 + 密码通过同一渠道传输 → 一起泄露就完了        │
│  · P12 导入后,私钥又从 P12 解出来到新钥匙串          │
│    此时 P12 本身的密码保护就没用了                    │
│    新的安全边界变成"新 Mac 的钥匙串"                  │
│                                                    │
│  💡 最佳实践:                                      │
│  · 强密码(16位以上随机)                            │
│  · P12 和密码分开发送(如 P12 发邮件,密码打电话说)   │
│  · 导入后 P12 文件可以删除(私钥已在钥匙串里)         │
│  · 或者用 Xcode 自动管理证书(不需要手动导 P12)       │
│                                                    │
└────────────────────────────────────────────────────┘

二、重签名

当我们测试设备达到上限(100台时),重签是解决思路之一,这里梳理下重签名的大体过程:

flowchart TD subgraph A [开发者准备阶段] A1[私钥 .p12 + 密码] A2[描述文件 .mobileprovision] A3[开发者证书 .cer] end subgraph B [CI/CD 构建与修改阶段] B1[拉取源码] B2[编译生成 App 包] B3[代码混淆/资源修改
此时原签名已失效] end subgraph C [CI/CD 自动重签名阶段] C1[安装证书与私钥到
临时钥匙串] C2[提取权限文件
Entitlements] C3[调用 codesign 命令
对修改后的包重新签名] C4[打包生成 IPA] end subgraph D [分发与部署] D1[上传 TestFlight] D2[部署到内网分发平台
蒲公英/fir.im 等] end A1 & A2 & A3 --> C1 B1 --> B2 --> B3 --> C3 C1 --> C2 --> C3 --> C4 --> D1 C4 --> D2

参考文章: ios逆向-重签名

相关推荐
其实防守也摸鱼2 小时前
VS code怎么使用 Conda 安装预编译包
开发语言·网络·c++·vscode·安全·web安全·conda
Wyc724092 小时前
信息安全与多媒体基础知识
网络·安全·web安全
Paranoid-up2 小时前
安全启动和安全固件更新(SBSFU)7:SECoreBin——安全引擎核心
安全·iap·安全启动·安全升级·sbsfu
heimeiyingwang2 小时前
【架构实战】VPC网络与跨域通信:构建安全可控的云上网络
网络·安全·架构
代码飞一会儿3 小时前
CTF之通过栈溢出偷出信息
安全
wangl_923 小时前
Modbus RTU 与 Modbus TCP 深入指南-安全加固方案
网络·网络协议·tcp/ip·安全·tcp·modbus·rtu
S1998_1997111609•X3 小时前
哈希树阻断正常系统通信工程进行函数钩子解析
安全·百度·缓存·哈希算法·量子计算
晓梦林5 小时前
Qingmei靶场学习笔记
笔记·学习·安全·web安全
昨夜见军贴06165 小时前
爆破冲击试验越来越严格,AI报告审核如何借助IACheck守住安全底线
人工智能·安全