心宇

FDF24DCED8C6738F8313A6D3B073C3F4

首页 管理

基于《iOS App 签名的原理》整理。本文优先保留原 PDF 的推导逻辑:先从数字签名出发,再解释为什么 iOS 最终需要 Certificate、Provisioning Profile、Entitlements、App ID、设备列表和本地私钥。

1. iOS 为什么需要签名

iOS 签名机制的核心目标不是“加密 App”,而是建立一条可信授权链:

  • Apple 要确认:这个 App 的安装/分发行为是否经过 Apple 允许。
  • 系统要确认:App 或其签名数据没有被非法篡改。
  • 开发调试场景还要限制:谁可以签、哪个 App 可以签、哪些设备可以安装、App 可以使用哪些能力。

因此可以把 iOS 签名理解成:

身份认证 + 完整性校验 + 安装范围控制 + Capability/Entitlements 权限授权


2. 基础:非对称加密与数字签名

非对称密码体系有一对密钥:

  • 私钥(Private Key):签名者自己保存。
  • 公钥(Public Key):提供给验证者。

数字签名并不是简单地“用私钥加密整个 App”。基本思想是先计算数据摘要,再用私钥对摘要进行签名;验证方用公钥验证签名,并将得到/验证的摘要与自己重新计算的数据摘要比较。

flowchart LR A[原始数据 / App] --> B[Hash] B --> C[摘要 Digest] C --> D[使用私钥签名] D --> E[数字签名 Signature] A --> F[接收方重新计算 Hash] E --> G[使用公钥验证签名] F --> H{摘要是否一致?} G --> H H -->|是| I[签名有效 / 数据未被篡改] H -->|否| J[验证失败]

数字签名解决两个问题

  1. 完整性:数据发生变化,摘要也会变化。
  2. 身份可信性:只有持有对应私钥的人才能生成可由该公钥验证的签名。

PDF 使用 MD5 作为讲解数字摘要的例子。理解原理时可把它抽象成 Hash(data);现代实际签名体系不应把 MD5 当作安全签名摘要算法。


3. 最简单模型:Apple 直接给 App 签名

假设 iOS 只允许从 App Store 安装应用,那么架构可以非常简单:

flowchart LR Apple[Apple 后台<br/>持有 Apple 私钥] -->|Apple 私钥签名| APP[App + Apple Signature] APP --> IOS[iOS 设备] PK[系统内置 Apple 公钥] --> IOS IOS -->|验证 App 签名| RESULT{是否合法?}

Apple 保存私钥,iOS 设备内置可信公钥。App 经 Apple 私钥签名后,设备即可验证它确实经过 Apple 授权且内容未被修改。

为什么现实中不能只有这一层?

开发过程中,开发者必须能把尚未上传 App Store 的 App 直接装到真机调试。如果每次 Build 都上传 Apple 服务器重新签名,开发效率无法接受。

所以新的问题变成:

Apple 不直接给每个开发中的 App 签名,又怎样允许开发者本地签名,同时仍保持控制权?


4. 核心机制:双层信任链

PDF 用“公钥 L / 私钥 L(Local)”和“公钥 A / 私钥 A(Apple)”描述这个过程。

第一层:Apple 认证开发者的公钥

开发者 Mac:

Private Key L  <---- 对 App 签名
Public Key  L  ----> 提交给 Apple

Apple 使用自己的 Private Key A 对开发者的 Public Key L 进行认证,形成开发者证书。

第二层:开发者给 App 签名

开发者使用 Private Key L 给 App 签名。

iOS 最终执行两级验证:

flowchart TB subgraph MAC[Mac 开发机] LPRI[开发者私钥 L] LPUB[开发者公钥 L] APP[编译后的 App] LPRI -->|签名| APP end subgraph APPLE[Apple 后台] APRI[Apple 私钥 A] APRI -->|认证/签名| CERT[开发者证书<br/>包含公钥 L] end LPUB --> CERT subgraph IOS[iOS 设备] APUB[系统信任的 Apple 公钥 A] V1[① 验证证书] V2[② 取得可信公钥 L] V3[③ 验证 App 签名] OK[允许继续安装/运行验证] APUB --> V1 --> V2 --> V3 --> OK end CERT --> V1 APP --> V3

这形成了关键的信任关系:

Apple Root / Apple Trust
        ↓
Apple 认证开发者证书
        ↓
开发者公钥 L 被系统信任
        ↓
开发者私钥 L 签名 App
        ↓
iOS 用公钥 L 验证 App

因此 Apple 不需要亲自签每一次 Debug Build,只需要证明:

