Provisioning Profile & Entitlements

最近学习了一下iOS代码签名机制 ,这里做个笔记记录,整理思路,加深理解。
想了解更多iOS签名相关,强烈推荐去看看原文,写的太棒了。原文出处 深度长文:细说iOS代码签名 。

背景

沙盒(Sandbox)技术是iOS安全体系中非常重要的一项技术,他的目的是通过各种技术手段限制App的行为,比如可读写的路径,允许访问的硬件,允许使用的服务等等,即使应用出现任意代码执行的漏洞,也无法影响到沙盒外的系统。(图来自Apple开发者网站)

sandboxing.png

Entitlements

通常所说的Entitlements(授权文件),也就是指iOS沙盒的配置文件,这个文件中声明了app所需的权限,如果app中使用到了某项沙盒限制的功能,但没有声明对应的权限,可能运行到相关的代码时会直接Crash。

授权机制也是按照 plist 文件格式来列出的。这个文件内部格式如下:





        application-identifier
        7TPNXN7G6K.ch.kollba.example
        aps-environment
        development
        com.apple.developer.team-identifier
        7TPNXN7G6K
        com.apple.developer.ubiquity-container-identifiers
        
                7TPNXN7G6K.ch.kollba.example
        
        com.apple.developer.ubiquity-kvstore-identifier
        7TPNXN7G6K.ch.kollba.example
        com.apple.security.application-groups
        
                group.ch.kollba.example
        
        get-task-allow
        


在 Xcode 的 Capabilities 选项卡下选择一些选项之后,Xcode 就会生成这样一段 XML。 Xcode 会自动生成一个 .entitlements 文件,然后在需要的时候往里面添加条目。当构建整个应用时,Xcode 会将这个文件作为 --entitlements 参数的内容传给 codesign ,作为应用所需要拥有哪些授权的参考。这些授权信息必须都在开发者中心的 App ID 中启用,并且包含在配置文件中,稍后我们会详细讨论这一点。在构建应用时需要使用的授权文件可以在 Xcode build setting 中的 code signing entitlements 中设置。

在这个应用中我启用了 iCloud 键值对存储 (key-value storage) (com.apple.developer.ubiquity-kvstore-identifier) ,以及 iCloud 文档存储 (com.apple.developer.ubiquity-container-identifiers)。另外我还将应用添加进了一个 App Group (比如说为了与扩展 (extensions) 共享数据,com.apple.security.application-groups), 最后开启了推送功能 (aps-environment)。这是一个开发版本,我会有将它连接到调试器的需求,这就需要将 get-task-allow 设为 true。另外,app id,也就是 bundle id 加上开发者 id,也被单独列出来了。

当然你并不能随心所欲的取得授权,你的应用能否得到某一项授权是有特定的规定的。举例来说,当 get-task-allow 被设定为 ture 时,应用只能在用于开发的证书签名下运行。你被允许使用的推送环境 (aps-environment) 也存在类似的限制。

实际上,这个文件的内容并非是全部的授权内容,因为缺省状态下,App默认会包含以下与Team ID及App ID相关的权限声明:


    get-task-allow
    
    application-identifier
    xxx.xxx.bundleID
    com.apple.developer.team-identifier
    xxxxxxxxxx

其中get-task-allow代表是否允许被调试,它在开发阶段是必需的一项权限,而在进行Archive打包用于上架时会被去除。

进行代码签名时,会将这个Entitlements文件(如有)与上述缺省内容进行合并,得到最终的授权文件,并嵌入二进制代码中,作为被签名内容的一部分,由代码签名保证其不可篡改性。

可以尝试查看签名信息中具体包含了什么授权信息:$ codesign -d --entitlements - Example.app

$ codesign -d --entitlements - CodeSignTest.app
Executable=/Users/bytedance/Downloads/iOS签名/sign/CodeSignTest.app/CodeSignTest
[Dict]
    [Key] application-identifier
    [Value]
        [String] JJHW9Jxxxx.com.xxxxxxx.xxxx
    [Key] com.apple.developer.applesignin
    [Value]
        [Array]
            [String] Default
    [Key] com.apple.developer.team-identifier
    [Value]
        [String] JJHW9Jxxxx
    [Key] get-task-allow
    [Value]
        [Bool] true

