前言
本篇文章虽然是介绍iOS开发中ipa包的签名原理。但因为签名涉及到密码学中的概念。在了解签名之前,我们需要明确一些概念。密码学中,根据加解密密钥的不同,通常把加密方式分为对称密码(对称加密)和公钥密码(非对称加密)。常见加密算法有:DES、3DES、DESX、AES、RSA、ECC。其中RSA、ECC是非对称加密算法。以下是一些必要的概念。
对称密码:又叫做对称加密。加密和解密使用的是同一个密钥。
公钥密码:又叫做非对称加密。有一个公钥和一个私钥,公钥和私钥组成一个密钥对。使用私钥加密的数据可以使用公钥解密,反之亦然。
混合加密:同时使用对称加密和非对称加密两类算法。
消息摘要:通过单向散列函数对消息进行一定的运算,计算出固定长度的结果,就是消息摘要。
数字签名:用私钥对消息摘要(又叫哈希值、散列值)进行加密得到的密文就是数字签名
数字证书:按照一定格式将明文信息和消息摘要进行打包得到的文件就是证书。
中间人攻击: 中间人通过在网络中拦截并持有端到端的真实公钥,然后把自己的公钥转发给消息接收者。而后通过公钥拦截解析消息甚至篡改的一种攻击方式。
加密
对称密码
又叫做对称加密,一种加密和解密使用同一个密钥的加密算法。 即在对称密码中,密钥既可以对数据进行加密,又可以对数据进行解密。
特点
对称加密的优点是加解密速度快。缺点是对称加密的算法的密钥在传输过程中和保存的安全性问题。因为加解密使用同一个密钥,一旦密钥被泄露,数据的隐私性和完整性将受到很大的威胁。
算法
对称加密的常见算法有DES、3DES、DESX、AES。
公钥密码
公钥密码即我们常说的非对称加密,也称为公私钥加密。此类算法有一个公钥和一个私钥。公钥和私钥一一对应,共同组成一个密钥对,每个密钥对中的公钥和私钥是不同的。密钥对由网络中的通讯设备生成,通常是客户端或服务器。此处我们以PC客户端为例,PC客户端生成密钥对后,自己持有私钥,然后将公钥通过网络分发给其他PC客户端。公钥加密的数据需要私钥解密,反之亦然。公钥是公开的,可公开分发给其他PC客户端,但私钥只有密钥对生成者持有且不能泄露,一旦私钥泄露将会危及数据的安全。
特点
非对称加密的缺点是加解密速度要远远慢于对称加密,在某些极端情况下,甚至能比非对称加密慢上1000倍。
公钥可公开,私钥需保密。
算法
常见的非对称加密算法有RSA、Diffie-Hellman、ECC(移动设备使用)
密钥配送问题
上述我们简单了解了对称加密和非对称加密的概念和特点。对称加密中加解密使用的是同一个密钥,密钥在网络的配送过程一旦被非法窃取,数据的私密性和完整性无法得到保证。所以采用对称加密需要解决密钥的配送问题。常见的解决方案有:
● 通过事先共享密钥来解决
● 通过密钥分配中心来解决
● 通过 Diffie-Hellman 密钥交换来解决
● 通过公钥密码来解决
通过对称加密的特点,我们了解了对称加密的加解密速度快,但是存在密钥配送问题。非对称加密不存在密钥配送问题,但是加解密速度慢。结合这两类加密方式的特点,前辈们发明了对称加密+非对称加密的混合加密方式,即对称加密+非对称加密双重混合加密,称为混合密码系统。混合密码系统是将对称加密和非对称加密的优势相结合的方法。让我们来看看是如何实现的:
会话密钥:本质上就是随机生成的对称密钥。消息发送方和接收方每次会话都会通过伪随机数生成器生成一个对称密钥,每次生成的对称密钥可能都不相同,这种想对称密钥称为会话密钥。
加密步骤:
消息接收方:生成非对称密钥对,把公钥发送给消息发送方
消息发送方:生成随机的会话密钥,本质就是对称密钥
消息发送方:使用对称密钥对消息进行加密
消息发送方:使用公钥对会话密钥进行加密从而生成会话密钥的密文
消息发送方:把用会话密钥的密文和用会话密钥加密过的消息一并发给消息接收方
解密步骤:
消息接收方:使用自己的私钥对加密过的会话密钥进行解密获得明文的会话密钥
然后用明文的会话密钥对消息进行解密获得明文消息
使用混合密码系统解决了密钥配送问题:因为对称密钥在网络上配送的是密文,密文是对称密钥使用公钥加密后的结果,只能通过私钥进行解密,即便密文的对称密钥被第三方非法窃取,但因为第三方没有对应的私钥,无法对密文的对称密钥进行解密,也就能够保证对称密钥的安全性。
为什么不是使用公钥对消息进行加密,再使用会话密钥对公钥进行加密呢?
1.公钥本身就是公开的,不需要对公钥进行加密,对公钥加密无意义,上图中公钥用于加密数据,即便窃听者获取了明文的公钥也只能对数据加密,而没有私钥无法对数据解密 。
2.使用公钥对数据加密没有解决非对称加密方式频繁加密大量数据的低效问题。
小结
因为对称加密算法的加解密速度比非对称加密算法的快,在日常的网络数据传输中,经常会频繁的传输大量的网络数据,使用非对称加密这种安全但不高效的加密方式进行加密显然是不可取的,所以应该采用对称密钥加密消息。但对称密钥需要在网络上进行传输,且极易容易被破解。所以需要保证对称密钥在网络传输中的安全性,即需要保证对称密钥在网络配送过程中的安全性。所以最终的方案是使用对称密钥对消息进行加解密,再使用非对称加密的公钥对对称密钥进行加密,最后在网络上配送的是被公钥加密过的对称密钥和对称密钥加密过的消息(因为对称密钥数据长度比较短,使用非对称加密方式加密并不会很低效)。这种方式被称为混合加密(混合密码) 即用非对称加密(通常是RSA)解决密钥配送问题,用对称加密(AES)解决加密效率问题。
HTTPS中的SSL就是使用的混合密码系统。
消息摘要
除对称加密和非对称加密之外,还有一种特殊的加密方式——消息摘要。消息摘要又叫做Hash算法、单向散列算法。准确的说,消息摘要不算是一种加密方式,因为消息摘要是不可逆的且消息摘要的长度和消息的长度无关,所以就没有和对称加密、非对称加密混为一谈。
消息摘要函数(message digest function)
消息摘要函数又被称为哈希函数(hash function)。单向散列函数(One-way hash function)
哈希函数可以根据消息内容计算出对应的哈希值。哈希值的长度和消息的长度无关,无论消息是1bit、10M、100G,哈希函数都会计算出固定长度的哈希值。输出的哈希值也被称为消息摘要(message digest)、指纹(fingerprint)、散列值。
特点
消息摘要长度固定。无论明文消息长度是多少,使用同一个消息摘要函数计算出的消息摘要的长度是固定的。
消息摘要函数计算速度快。相比较其他复杂的计算方式,消息摘要函数计算速度快。
消息明文和摘要一一对应。同样的消息经过同一个摘要函数计算的散列值永远相同,不同的消息计算的散列值也不同。
消息摘要具备不可逆性。消息摘要函数又叫做单向散列函数,顾名思义,函数具备单向性和不可逆性。正常情况下,无法通过算法计算消息摘要对应的明文消息。
算法
单向散列算法是一个概念和标准,而不是一个具体的算法。常见的单向散列算法有:MD2、MD4、MD5、HAVAL、SHA、SHA-1、HMAC、HMAC-MD5、HMAC-SHA1、SHA-256。目前最常用的且相对安全的是SHA-256,SHA-256的散列值长度就是256bit。此外还有SHA-384、SHA-512。SHA-3是正在研究的全新标准。
macOS上自带md5散列函数:
消息摘要的应用
因为消息摘要和明文的一一对应关系以及不可逆性,所以消息摘要通常用来验证消息的完整性和真实性,以及用于不可还原的密码存储。
1.防止数据篡改
- 单向散列函数的应用场景之一就是防止(验证)数据是否被篡改,一旦发现数据被篡改则丢弃该数据。所以需要事先保证散列值的安全性,即不能把散列值暴露出去,也不能在网络上传输散列值。
- 一些软件网站为了保证用户从任何渠道下载的软件是正版未被篡改的,通常会在自己的官网上挂出软件的散列值。使用者从其他渠道下载了软件之后对软件进行散列值计算,和官网的散列值对比即可验证下载的软件是否为正版可信赖。
2.密码口令加密
- 单向散列函数的另一个应用场景就是用户的登录口令加密。为了保证用户敏感信息的私密性,互联网上传输的是隐私数据通常是经过散列函数计算过的散列值,数据库里存储的也可以是散列值而非明文。这样用户的明文密码无论是在传输过程中还是在存储过车中都不会被泄露。
数字签名
有了上述的对称密码、公钥密码、单向散列函数是不是就可以满足我们的数据安全需求了呢?答案是否定的。
对称密码和公钥密码仅解决了数据的加密问题,但依然无法彻底避免数据篡改和身份伪装。比如 常见的中间人攻击,就是在网络中拦截公钥并转发自己的公钥来实现消息拦截和篡改的。我们常见的网络代理应用——Charles就是采用中间人攻击的方式实现网络代理。
因为对称密码、公钥密码、单向散列函数都无法同时满足【防篡改、防伪装、防否认】。所以需要一种新的技术来识别数据篡改、伪装、否认。这种技术就是数字签名。
作用
数字签名通过一系列手段可以识别数据是否被篡改、识别消息发送方的真实身份是否合法,防止消息发送方否认。所以,数字签名的作用就是防止篡改、伪装、否认。
数字签名加密
数字签名加密即指对消息执行数字签名的处理过程,如下:
- 将明文消息进行摘要处理(以MD5为例),得到对应的消息摘要
- 用私钥对消息摘要进行加密得到摘要的密文,密文称之为数字签名
数字签名解密
数字签名解密即指对消息摘要执行解密和验证的处理过程,如下:
- 使用公钥解密数字签名(私钥加密的摘要)得到解密后的消息摘要A
- 使用相同算法的单向散列函数对明文消息进行摘要计算得到消息摘要B
- 对比消息摘要A和消息摘要B是否相等,即可验证数据的完整性和真实性
数字签名特点:
- 用私钥加密摘要,用公钥验证摘要
- 明文消息和数字签名都会发送给接收者
- 无法保证消息的机密性,只能保证消息摘要的机密性
- 数字签名得到的结果是消息摘要的密文,不是消息的密文
- 数字签名是一个【消息摘要+私钥加密】的过程,相对于单纯的消息摘要多了一步私钥加密。
数字签名的完整过程
- 发送者生成密钥对
- 发送者把公钥发送给消息接收者
- 发送者把消息生成消息摘要
- 发送者用私钥加密消息摘要
- 发送者将明文消息和加密后的消息摘要发送给消息接收者
- 接收者对明文消息生成摘要A
- 接收者用公钥解密密文摘要,得到明文消息摘要B
- 接收者对比第5、6步的消息摘要A、B,相等则说明消息未被篡改
为什么要对数据的哈希值进行加密而不是对数据本身进行加密?
通常网络数据较长,直接用私钥对数据进行加密后的密文可能会很长。
数据的哈希值通常是固定长度的,且长度不会很长,所以对哈希值进行加密后的密文不会很长,方便网络传输。
数字签名的目的
数字签名发送的是【明文消息+数字签名】。即数据在网络上是明文传输的,所以无法保证数据的机密性。并且这也不是数字签名的目的。
数字签名的目的是识别接收的数据的真实性和完整性(即有没有被篡改数据(对比消息摘要)、有没有被伪装身份(公钥解密签名)、保证发送者无法否认(和身份伪装是一回事,因为是用发送者的私钥加密的消息摘要,所以发送者不能否认))。
中间人攻击
因为公钥是需要在网络上传输的,所以公钥有可能被中间人拦截篡改,这种篡改公钥的攻击方式叫中间人攻击。Charles代理的方式就是中间人攻击的应用。
中间人攻击是通过拦截并持有真正的公钥,转发自己的公钥来实现消息的篡改和转发。一旦公钥被拦截篡改,消息接收者收到的将是中间人的公钥,那么数字签名将形同虚设。
综上,问题就演变成:
要正确使用签名,前提是需要保证:用于验证签名的公钥必须属于真正的发送者。
所以如何保 证公钥属于真正的消息发送者?
为了保证验证签名的公钥属于真正的消息发送者,即避免遭受中间人攻击拦截&伪造公钥,即保证数字签名的公钥的真实性合法性,需要CA证书
公钥证书
上面通过介绍数字签名,了解到签名的原理是消息发送端用私钥加密消息摘要,消息接收端用公钥解密消息摘要。又了解到中间人攻击可以拦截公钥并转发自己的公钥,所以要正确使用签名,前提是需要保证:用于验证签名的公钥必须属于真正的发送者。如何保证数字签名的公钥是真实的呢?这里就用到了公钥证书(Public-key Certificate,PKC)。
什么是公钥证书?
要开车先得考驾照,驾照上面记有本人的照片、姓名、出生日期等个人信息,以及有效期、准驾车辆的类型等信息。并由公安局在上面盖章。我们只要看到驾照,就可以知道公安局认定此人具有驾驶车辆的资格。
公钥证书其实和驾照很相似,里面记有姓名、组织、邮箱地址等个人信息,以及属于此人的公钥,并由认证机构(Certification Authority、Certifying Authority,CA)施加数字签名。只要看到公钥证书,我们就可以知道认证机构认定该公钥的确属于此人。公钥证书也简称证书。
以上是笔者摘自《图解密码技术》一书中对公钥证书的定义。
作用
通过公钥证书的定义,可见公钥证书本质上就是对公钥的签名认证,已达到认证公钥确实属于某个机构、组织或个人的目的。
所以公钥证书的作用是验证公钥的真实性。这样就可以解决公钥配送过程中被中间人攻击的问题。
证书结构
- 里面有名称、邮箱等个人或机构信息,以及个人或机构的公钥
- 包含认证机构(Certificate Authority,CA)施加的数字签名
- 所以证书包括两类元素:公钥信息+公钥信息的签名
何为CA(Certificate Authority)
CA就是我们上面说的认证机构
- CA就是能够认定“公钥确实属于此人”并能够生成数字签名的个人或者组织
- 有国际性组织、政府设立的组织。有通过提供认证服务来盈利的企业
- 个人也可以成立认证机构
注册和使用证书
注册证书
1.消息接收者生成密钥对
2.消息接收者将密钥对的公钥发送给CA机构
3.CA机构用CA自己的私钥对消息接收者的公钥施加数字签名
4.CA机构通过上一步生成的数字签名和消息接收者的公钥生成公钥证书
使用证书
1.消息发送者从CA机构获取到指定的公钥证书
2.消息发送者通过预置的CA机构的公钥验证公钥证书的合法性
- 使用哈希函数对公钥证书中的公钥进行单向散列求得散列值A
- 使用预置的CA机构的公钥解密公钥证书的数字签名获得散列值B
- 对比散列值A和散列值B是否相等,相等则说明公钥合法,否则不合法
3.消息发送者使用证书中的公钥对传输的会话密钥(对称密钥)进行加密(采用混合密码系统)
HTTPS中的证书就是指CA证书
iOS签名机制
一些概念
在了解iOS签名机制之前,我们必须先对齐一些概念,以及每个概念背后的意义。这些概念主要包括:
- .certSigningRequest
- .cer
- .mobileprovision
- Entitlements
- p12
Mac公钥证书(.certSigningRequest)*
.certSigningRequest文件是以certSigningRequest作为后缀名的文件,也就是我们常说的CSR文件。CSR文件是从macOS的钥匙串的证书助理中通过证书颁发机构请求的公钥证书*。Mac作为证书颁发机构,生成的密钥对默认采用RSA算法,密钥大小默认2048位。
Apple证书(.cer)
- 利用Apple私钥(CA)对Mac的公钥(CSR)进行签名后获得的公钥证书
- .cer证书主要包括两个元素:明文的Mac公钥、Mac公钥的签名(用Apple私钥对Mac公钥签名)
描述文件(.mobileprovision)
- 利用Apple私钥对【Apple证书+iOS devices+appId+app权限文件entitlements】进行签名
- 描述文件包括【Apple证书+iOS devices+appId+app权限文件entitlements】以及以上信息的数字签名
所以,描述文件最终描述(限制)了:证书、iOS devices、appId、app的权限。
描述文件是开发期使用的文件,App Store下载的App不存在描述文件。
权限列表(Entitlements)
权限列表包含了 App 拥有的所有权限,比如消息push权限、后台运行权限。
p12
p12本质是Mac本地私钥的另一种形式,可以在钥匙串访问(Keychain Access)中导出p12文件给其他Mac设备,其他Mac设备把p12安装到自己的钥匙串中后就可以进行身份伪装。
传统真机调试
在Xcode6之前,不管是真机调试,还是发布APP,开发者都需要按年购买一个付费的Apple ID,在开发一个新的App时,需要去Apple后台执行一系列复杂的配置步骤,目的就是要生成一个iOS开发证书和一个对App的描述文件,操作步骤如下:
- Mac上生成CSR文件(默认名为CertificateSigningRequest.certSigningRequest)
- 使用付费的开发者账号(Apple ID)登录Apple开发者后台
- Apple 后台上传CertificateSigningRequest.certSigningRequest文件
- 下载Apple证书,可能是ios_development.cer(开发证书)或 ios_distribution.cer(发布证书)
- 获取iOS设备的UDID,Apple后台通过UDID注册Devices
- Apple后台添加一个App ID
- 通过勾选Apple证书、Devices、App ID、entitlements配置一个*.mobileprovision文件
- 下载*.mobileprovision文件
- 安装Apple证书和*.mobileprovision文件
模拟器调试则不需要执行以上配置,也不需要在Xcode添加Apple ID。对于真机调试,现在的Xcode会自动帮开发者执行以上操作。所以,非必要情况下,大多数开发场景是不涉及到以上繁琐的配置的。
App分发方式
Apple根据iOS App安装渠道来源的不同,对App的签名方式有所区别。通常App的安装渠道可以分为:
- App Store。应用市场分发。对Apple用户分发的线上正式的App。不限制用户数量。
- In-House。企业内部分发。可以直接安装企业证书签名后的App。不限制用户数量。
- AD-Hoc。企业内部分发的限制版。限制App安装设备的数量,通常用于内部小范围使用或测试,使用场景有限。
- Xcode。开发者分发。通过Xcode编译App源代码,将编译成功的App安装到手机上。
App Store分发
App Store签名是最简单的签名方式。只需要保证用户安装的App来源是App Store且被Apple认可的。
要实现这个需求很简单,最直接的方式,苹果官方生成一对公私钥,在 iOS 系统里内置一个Apple公钥,私钥由苹果后台保存,我们传 ipa 到 AppStore 时,苹果后台用私钥对 App 数据进行签名,iOS 系统下载这个 App 后,用预置的Apple公钥验证这个签名,若签名正确,说明这个 App 肯定是由苹果后台认证的,并且下载和安装过程中都没有修改过App,也就达到了苹果的需求:保证安装的每一个 APP 都是经过苹果官方允许的。事实上,Apple也是这么做的。Apple会对我们提审App Store的App进行重签名,所谓重签名就是对开发者提审的ipa包中的App进行重签,重签发生在Apple的后台,使用的Apple自己的私钥。具体重签流程后面介绍,这里仅作为了解。
线下分发
上面App Store对应用市场分发的App进行签名,很好的保证了App的安全性。但我们知道,除了App Store分发的应用外,还有其他三种应用分发方式:In-House、AD-Hoc、Xcode。这三种方式生成的App文件不会上传到App Store,但Apple还是要兼顾这些法外之地的App的合规性和安全性,对这些App的安装和使用享有绝对的控制权。所以Apple还需要添加其他手段来验证这些非App Store分发的App。这里就引出了上面所说的描述文件——mobileprovision profile。
描述文件其实是Apple对App二次签名的产物。苹果想要对线下安装的App享有控制权,包括:
- 经过苹果允许才可以安装使用App。
- 指定的设备才能安装使用线下分发的App。
- 指定设备只能安装指定的App,设备不能安装非开发期的App。
如上,第一条,苹果想要控制经过许可才可以线下安装App。通过我们对签名和证书的认识,这个实现很简单。其步骤大致如下:
- Mac设备生成一对公私钥。Mac私钥仅Mac本地持有,开发者将Mac公钥上传到Apple后台。
- Apple后台用Apple的私钥对开发者上传的Mac公钥进行签名,并生成一个Apple证书。
- 开发者从Apple后台下载Apple证书,并将Apple证书安装到Mac本地。
- 在Xcode编译App或对App重签名时,用Mac本地的私钥对这个App进行签名,同时把第三步得到的Apple证书一起打包进App 中,然后安装到手机上。
- 在手机安装App时,iOS 系统从App中读取出第三步的Apple证书,然后通过系统内置的Apple公钥,去验证Apple证书的数字签名的正确性。
- 验证证书后确保了Mac公钥是苹果认证过的,再用Mac公钥去验证 App的签名(因为App是使用Mac私钥签名的,所以可以使用Mac公钥验证签名),如果Mac公钥验证App的签名是正确的,就说明App没有被篡改过,这里就间接验证了这个 App 安装行为是否经过苹果官方允许。(这里只验证安装行为,不验证App 是否被改动,因为开发阶段 App 内容总是不断变化的,苹果不需要管。)
简化的流程图大致如下:
上述流程只解决了上面第一个需求,也就是经过苹果允许才可以安装使用App,还未解决第2、3个问题(2.指定的设备才能安装使用线下分发的App 3.指定设备只能安装指定的App,设备不能安装非开发期的App)。怎么解决呢?苹果再加了两个限制,一是限制在Apple后台注册过的设备才可以安装App,二是限制签名只能针对某一个具体的 App(也就是Bundle ID)。
怎么加的?在上述第2步,苹果用私钥签名我们本地公钥时,实际上除了签名公钥,还可以加上无限多数据(比如Devices、Bundle Id),这些数据都可以保证是经过苹果官方认证的,不会有被篡改的可能。
可以想到把 允许安装的设备 ID 列表 和 App对应的 AppID 等数据,都在第三步这里跟Mac公钥一起组成证书,再用苹果私钥对这个证书签名。在最后第 5 步验证时就可以拿到设备 ID 列表,判断当前设备是否符合要求。根据数字签名的原理,只要数字签名通过验证,第 5 步这里的设备 IDs / AppID / 公钥 L 就都是经过苹果认证的,无法被修改,苹果就可以限制可安装的设备和 App,避免滥用。
实际上一个“公钥证书”本来就有规定的格式规范,公钥证书,顾名思义就是对公钥的签名,上面我们把各种额外信息塞入证书里是不合适的,于是苹果另外加了一个文件,叫 Provisioning Profile,一个 Provisioning Profile 里就包含了证书以及上述提到的所有额外信息,以及所有信息的签名。这也是苹果二次签名(1. 对Mac公钥签名 2. 对Apple证书+Devices+Bundle ID+Entitlements签名)的原因。
至此,我们知道了,Apple想限制安装App的设备和限制安装的App,于是增加了描述文件,描述文件其实是对Apple证书、Devices、 App Id、Entitlements等条款的签名。
如下图,是笔者画的iOS开发期的详细的签名和验签的流程。其中涉及到Mac公钥(CSR文件)、Mac私钥、Apple公钥(提前预置到iOS设备中)、Apple私钥(用于对Mac公钥签名)、Apple证书、mobileprovison文件。下面详细介绍签名和验签的步骤。
签名过程
- Mac公钥上传到Apple后台进行签名,生成Apple证书
- Apple证书和App ID(bundle ID)、Devices(iOS设备列表)、Entitlements(App权限列表)进行组装
- Apple后台使用Apple私钥对上面组装的信息进行签名,生成一个后缀名为mobileprovision(描述文件)的文件
- Xcode 编译项目生成App文件,然后使用Mac私钥对App进行签名
- 上面第3、4步生成的.mobileprovision、签名后的App共同组成了IPA安装包
验签过程
- iOS设备通过预置的Apple公钥验证描述文件
- iOS设备通过预置的Apple公钥验证Apple证书
- iOS设备通过第2步获取的Mac公钥验证App
这里再次不厌其烦的赘述下最终的流程:
- 在你的 Mac 开发机器生成一对公私钥,这里称为公钥L,私钥L。L:Local
- 苹果自己有固定的一对公私钥,跟上面 AppStore 例子一样,私钥在苹果后台,公钥在每个 iOS 设备上。这里称为公钥A,私钥A。A:Apple
- 把公钥 L 传到苹果后台,用苹果后台里的私钥 A 去签名公钥 L。得到一份数据包含了公钥 L 以及其签名,把这份数据称为公钥证书。
- 在苹果后台申请 App ID,配置好设备 UDID 列表和 App 可使用的权限,再加上第③步的证书,组成的数据用私钥 A 签名,把数据和签名一起组成一个 Provisioning Profile 文件,下载到 Mac 设备本地。
- 在开发时,编译完一个 App 后,用本地的私钥 L 对这个 App 进行签名,同时把第④步得到的 Provisioning Profile 文件打包进 APP 里,文件名为
embedded.mobileprovision
,把 APP 安装到手机上。 - 在安装时,iOS 系统通过iOS设备内置的公钥 A,去验证
embedded.mobileprovision
的数字签名是否正确,里面的公钥证书签名也会再验一遍。 - 确保了
embedded.mobileprovision
里的数据都是苹果授权以后,就可以取出里面的数据,做各种验证,包括用公钥 L 验证App签名,验证设备 ID 是否在 ID 列表上,AppID 是否和Apple后台配置的Bundle ID对应得上,权限开关是否跟 App 里的 Entitlements 对应等。如果上述数据都能够对应的上,说明这个App的数据没有被篡改,允许安装。
为什么从App Store下载安装的App没有mobileprovison文件?
App发布的时候做了一系列的合法性验证(三次签名),当我们把App上传到App Store后,苹果会用他自己的私钥对app进行重签名。 这样从app Store下载的app验证流程就变简单了:iOS 设备只需要用Apple预置的公钥验证下载的App的数字签名。签名验证通过说明App没有被篡改过,这样就保证了App渠道的合法性和App的安全性。
为什么我们发布到App Store的App必须要被Apple重签名?
因为发布到App Store的App需要安装到很多用户手机上,也要保证用户安装的App没有证书过期的问题。这样对证书有效期、可安装的Devices列表都有不一样的要求。所以,App Store 的签名验证方式和Xcode线下开发以及企业分发的App的验证方式不一样。我们上传到App Store的App会被Apple重签名,其重签名的思路大致是:①先对ipa中的描述文件embedded.mobileprovision进行验证,此步骤可以获得Apple证书,②然后再验证Apple证书,此步骤可以获得Mac公钥③再用上面一步获得的Mac公钥验证App是否被篡改过。如果以上三步都通过,则Apple会使用自己的Apple私钥对App文件进行重签名。这样用户从App Store下载的App就不会有embedded.mobileprovision
文件,也就是它安装和启动的流程是不依赖这个文件,验证流程也就跟Xcode、In-House、AD-Hoc的验证流程不一样了。
所以 App 上传到 AppStore 后,就跟你的Apple开发证书、Provisioning Profile 都没有关系了,无论他们是否过期或被废除,都不会影响 App Store 上的安装包。
那为什么发布 AppStore 的包还是要跟开发版一样搞各种证书和 Provisioning Profile?
iOS App 签名的原理中说“猜测因为苹果想做统一管理,Provisioning Profile 里包含一些权限控制,AppID 的检验等,苹果不想在上传 AppStore 包时重新用另一种协议做一遍这些验证,就不如统一把这部分放在 Provisioning Profile 里,上传 AppStore 时只要用同样的流程验证这个 Provisioning Profile 是否合法就可以了。”
上面的猜测比较合理。笔者这里的补充是Apple需要对开发者上传大App Store的包进行验证。即保证开发者上传过程中App的文件信息没有被中间人攻击,所以这里Apple还是要求开发者将App带着各种证书和签名上传到Apple后台,Apple后台再以拆快递的方式对ipa包进行各种合法性校验验证通过后再重签名。
越狱中的重签名
非越狱手机才会验证App的数字签名。越狱手机可以随意安装各种App且不会验证签名,相当于没有了安全验证机制。所以如果越狱开发者把篡改后的App安装到越狱手机,则不需要对App重签名。 所以,改完的被篡改过mach-O的app文件不需要重签名就可以运行在越狱手机上。
正因为非越狱手机会验证App的数字签名,所以如果想把被修改过的app安装到非越狱手机上,需要对app进行重签名,目的就是让被篡改过的App可以通过设备的对数字签名的层层校验。
通常我们对App重签名的方式有:
- 手动重签名
- iOS App Signer重签名
- fastlane脚本重签名
- MonkeyDev重签名
参考文章
《图解密码技术》
RSA 算法原理(一)(二)
常见加密算法分类
《图解密码技术》读书笔记
iOS App 签名的原理