App签名二三事

1、概述

相比于Android系统,iOS对下载到设备中的软件有比较严格的限制;绝大多数人,只会从AppStore下载App,这也杜绝了不少安全隐患;可是对于iOS开发者来讲,须要搞明白不少事情(如:iOS App的签名原理),甚至须要作一些小动做(如重签名)来达到本身(友好的)目的。git

一、基础概念

  • 摘要算法:把一个任意长度的字节串映射 为必定长度的十六进制的数字串;这个数字串称为哈希值。常见有:MD五、SHA一、SHA25六、SHA512等算法

  • 对称加密:加密和解密使用相同密钥,常见有:DES算法、3DES算法和AES算法等;shell

  • 非对称加密:加密和解密使用不一样密钥的加密算法,用公钥加密的数据,要用私钥才能解密,用私钥加密的数据,要用公钥才能解密;经常使用加密算法有:RSA、Elgamal、背包算法等;安全

  • 数字签名(digital signature):bash

    • 是非对称加密与摘要算法的结合,用于验证数据的完整性及不可抵赖性;
    • 发送方对数据计算出摘要信息,而后用发送方私钥加密,获得摘要密文,这就是数字签名;
    • 接收方收到后,利用发送方的公钥和非对称算法从数字签名中获取摘要明文;根据原始内容计算出摘要 和 解密出来的摘要明文进行对比;不一致,说明内容被篡改 or 收到内容不是指定发送方;
  • 数字证书(digital certificate):app

    • 数字证书数为了保护发送方公钥不被伪造而发明的,引入证书中心(Certificate Authority,CA)概念,CA用本身的私钥,对发送方的公钥和一些相关信息一块儿加密,生成"数字证书"(Digital Certificate)。
    • CA的数字证书中有:签发者、证书用途、发送方公钥、发送方非对称加密算法、发送方HASH算法和到期时间等
    • 接收方拿到数字证书后,先从数字证书中解密出发送方公钥(用的是CA的公钥和CA解密算法);而后根据发送方公钥去解密数字证书,获得摘要;最后比对原始数据计算出的摘要是否一致。
    • CA是第三方机构,CA公钥是公开的,接收方能够跟别人比对(好比网上查),所以不可能伪造。而发送方公钥,是接收方从数字证书中得到的。
    • 数字证书在https协议实现中有重要应用

二、签名相关的几个概念

名称 做用
证书(cer) 内容是公钥或私钥,由其余机构对其签名组成的数据包。
Entitlements 包含了 App 权限开关列表
CertificateSigningRequest 本地公钥
p12 本地私钥,能够导入到其余电脑。
Provisioning Profile 包含了 证书 / Entitlements 等数据,并由苹果后台私钥签名的数据包。

三、iOS包渠道及其签名机制

  • iOS设备上App的渠道粗分有AppStore渠道非AppStore渠道,非AppStore包有:Testflight内测包、In-House 企业内部分发包、Ad-Hoc(至关于企业分发的限制版,限制安装设备梳理)和Xcode调试安装;(越狱包不在此范围)。ide

  • AppleStore中渠道包签名验证工具

    • 苹果官方生成一对公私钥,在 iOS 系统中内置一个公钥,私钥由苹果后台保存。
    • App 上传到 App Store 时,苹果后台用私钥对 App 数据进行签名(计算出摘要,再私钥加密);
    • iOS 下载这个 App 后,用公钥验证这个签名,若是签名正确则这个 App 确定是由苹果后台认证的,而且没有被修改或损坏。
  • 非AppleStore渠道包的签名验证须要使用双重签名机制,保证不被滥用。post

2、双重签名机制

一、简介

  • 使用两对公私钥作加密验证,分别是 Mac本地的一对公私钥Apple提供的一对公私钥(私钥在苹果后台,公钥在每一个 iOS 设备上)。
  • 双重签名的存在是为了知足:
    • App 须要通过苹果容许才能安装;
    • 在 Apple 后台中注册过的设备才能安装,好比在 TestFlight 内测、真机调试模式下;
    • 限制签名只能对应惟一的 App;

二、重要概念

  • Mac 上执行钥匙串访问 -> 证书助理 -> 从证书颁发机构请求证书...,就会在Mac本地生成了一对公私钥,导出的 CSR 文件(CertificateSigningRequest.certSigningRequest)就是 Mac 公;测试

  • CSR 文件上传到苹果后台,苹果用Apple私钥对其签名,并生成一份包含Mac公钥信息 和 苹果签名信息的开发/发布证书cer

  • 当咱们将cer下载并安装到Mac后,keychain会把CertificateSigningRequest和cer证书关联起来。在钥匙串中找到该证书,能够导出Mac私钥(.p12 文件)

  • 在苹果后台须要配置AppID、可用设备IDs(企业证书不须要) 和 Entitlements(App 权限开关列表),对这些额外信息 和 cer证书使用Apple私钥签名,最后苹果将证书 + 额外信息 + 签名组成一个Provisioning Profile文件(后缀mobileprovision),可下载到Mac上。

    Provisioning Profile文件又被成为描述文件,安装好后,存放在~/Library/MobileDevice/Provisioning Profiles路径下
    复制代码

