在iOS开发过程中,不可避免的要和证书打交道,真机调试、App上架、打包给测试去测试等都需要搞证书。在此过程中我们会遇到很多的问题,但是如果掌握了真机调试的原理和本质;遇到问题,我们就更容易定位问题之所在,从而迅速的解决问题。
知识点补充:
摘要算法:
摘要算法是指,可以将任意长度的文本,通过一个算法,得到一个固定长度的文本。这里文本不一定只是文本,可以是字节数据。所以摘要算法试图将世间万物,变成一个固定长度的东西
1.只要源文本不同,计算得到的结果,必然不同
2. 无法从结果反推出源(那是当然的,不然就能量不守恒了)
MD5和SHA。摘要算法主要用于比对信息源是否一致,因为只要源发生变化,得到的摘要必然不同;而且通常结果要比源短很 多,所以称为“摘要”。
数字证书(digital certificate)
证书生成
开发者在申请iOS开发证书时,需要通过keychain生成证书签名请求 (CSR) 文件 (*.certSigningRequest),生成 CSR 会创建公钥、私钥以及 *.certSigningRequest 文件。公钥包含在 CSR 中,私钥用于为请求签名。提交给苹果的 Apple Worldwide Developer Relations Certification Authority(WWDR)证书认证中心进行签名,最后从苹果官网下载并安装使用。,证书中的用户的这个公钥与我本机的私钥是对应的。当我们双击安装完证书后,KeyChain会自动将这对密钥关联起来,所以在KeyChain中可以看到类似的效果::
CertificateSigningRequest.certSigningRequest文件:
1.申请者信息,此信息是用申请者的私钥加密的
2.申请者公钥,此信息是申请者使用的私钥对应的公钥
3.摘要算法和公钥加密算法
WWDR (Apple Worldwide Developer)是我们从苹果MC中申请的所有证书的“根证书”,安装这个证书意味着我们的开发工具对此CA的信任,从而可以用此CA签发的其他证书进行签名和打包。一般而言,如果安装了Xcode,那么这个证书是自动安装在Key Chain中了。证书如下图
证书签名请求 (CSR) 文件的生成过程
(1)打开Keychain(钥匙串),点击菜单栏“钥匙串访问”->“证书助理”->“从证书颁发机构请求证书”
填写开发账号邮件和常用名称,勾选“存储到磁盘”。
继续并选择存储位置后,Keychain将生成一个包含开发者身份信息的CSR(Certificate Signing Request)文件。同时,Keychain Access->Keys(密钥)中增加一对Public/Private Key Pair。
私钥(private key)始终保存在Mac OS的Keychain Access中,用于签名(CodeSign)对外发布的App。
公钥(public key)一般随证书散布出去,对App签名进行校验认证。
数字签名(digital signature)
假设,我们有一段授权文本,需要发布,为了防止中途篡改文本内容,保证文本的完整性,以及文本是由指定的权限狗发的。首先,先将文本内容通过摘要算法,得到摘要,再用权限狗的私钥对摘要进行加密得到密文,将源文本、密文、和私钥对应的公钥一并发布即可。那么如何验证呢?
验证方首先查看公钥是否是权限狗的,然后用公钥对密文进行解密得到摘要,将文本用同样的摘要算法得到摘要,两个摘要进行比对,如果相等那么一切正常。这个过程只要有一步出问题就视为无效。
数字签名可以快速验证文本的完整性和合法性,已广泛应用于各个领域。理解了数字签名以后,我们进一步来看什么是数字证书。
非对称加密的用途之一:
身份验证和防止篡改:权限狗用自己的私钥加密一段授权明文,并将授权明文和加密后的密文,以及公钥一并发送出来,接收方只需要通过公钥将密文解密后与授权明文对比是否一致,就可以判断明文在中途是否被篡改过。此方法用于数字签名。
数字证书组成
经过WWDR数字签名后的数字证书长这个样子:
其中包含两大部分:
· 证书本身
包含用户的公钥、用户个人信息、证书颁发机构信息、证书有效期等信息。
· 证书签名
WWDR将上述证书本身内容的使用哈希算法得到一个固定长度的信息摘要,然后使用自己的私钥对该信息摘要加密生成数字签名,整个过程如图所示:
数字证书使用
iOS系统原本就持有WWDR的公钥,系统首先会对证书内容通过指定的哈希算法计算得到一个信息摘要;然后使用WWDR的公钥对证书中包含的数字签名解密,从而得到经过WWDR的私钥加密过的信息摘要;最后对比两个信息摘要,如果内容相同就说明该证书可信。整个过程如图所示:
在验证了证书是可信的以后,iOS系统就可以获取到证书中包含的开发者的公钥,并使用该公钥来判断代码签名的可用性了。
证书存在的意义
通过证书使用过程可以看出,证书本身只是一个中间媒介,iOS系统对证书并不关心,它其实只想要证书中包含的开发者的公钥!!
但是开发者怎么才能证明公钥是自己的呢?iOS安全系统怎么才能相信这个公钥就是这个开发者的呢?
不管是哪一个开发者对iOS的安全系统说,这个公钥就是我的,系统是都不相信的,即系统对开发者有着百分之百的不信任感。但是iOS安全系统对自家的WWDR是可信任的,苹果将WWDR的公钥内置在了iOS系统中。有了证书,iOS安全系统只需要通过WWDR的公钥就可以获取到任何一个开发者的可信任的公钥了,这就是证书存在的意义!!
三、公钥(public key)
公钥被包含在数字证书里,数字证书又被包含在描述文件(Provisioning File)中,描述文件在应用被安装的时候会被拷贝到iOS设备中。
iOS安全系统通过证书就能够确定开发者身份,就能够通过从证书中获取到的公钥来验证开发者用该公钥对应的私钥签名后的代码、资源文件等有没有被更改破坏,最终确定应用能否合法的在iOS设备上合法运行。
四、私钥(private key)
每个证书(其实是公钥)都对应有一个私钥,
私钥会被用来对代码、资源文件等签名。只有开发证书和描述文件是没办法正常调试的,因为没有私钥根本无法签名。
此后的内容基本都是从《代码签名探析》摘抄过来的笔记,建议大家看原文好了。
通过私钥加密的密文只能通过公钥解密,公钥加密的密文只有通过私钥解密
开发者证书分为三种
1) Developer Certification(开发证书)
安装在电脑上提供权限:开发人员通过设备进行真机测试。
可以生成副本供多台电脑安装;
2) Distribution Certification(发布证书)
安装在电脑上提供发布iOS程序的权限:开发人员可以制做测试版和发布版的程序。
不可生成副本,仅有配置该证书的电脑才可使用;
上面提到的证书副本就是通过配置证书的电脑导出Keychain(就是.p12文件)安装到其他机子上,让其他机子得到证书对应的权 限。Developer Certification就可以制做副本Keychain分发到其他电脑上安装,使其可以进行真机测试。
注意:Distribution Certification只有配置证书的电脑才可使用,因此即使导出导出Keychain安装到其他电脑上,其他电脑也不可能具有证书的权限。
开发证书和发布证书每种最多有3个,无法创建更多了。
3) Push Notifications Certification(推送证书)
下面详细讲解下推送证书的生成步骤:
有两种方式,
<1>.一个是在APPID里面 Edit 设置里打开 Push notifications 功能,此时此功能的状态是 Configurable(可配置)状态。
分别在为开发环境下的推送证书、发布环境下的推送证书上传你电脑导出的 证书签名请求 (CSR) 文件即可,全部添加后功能的状态会变成 Enabled状态。
<2>.通过为指定APPID设置 测试、生产环境下的推送证书来实现。
选择开发证书或者生产证书,这里以生产证书为例,继续
选择App ID,即我们在“ Identifiers”中创建的App ID,继续
这里需要添加生成的证书请求文件(CSR),“Choose File”选择生成的.certSigningRequest文件,点击“Generate”。
我们可以点击“Download”下载该开发证书,或者在“Certificates”->“All”中查看该证书,并进行下载或删除,如图:
下载证书,双击导入Keychain Access,可在Keychain Access->“证书”中查看
展开安装的证书(ios_development.cer)前面的箭头,可以看到其对应的私钥。在KeychainAccess->“密钥”中展开创建CSR时生成的Key Pair中的私钥前面的箭头,可以查看到包含其对应公钥的证书.
打开Keychain Access,选择安装成功的证书,右键选择“导出”
输入名字,默认格式为.p12类型,选择“Save”
设置密码,点击“OK”
自此指定APPID的推送证书便生成并导出完毕。
下面这种开发打包过程中遇到的问题是因为 WWDR 证书过期了,需要删掉旧的WWDR 证书,重新下载新的根证书安装即可:
Provisioning Profiles(mobileprovision文件)
有新的设备加进来之后,不用更新证书,只需 到开发者中心那里,编辑你之前使用的 配置文件,重新把新设备的UDID 包含进来,然后重新下载,在本地双击安装即可(双击后自动更新了本地同名的配置文件)。
iPad 的UDID 的获取方法跟 iPhone的方式一样。
mobileprovision文件包含:
AppId。每个app必须在MC中创建一个对应的AppId。
使用哪些证书。上面说了,不同类型的证书就代表了不同的发布方式,还包括一些功能的能否使用(比如APN)
功能授权列表
可安装的设备列表。对于AdHoc方式发布的app或者真机调试时,会有一个列表,这个列表里面是iOS设备的UDID,每台iOS设备出厂的UDID都不同,所以可以用来标识设备。可通过iTunes连接设备,或者http://fir.im/udid这里获取
苹果的签名!
注意5,这里的签名是苹果签的,跟我们的私钥没有关系。也就是说mobileprovision文件是苹果签名的,我们除了从MC中获取,别无他法。也不能再获取后随意篡改(比如添加别的设备)。因此上面的1-4就被苹果牢牢的控制在手里,所有的规则都必须由苹果来制定和约束。
描述文件描述了可由哪台电脑,把哪个App,安装到哪台手机上面。一个描述文件的制作是需要上面的一些信息的。所以苹果在Member Center中把这个文件的制作排在最后面是很合理的。描述文件其实可以分为两种类型,一种是带有device信息的;而另一种是不带device信息的。
带device信息的描述文件
这种类型的描述文件包括所有开发类型的描述文件和发布到Ad Hoc上面的描述文件,因为做这些事情的时候,都有很明确的目的,这个App要安装到哪台设备上面。
不带device信息的描述文件
不带device信息的描述文件只有发布到App Store和In House两种情况下才使用这个描述文件,因为通过这两个渠道发布的App我们是不能确定将来那一台设备才会安装,只让也就不会带有App的信息。
ipa的组成
iOS程序最终都会以.ipa文件导出,先来了解一下ipa文件的结构:
事实上,ipa文件只是一个zip包,可以使用如下命令解压:
/usr/bin/unzip -q xxx.ipa -d
解压后,得到上图的Payload目录,下面是个子目录,其中的内容如下:
资源文件,例如图片、html、等等。
_CodeSignature/CodeResources。这是一个plist文件,可用文本查看,其中的内容就是是程序包中(不包括Frameworks)所有文件的签名。注意这里是所有文件。意味着你的程序一旦签名,就不能更改其中任何的东西,包括资源文件和可执行文件本身。iOS系统会检查这些签名。
可执行文件。此文件跟资源文件一样需要签名。
一个mobileprovision文件.打包的时候使用的,从MC上生成的。
Frameworks。程序引用的非系统自带的Frameworks,每个Frameworks其实就是一个app,其中的结构应该和app差不多,也包含签名信息CodeResources文件
iOS设备如何验证app是否合法
关键的几个点:
解压ipa
取出embedded.mobileprovision,通过签名校验是否被篡改过
其中有几个证书的公钥,其中开发证书和发布证书用于校验签名
BundleId
授权列表
校验所有文件的签名,包括Frameworks
比对Info.plist里面的BundleId是否符合embedded.mobileprovision文件中的
总结
苹果通过证书来授权开发者开发iOS应用,不同的证书具有不同的用处,建议申请时使用相同的请求文件(即保证私钥统一)。可以通过共享私钥的方式让团队使用相同的私钥和证书,已方便开发。为了保证app的安全性,app中所有的文件都会被签名,这样,签过名的app除非重新签名,否则无法改动其中的任何东西。
mobileprovision是一个配置文件,由苹果签名并发布给开发者。配置文件是一组信息的集合,这组信息决定了某一个应用是否能够在某一个特定的设备上运行。配置文件可以用于让应用在你的开发设备上可以被运行和调试,也可以用于内部测试 (ad-hoc) 或者企业级应用的发布。有了配置文件,苹果对开发者的约束就十分稳固了。所以,证书(及其对应的私钥)和配置文件是签名和打包的两个必要文件。必须深刻理解,才能在日常的错误中找到解决办法。