“这个用于签 App 的公钥,是我 Apple 批准的。”


5. 为什么只有 Certificate 仍然不够

如果 Apple 只认证开发者公钥,那么开发者可能用这个私钥给任意 App 签名,并装到任意设备。

因此 Apple 还需要控制:

  • 哪些设备可以安装:Device UDID / Device IDs
  • 签的是哪个应用:App ID
  • App 可以使用什么能力:Entitlements
  • 使用哪张开发者证书:Certificate
  • 授权有效期等信息

这些信息最终集中到 Provisioning Profile。


6. Provisioning Profile 是整个体系的授权清单

可以把 Provisioning Profile 理解为:

Apple 签名过的一份“这个 App 可以怎样运行”的授权文件。

逻辑结构可简化为:

Provisioning Profile
├── Developer Certificate
│   └── Developer Public Key
├── App ID
├── Device IDs / UDIDs(某些分发类型)
├── Entitlements
├── 有效期等信息
└── Apple Signature

Apple 对 Profile 整体签名,因此开发者不能自行修改其中的 App ID、设备列表或权限。


7. 最终完整签名架构

flowchart LR subgraph DEV[Mac / Developer] KEYPAIR[生成密钥对] PRI[Private Key L<br/>Keychain] PUB[Public Key L / CSR] BUILD[App Build] KEYPAIR --> PRI KEYPAIR --> PUB PRI -->|codesign| BUILD end subgraph PORTAL[Apple Developer 后台] CERT[Developer Certificate] APPID[App ID] DEVICES[Device IDs] ENT[Entitlements / Capabilities] PROFILE[Provisioning Profile] PUB -->|提交 CSR/公钥信息| CERT CERT --> PROFILE APPID --> PROFILE DEVICES --> PROFILE ENT --> PROFILE APPLEKEY[Apple Private Key] -->|Apple 签名| CERT APPLEKEY -->|Apple 签名| PROFILE end PROFILE -->|下载并嵌入| IPA[Signed App<br/>embedded.mobileprovision] BUILD --> IPA subgraph DEVICE[iOS Device] APPLEPUB[Apple Trust / Public Key] CHECK1[验证 Provisioning Profile] CHECK2[验证 Developer Certificate] CHECK3[验证 App Code Signature] CHECK4[核对 App ID / Device / Entitlements] RUN[允许安装/启动] APPLEPUB --> CHECK1 CHECK1 --> CHECK2 --> CHECK3 --> CHECK4 --> RUN end IPA --> CHECK1

8. 从创建证书到真机验证:完整过程

Step 1:Mac 生成本地密钥对

Keychain 中执行“从证书颁发机构请求证书”等操作,本质上是在本机建立与证书申请相关的密钥材料。

核心关系:

Mac
├── Private Key  ← 最重要,不能泄漏
└── Public Key   ← 用于向 Apple 申请证书

Step 2:向 Apple 申请开发者证书

开发者向 Apple 提交 CSR/公钥相关信息。

Apple 对开发者身份/公钥进行认证,生成 Developer Certificate。

Developer Public Key
        ↓
Apple CA / Developer Portal
        ↓ Apple 签名
Developer Certificate

Step 3:配置 App ID、设备和能力

Developer Portal 中配置:

Bundle/App Identity
        +
Registered Devices
        +
Capabilities / Entitlements
        +
Developer Certificate

Step 4:生成 Provisioning Profile

Apple 将这些授权信息组合并签名:

Certificate
+ App ID
+ Devices
+ Entitlements
+ ...
       ↓
Apple Signature
       ↓
Provisioning Profile

Step 5:Xcode 本地签 App

Xcode 找到 Developer Certificate 对应的本地 Private Key,使用它对 App 进行代码签名。

同时将 Provisioning Profile 嵌入 App:

MyApp.app/
├── MyApp                 # Mach-O,可执行文件含代码签名信息
├── _CodeSignature/
│   └── CodeResources
└── embedded.mobileprovision

Step 6:iOS 验证 Apple 的授权

安装/运行时,系统首先确认 embedded.mobileprovision 等授权数据确实来自可信 Apple 签名链。

Step 7:iOS 验证 App

随后检查:

开发者证书是否合法?
        ↓
App 的代码签名能否由证书对应公钥验证?
        ↓
App ID 是否匹配?
        ↓
当前设备是否被允许?(适用时)
        ↓
App Entitlements 是否超出 Profile 授权?
        ↓
全部通过 → 安装 / 启动

9. Certificate、CSR、Private Key、p12、Profile 的关系