三、App签名和验证

双签名和验证

  • 在Mac上编译完一个App后,Mac先用Mac私钥对App签名,并将Provisioning Profile文件也打包到App中,文件名为embedded.mobileprovision

  • iOS系统安装App时,苹果经过内置在手机中的Apple公钥验证embedded.mobileprovision中的签名是否正确,接着验证证书中的签名是否正确

  • 在确保embedded.mobileprovision里的数据都是苹果受权之后,就从里面取出数据,作后续各类验证,包括

    • 用Mac公钥验证App签名
    • 验证设备 ID 是否在 ID 列表上
    • 验证证书是否过时
    • 验证AppID 是否对应得上
    • 验证权限开关是否跟 APP 里的 Entitlements 对应等等。
  • 若是别的 Mac 也要编译后签名这个 App,就必需要获取申请生成cer证书那个Mac机器上的私钥;这个比较简单,只须要在那台机器的钥匙串中找到cer证书,而后右键导出Mac私钥(.p12 文件);

  • 简单来讲,要在别人设备上成功编译成功并将App安装到设备中,须要cer证书导出的**.p12文件和Provisioning Profile文件**(描述文件)

四、补充

  • 双层代码签名是针对开发测试包、In-House 企业签名、Ad-Hoc 包为例的签名和验证的流程,只是企业签名不限制安装的设备数,所以描述文件中不会有设备列表,而是一条 ProvisionsAllDevices 记录。
  • 从 App Store 上下载的安装包,里面是没有描述文件的,但上架以前仍是要配置证书、PP 文件,由于 App ID 和权限的检验仍是须要作的。但 App 上传到 AppStore 之后就跟 PP 文件没有关系了,因此咱们能够理解为 App Store 上包的签名验证采用就是前面说的最简单的签名方式,Apple 后台直接用私钥签名 App 就能够了。

3、App重签名

一、概述

  • 重签名本质是将已发布/未发布的包从新签名为本身的证书和签名,关键点是替换ipa内的证书描述文件
  • 使用codesign工具

二、重签名方案

  • 查看ipa包是否加壳,只有未加壳的包才能够重签名。

    otool -l app_name.app/app_name | grep crypt
     # 输出cryptid为0表明已经砸壳,即解密,为1或者2表示以第1类或者第2类加密方案加密。
    复制代码
  • 查看本地证书列表并记录下要用来签名的证书名,例如”iPhone Distribution: XXXXX (XXX)”

    security find-identity -v -p codesigning
    # 输出有效的证书列表
    复制代码
  • 建立一个和App同名的工程,从上步获得有效证书列表中,选择一个,编译后生成新App;将这个新App里embedded.mobileprovision文件取出替换iap包中的文件。

  • 删除ipa包内部不能被重签名的插件(PlugIns文件夹 和 Watch文件夹)

  • 将ipa包内的全部Framework中Mach-O文件重签名(Frameworks目录下有Framework)

# 命令参考
codesign -fs [证书名称] [要签名的文件]
 #若是没有权限,执行chmod +x app_name.app/app_name 给Mach-O文件添加可执行权限
#Frameworks文件夹里面的.framework本质仍是文件夹,真正要重签的是.framework里面的MachO可执行文件
复制代码
  • 将ipa包内info.plist的BundleId修修改成新App对应的的BundleId

  • 用命令查看embedded.mobileprovision文件,找到其中的entitlements字段,而且复制entitlements字段和其中的内容。

    security cms -D -i 「embedded文件路径」
    复制代码
  • 新建entitlements.plist文件,将复制内容拷贝到文件中,而后将entitlements.plist复制到ipa的同级目录下。

  • 对App进行重签名,并压缩成新的ipa包

    # 重签名
    $ codesign -fs "iPhone Distribution: XXXXX (XXX)" --no-strict --entitlements=entitlements.plist
    
    // --no-strict 不严谨的 
    // --entitlements=entitlements.plist权限所在文件是entitlements.plist
    codesign -fs 签名证书 --no-strict --entitlements=entitlements.plist app_name.app
     # 压缩ipa包
    $ zip -r 「输出的文件名(.ipa)」 Payload/
    复制代码
  • 将ipa包安装到手机,若能同时存在两个应用且能正常运行则表示重签名成功。

三、防止App被重签名办法

  • 校验描述文件信息:在启动时校验描述文件信息与打包时是否一致。例如判断组织单位: 先记录证书中的组织单位信息。
  • sysctl检测是否被调试,具体可见iOS安全防御之重签名防御和sysctl反调

四、目的

  • 对于大多数iOS开发,了解App签名原理,知道要对App作防止重签名的保护便可。
  • 本人并不是从事越狱安全工做;使用重签名,主要是为了让测试包能够支持IAP测试,搞过IAP的同窗应该明白IAP测试中的痛点: 使用TestFlight or ad-hoc包测试的效率真的会把人逼疯,企业内测又不支持[坑]

历史文章

早年简单了解过加密,混淆之类的事情,具体能够看以前文章

浅谈数据加密

浅谈AES

浅谈代码混淆

参考文章

代码签名探析

iOS App 签名的原理

iOS应用安全3 -- APP重签名

相关文章
相关标签/搜索