背景
在开发手Q需要真机调试的时候经常有同事抱怨签名报错的问题,一方面是手Q工程非常庞大、有很多Target
每个都需要签名,另一方面IOS签名本身就非常繁琐复杂,其次,很多开发者对签名机制没有彻底掌握,导致出现问题浪费好多时间。所以花了一些时间仔细研究总结了一下IOS签名机制,推荐给大家,希望本文有助于开发者更好地理解IOS签名机制,提升开发效率。
苹果为什么要推出签名机制
苹果一直致力于打造一个健康的闭环生态圈,只有符合标准的App才能在平台上运行,所以推出一个准入认证机制,来保证App的质量和用户的安全。Windows
、Android
等开发平台上的流氓软件横行,我觉得主要一个原因还是平台缺少审核机制。
关键技术和基础原理
目前App
主要通过四种途径在苹果平台上运行:
1.App Store
2.真机调试
3.In-House
企业内部分发,用企业证书签名后可直接运行
4.AD-Hoc
相当于企业分发的限制版,限制安装设备数量
App Store
是采用单层签名验证机制,后面三种情况使用的是双层签名验证机制,接下来从相对简单的单层签名验证机制开始,详细讲解两者的区别和具体实现过程。
单层签名验证
实现过程大致分为以下几步:
- 苹果官方生成一对公私钥,在 iOS 里内置一个公钥,私钥由苹果后台保存。
- 我们传 App 上 AppStore 时,苹果后台用私钥对 APP 数据进行签名。
- iOS 系统下载这个 APP 后,用内置的公钥验证这个签名,若签名正确,这个 APP 肯定是由苹果后台认证的,并且没有被修改过,就可以正常运行在IOS上,否则,不能运行。
从上图分析可以看出,签名验证机制的核心技术是数字签名。
数字签名
数字签名的主要作用防止数据被篡改、防止抵赖,数字签名是非对称密钥加密技术与数字摘要技术的应用。接下来讲解一下数字签名的实现过程:
实现过程大致分为以下几步:
- 首先用一种算法,算出原始数据的摘要。这种算法需要满足两个条件:若原始数据有任何变化,计算出来的摘要值都会变化。摘要要够短。这里最常用的算法是MD5。
- 生成一份非对称加密的公钥和私钥,私钥我自己拿着,公钥公布出去。
- 用私钥加密这个摘要,得到一份加密后的数据,称为原始数据的签名。
- 摘要和原始数据一起发送给用户。
- 用户收到数据和签名后,用公钥解密得到摘要。同时用户用同样的算法计算原始数据的摘要,对比这里计算出来的摘要和用公钥解密签名得到的摘要是否相等,若相等则表示这份数据中途没有被篡改过,因为如果篡改过,摘要会变化。
从上述分析可以看出,数字签名技术主要依赖加密技术和摘要算法,接下来简单介绍一下非对称加密技术。
非对称加密
非对称加密算法需要两个密钥:公开密钥(publickey
)和私有密钥(privatekey
)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。
非对称密码体制的特点:算法强度复杂、安全性依赖于算法与密钥但是由于其算法复杂,而使得加密解密速度没有对称加密解密的速度快。
了解更多前往 RSA 算法原理(一)RSA 算法原理(二)
双层签名验证
在很多种情况下App
不需要传到苹果后台认证和审核,能直接在平台上运行,但是苹果又需要对这种情况进行监管和控制,比如说:真机调试、企业证书签名等。为了解决这个问题,因此推出了双层签名认证机制。
大致流程分为以下几步:
- 第1步,对应的是 keychain 里的 “从证书颁发机构请求证书”,这里就本地生成了一对公私钥,保存的 CertificateSigningRequest 就是公钥,私钥保存在本地电脑里。
- 第2步,苹果自身实现。
- 第3步,对应把 CertificateSigningRequest 传到苹果后台生成证书,并下载到本地。这时本地有两个证书,一个是第 1 步生成的,一个是这里下载回来的,keychain 会把这两个证书关联起来,因为他们公私钥是对应的,在XCode选择下载回来的证书时,实际上会找到 keychain 里对应的私钥去签名。这里私钥只有生成它的这台 Mac 有,如果别的 Mac 也要编译签名这个 App 怎么办?答案是把私钥导出给其他 Mac 用,在 keychain 里导出私钥,就会存成 .p12 文件,其他 Mac 打开后就导入了这个私钥。
- 第4步,都是在苹果网站上操作,配置 AppID / 权限 / 设备等,最后下载 Provisioning Profile 文件。
- 第5步,XCode 会通过第 3 步下载回来的证书(存着公钥),在本地找到对应的私钥(第一步生成的),用本地私钥去签名 App,并把 Provisioning Profile 文件命名为 embedded.mobileprovision 一起打包进去。这里对 App 的签名数据保存分两部分,Mach-O 可执行文件会把签名直接写入这个文件里,其他资源文件则会保存在 _CodeSignature 目录下。
- 第6步,在安装时,iOS 系统取得证书,通过系统内置的公钥 A,去验证 embedded.mobileprovision 的数字签名是否正确,里面的证书签名也会再验一遍。
- 第7步,确保了 embedded.mobileprovision 里的数据都是苹果授权以后,就可以取出里面的数据,做各种验证,包括用公钥 L 验证APP签名,验证设备 ID 是否在 ID 列表上,AppID 是否对应得上,权限开关是否跟 APP 里的 Entitlements 对应等。
名词解释
证书:公钥+签名信息
Code Signing Identity:证书+私钥
.p12文件:导出的私钥就是p12文件格式
Entitlements:授权机制决定了哪些系统资源在什么情况下允许被一个应用使用。简单的说它就是一个沙盒的配置列表,上面列出了哪些行为被允许,哪些会被拒绝。在xcode
的Capabilities
中列举的功能都是需要配置授权的。
Provisioning Profile:证书+设备IDs+AppID+Entitlements+签名信息
小结
提交App Store
的应用就是采用单层签名验证,只需要苹果自身的公私秘钥就能完成。而企业签名、真机调试等情形,不仅需要苹果参与签名,而且需要开发者自身参与签名,因此称之为双层签名验证。
参考文献
bang’s blog
代码签名探析