这是最容易混淆的一组概念。

对象 本质 谁生成/签发 主要作用
Private Key 私钥 Mac 本地 对 App 进行签名
Public Key 公钥 与私钥成对生成 验证开发者签名
CSR 证书签名请求 Mac 向 CA/Apple 申请证书时提交的信息
Developer Certificate Apple 认证的开发者身份/公钥凭证 Apple 证明该签名身份得到 Apple 认可
.p12 通常用于导出/迁移证书和对应私钥的 PKCS#12 容器 开发者导出 将签名身份迁移到另一台 Mac/CI
Entitlements App 权限声明 App/Xcode + Apple 授权体系 声明 App 要使用的能力
Provisioning Profile Apple 签名的授权配置 Apple 将证书、App ID、设备、Entitlements 等约束关联起来
embedded.mobileprovision App 内嵌的 Profile Xcode 打包 供设备验证授权范围

一句话记忆

Certificate:你是谁
Private Key:证明“你就是你”的秘密
App ID:你要签哪个 App
Entitlements:这个 App 能做什么
Devices:它能装到哪些设备
Provisioning Profile:Apple 对以上组合给出的授权证明
Code Signature:你用自己的私钥对实际 App 做出的签名

10. CSR → Certificate → p12 的关系图

flowchart LR KEYCHAIN[Mac Keychain] -->|生成| PRI[Private Key] KEYCHAIN -->|生成对应公钥/申请信息| CSR[CSR] CSR -->|上传| APPLE[Apple Developer] APPLE -->|签发| CERT[Developer Certificate] CERT -->|安装回 Mac| KEYCHAIN PRI -.匹配.- CERT KEYCHAIN -->|导出证书 + 私钥| P12[p12 / PKCS#12] P12 -->|导入| MAC2[另一台 Mac / CI]

关键点:

只有 .cer / Certificate,而没有与其匹配的 Private Key,通常无法完成对应身份的代码签名。

这也是常见的:

No signing certificate
Certificate has no matching private key

一类问题的根源。


11. Entitlements 为什么必须同时校验

App 自己会携带签名后的 Entitlements,而 Provisioning Profile 里也包含 Apple 授权范围。

因此不是 App 自己声明:

com.apple.developer.xxx = true

就自动拥有能力。

逻辑上必须满足:

App 请求的 Entitlements
        ⊆
Provisioning Profile 允许的 Entitlements

否则签名/安装/运行验证可能失败。

flowchart LR A[App Entitlements<br/>我想使用 Push / iCloud / ...] --> C{是否在 Apple 授权范围内?} B[Provisioning Profile Entitlements<br/>Apple 允许的能力] --> C C -->|匹配| D[验证通过] C -->|不匹配| E[签名或安装/运行失败]

12. 不同分发方式的架构对比

下表主要按照 PDF 的分类和解释整理。Apple 的产品名称、分发政策和现代签名实现会随平台版本演进,因此这里重点理解“信任链和限制条件”,而不是把旧资料中的名称当成最新政策文档。

场景 谁最终授权 是否限制设备 Profile 的角色 典型用途
Development Apple + Developer 签名链 是 约束 App ID、设备、Entitlements、证书 真机开发调试
Ad Hoc Apple + Developer 签名链 是 指定允许安装的设备 小范围测试分发
In-House / Enterprise(PDF 用语) Apple 认可的企业签名体系 PDF 描述为不按普通设备列表限制 用于企业分发授权 企业内部应用
App Store Apple 分发体系 不按开发测试 UDID 列表 上传阶段用于开发者身份/权限等校验;商店分发验证模型不同 正式公开分发

13. Development 与“最简单 App Store 模型”对比

flowchart TB subgraph SIMPLE[简化的 App Store 信任模型] A1[Apple Private Key] -->|签 App| A2[App] A3[iOS 内置信任] -->|验证| A2 end subgraph DEVFLOW[Development 双层信任模型] B1[Apple] -->|签/认证| B2[Developer Certificate / Profile] B2 -->|证明 Developer Public Key 可信| B3[Developer Identity] B3 -->|Developer Private Key 签名| B4[App] B5[iOS] -->|先验证 Apple 授权| B2 B5 -->|再验证 Developer Code Signature| B4 end

本质差异

简单模型:

Apple → App

开发模型:

Apple → Developer Identity / Authorization → App

多出来的一层,就是为了让开发者能够离线、本地、高频地签 Debug Build,同时 Apple 仍掌握授权边界。


14. iOS 签名最值得记住的信任链

                   Apple 信任根
                       │
              Apple 对证书/Profile签名
                       │
          ┌────────────┴────────────┐
          │                         │
 Developer Certificate     Provisioning Profile
          │                 ├─ App ID
          │                 ├─ Devices
          │                 └─ Entitlements
          │
          ▼
 Developer Public Key
          ▲
          │ 对应
 Developer Private Key
          │
          │ codesign
          ▼
       App Binary
          │
          ▼
       iOS 验证

可以浓缩成一句:

Apple 不必直接信任每一个开发中的 App;Apple 信任一个受约束的开发者签名身份,iOS 再沿着这条信任链验证 App。


15. 常见签名错误如何从原理定位

① Certificate 存在,但没有 Private Key

Certificate ✓
Private Key ✗

结果:你有“身份证明”,但没有能够生成该身份签名的秘密密钥。

处理思路:检查 Keychain 中证书下是否有关联私钥;需要迁移时从原机器导出包含对应私钥的 p12。

② Provisioning Profile 与 Certificate 不匹配

Profile 允许 Certificate A
当前使用 Certificate B

→ 授权链断裂。

③ Bundle ID / App ID 不匹配

App Bundle ID
      ≠
Profile 授权的 App ID

→ Profile 并没有授权这个 App。

④ Device 不在 Profile 中

Development / Ad Hoc 等需要设备授权的场景:

Current UDID ∉ Provisioned Devices

→ 真机无法按该授权安装。

⑤ Entitlements 不匹配

App Requested Capability
        >
Profile Granted Capability

→ App 请求了 Apple 没有在该 Profile 中授权的能力。

⑥ Profile / Certificate 过期或失效

签名不仅要“数学上正确”,相关凭证和授权本身也存在有效性条件。


16. 一套排查思维

遇到 Xcode Signing 问题时,不要只反复点击 “Automatically manage signing”,可以沿信任链逐层检查:

flowchart TD A[Signing Error] --> B{Private Key 存在?} B -->|否| B1[检查 Keychain / p12] B -->|是| C{Certificate 有效且匹配?} C -->|否| C1[重新选择/申请 Certificate] C -->|是| D{Profile 匹配 Certificate?} D -->|否| D1[重新生成 Profile] D -->|是| E{App ID / Bundle ID 匹配?} E -->|否| E1[检查 Identifier] E -->|是| F{Device 被授权?} F -->|否| F1[注册设备并更新 Profile] F -->|是| G{Entitlements 匹配?} G -->|否| G1[检查 Capabilities / Entitlements] G -->|是| H[检查有效期、签名产物及其他配置]

17. PDF 原文中需要带着“历史资料”视角理解的地方

这份 PDF 非常适合建立签名机制的概念模型,尤其是“双层签名 → 增加设备/App限制 → Provisioning Profile”的推导过程。

但学习时建议区分两层:

原理层:长期有效

  • 公私钥与数字签名
  • Apple 信任链
  • Developer Certificate
  • 本地 Private Key
  • App Code Signature
  • Provisioning Profile
  • App ID / Entitlements 的授权约束

实现与政策层:可能随 iOS / Xcode / Apple Developer Program 更新

  • 摘要算法的具体选择
  • App Store 安装包内部细节
  • Enterprise / In-House 的政策和验证机制
  • Xcode 自动签名的具体行为
  • Profile 是否/如何出现在不同现代分发产物中

因此排查现代 Xcode 问题时,应以 Apple 当前官方文档和实际 codesign / Profile 内容为准。


18. 最终速记版

1. Mac 生成 Private Key + Public Key
2. 用 CSR 向 Apple 申请 Developer Certificate
3. Apple 认证开发者签名身份
4. Developer Portal 配置:
      Certificate
      + App ID
      + Devices
      + Entitlements
5. Apple 对这些授权信息签名
      → Provisioning Profile
6. Xcode 使用本地 Private Key 对 App codesign
7. Profile 作为授权信息参与打包/验证
8. iOS:
      先信 Apple
      → 再信 Apple 批准的 Developer Certificate/Profile
      → 再验证 Developer 对 App 的签名
      → 再核对 App ID / Device / Entitlements
9. 全部满足后,App 才获得相应安装/运行授权

核心公式

Apple Trust
    ↓
Certificate + Provisioning Profile
    ↓
Developer Identity
    ↓
Code Signature
    ↓
App

签名体系的核心不是某一个 .cer 或 .mobileprovision 文件,而是整条可验证的信任链。

posted on 2026-10-06 12:35  心宇16969  阅读(15)  评论(0)    收藏  举报