Provisioning Profile

这里引用一下苹果的原文解释

A provisioning profile is a collection of digital entities that uniquely ties developers and devices to an authorized iPhone Development Team and enables a device to be used for testing.

Provisioning Profile在这里就起到了一个对设备和开发者授权的作用,他将开发者账号、证书、entitlements文件以及设备进行了绑定。

在开发过程中,使用的 Provisioning Profile 都被存放在 ~/Library/MobileDevice/Provisioning\ Profiles/ 路径下,以 UUID 格式命名。

由于这个文件是被苹果签过名的,所以我们没有办法伪造或者修改这个文件,它使用的是标准的CMS(Cryptographic Message Syntax)格式,可以通过 security 命令查看它的签名信息:

$ security cms -D -i xxxxxxxxxxx.mobileprovision -h 1 -n  # 查看签名信息
SMIME:    level=1.2; type=signedData; nsigners=1;
      signer0.id="Apple iPhone OS Provisioning Profile Signing"; signer0.status=GoodSignature;
  level=1.1; type=data;

Provisioning Profile 统一都是由 Apple iPhone OS Provisioning Profile Signing 进行签名的,机构名称言简意赅。

profile_cer.png

通过 security 命令将文件的内容提取出来:

$ security cms -D -i ea8585cd-c2da-4b08-81c2-e32b28c34871.mobileprovision -o provision.plist # 将内容导出





  AppIDName
  xxxxx
    ...
  DeveloperCertificates
  
      xxxxx
      xxxxx
      xxxxx
  
  Entitlements
  
      get-task-allow
      
      application-identifier
      xxxxx.xxx.bundleID
      com.apple.developer.team-identifier
      xxxxx
      com.apple.developer.siri
      
  
  ExpirationDate
  2022-01-22T05:14:57Z
  Name
  iOS Team Provisioning Profile: xxxx
  ProvisionedDevices
  
      xxxxx
      xxxxx
      xxxxx
  
  ...


明显可以看出这是一个xml格式的plist文件,里面的内容不难理解,最关键的是这几项

  • DeveloperCertificates:允许使用的开发者证书,这是一个列表,一般包含生成这个Provisioning Profile文件时,当前开发者账号下所有有效的Development证书,以base64格式保存。
  • Entitlements:允许使用的权限列表,这些授权信息是你在开发者中心下载配置文件时在 App ID 中设置的。实际在App中使用的权限必须是这个列表的子集,否则安装时会无法通过校验而失败。如果曾经开启过某个功能,Xcode自动更新了Provisioning Profile,后来又关闭它,Xcode并不会将其从Provisioning Profile中删去,如示例中的com.apple.developer.siri
  • ProvisionedDevices:允许安装的设备列表,如果目标设备的UUID不在这个列表中,会安装失败。对于这一项,普通开发者证书和企业级开发者证书的待遇是不同的。普通开发者证书使用Provisioning Profile的方式安装App到设备,只是出于测试和调试的需要,因此Apple只允许最多注册100台用于测试的设备,否则开发者就可以以测试的名义任意任意分发自己的App了。而对于企业级开发者来说,本身就有任意安装的需求,因此在分发时,这一项会被ProvisionsAllDevices取代,代表授权任意设备。

这些信息中有任何变动的时候,比如开发者证书有新增或者失效,在Capabilities中启用了当前App从未使用过的新功能,或是将新的iPhone连接到Xcode用于测试,Xcode都会自动重新申请Provisioning Profile。

Provisioning Profile会被内置在App中,置于App根目录下的 embedded.mobileprovision 。安装App时如果签名校验通过,这个文件会自动被拷贝到iOS设备的 /Library/MobileDevice/Provisioning\ Profiles/ 路径下。由于该文件已被Apple官方签名,系统可以无条件信任它,并用它来校验App的签名、权限,以及本机的UUID等是否满足来自官方的授权。

embed_profile.png

通过这种方式,设备间接信任开发者的身份,让iOS设备可以运行非苹果官方签名的App。

假如你有一台越狱的设备,查看任意一个从AppStore上下载下来的App,里面都不会有embedded.mobileprovision这个文件,因为经过Apple重新签名以后,设备就不再需要它来信任开发者了。

你可能感兴趣的:(Provisioning Profile & Entitlements)