最近遇到一个签名的问题,借机把iOS签名相关知识点研究了一下。现总结以下:(研究过程当中参考了这位仁兄的博客。很全面,本文也有部分借鉴)html
非对称加密ios
这个是签名机制的算法基础。所谓非对称加密的是相对于对称加密来讲的。对称加密是加密方和解密方约定一个相同的密钥和加解密算法。只要获取了这个密钥,则能够破译加密内容。这种加密方法下,假如我要和3我的通讯,就须要和三我的分别约定好3个不一样的密钥,否则这三我的就没办法鉴别消息是由我本人加密的。git
而非对称加密则是采用了一对密钥(私钥和公钥)。经过公钥加密的内容只能经过私钥解密,而经过私钥加密的内容也只能经过公钥解密。通常公钥是公开的,私钥本身保存。经过这种加密方式,能够鉴别加密内容是否由私钥持有者进行加密,从而验证对方身份。这种加密方法下:假如我要和3我的通讯,只须要这三我的知道个人公钥便可。只要能经过个人公钥解密便可认为消息是由我进行加密。而3我的中任何一我的加密的内容,只能由我来解密。固然这种状况下,我就没办法鉴定这三我的的真实身份了。github
摘要(Hash)算法
摘要技术也称为哈希技术,是将任意长度的数据一一映射到一个固定长度数据的技术,而且获得的摘要数据是不可逆的。只要原始数据不同,则获得的摘要也会不同;原始数据同样,摘要当然也同样。所以摘要技术能够用来验证数据是否被篡改。xcode
常见的摘要算法有SHA1(160bit),SHA256(256bit),SHA512(512bit)等等app
数字签名工具
数字签名其实就是摘要技术和非对称加密的应用。当发送方要发送一段数据给别人时,为了让接受者能对接受到的数据进行验证,确保数据没有被篡改过。ui
1. 发送方会同时为数据生成摘要,并用私钥进行加密。加密
2. 接收方会同时受到数据和加过密的摘要,经过将加密摘要用公钥进行解密
3. 接收方将数据也经过摘要算法进行摘要,和第2步中获得的摘要进行对比,若是一致,能够证实数据没有被篡改过。不然即数据被篡改。
下图描述了上面的场景
数字证书
上面说过非对称加密机制里公钥是公开的,数字证书就是其公开形式。私钥持有者将其我的(或组织)信息与公钥信息提交给证书颁发机构,证书颁发机构用本身的私钥将所提交的信息进行数字签名,而后生成数字证书。这个证书就是私钥持有者在认证机构的体系下身份标示。也是获取其公钥的途径。这里其实还有点隐藏起来的知识点,证书颁发机构用他的私钥签名,那如何验证这个签名呢?只有验证了签名才能验证证书的真伪啊。秘密就藏在操做系统的授信证书库中。
1. 要验证证书的签名,须要证书颁发机构的公钥
2. 证书颁发机构的公钥通常会内置在操做系统中,或者自行导入证书颁发机构证书(包含其公钥)。
这样一来,这个信任链条就完整了。
广泛使用的数字证书格式是X.509格式,文件格式是.cer。还有一种包含了私钥的证书.pfx(或.p12)。好比咱们在key chain中把包含私钥的证书导出会生成.p12文件,就是包含私钥的。这种通常用于本身将证书和私钥移植到别的机器。
好,上面已经把iOS签名机制的基础知识进行铺垫了。接下来看看iOS开发过程当中的签名究竟是怎么回事。
苹果开发者数字证书
要签名,必需要有私钥,公钥对。所以作iOS开发首先要去苹果开发者中心去申请我的证书。申请方式是:
1. 经过Key Chain的Certificate Assistant产生一个CSR(Certificate Signing Request)文件。在生成CSR的时候须要填写邮箱和Common Name.这就是你的我的信息。
2. 而后系统会产生一对密钥对,私钥保存在key chain中,公钥写入CSR文件。
3. 在苹果开发者中心将CSR文件上传,他会产生一个数字证书(苹果在证书中会添加Team相关的信息)。这个证书就是你在苹果认证体系中的我的身份了。在后续的签名中也会用到该证书。当你下载并安装该证书后,系统会自动将该证书的公钥与系统中的私钥配对。所以你再key chain中的证书列表中会看到证书关联了一个私钥。
证书的信息长这样:
各类证书(App Store,Ad-Hoc,development)
Provisoning文件
有了证书后能够用来签名了,可是问题来了: 当咱们对app签名的时候,总不能容许任意一个的开发者证书来签名吧。所以苹果的解决办法是Provisioning文件,该文件中记录了容许被用来签名的证书列表。同时该文件还记录了app的bundle id,容许运行的设备列表(ad-hoc发布的时候有用),以及app可使用的苹果的一些服务列表。在生成该文件时,苹果会用本身的私钥生成签名。开发者须要在开发者中心生成该文件而后下载到本地。在打包app的时候该文件会一块儿打包进ipa文件,在app运行的时候根据他对app进行合法性检查。
XCode签名配置
1. 在Target的配置界面General/Signing节点中,能够选择Automatically Manage Signing.勾选该选项后,XCode会去自动为你产生证书,Profile文件,前提是你要在XCode中登陆你的开发者帐号(通常开发阶段能够选择此种方式)
2. 在Signing(Debug)/Signing(Release)节点中,能够选择Provisioning文件,前面说过该文件里面存储了可用来签名(签名其实用的时证书中公钥所对应的私钥)的证书信息。所以选择了Provisioning文件后,XCode会自动去key chain中寻找本地存在的证书和私钥。(若是本地没有对应的证书和私钥,则会报错)
若是本地有多个可用证书,可在BuildSetting配置 Tab里面的Signing节点进行进一步选择。
Framework签名配置
项目中Framework Project是不须要设置签名信息的,由于他会在引用它的主项目中进行签名,固然也是用的主项目的签名配置信息。
XCode签名流程
XCode在签名app时会:
1. 为每一个文件生成摘要信息(这里包括provisioning文件),而后用签名证书对应的私钥进行签名
2. 将每一个文件对应的签名信息存储在app包的_CodeSignature\CodeResources文件内
3. 对于Framework,其本质其实也是一个包文件(和app同样)。XCode会对他里面的全部文件进行签名而后签名信息放在Framework包文件内的_CodeSignature\CodeResources文件内。
具体流程见下图:
最后获得的ipa文件内部是这个样子的:
相关工具
上面XCode签名流程中用到了两个工具: codesign和zip
1. codesign是真正用来执行签名工做的工具。它提供签名,验证签名,显示签名信息等等功能。XCode在执行签名的时候实际上是调用该工具。
2. zip是压缩工具。用它能够将app包文件进行压缩。(ipa文件格式只是将压缩文件改了个扩展名而已)
3. 同时XCode Command Line Tool中提供了一个PackageApplication的可执行程序,这个程序接收provisioning file和证书做为参数,能够对app进行替换provisiong file和重签名(只对app包进行重签名,内置的Framework不会重签)。具体用法能够
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/PackageApplication -man来查看。可是该工具在最新的XCode中已经被移除。推荐使用xcodebuild -exportArchive来生成ipa.
详见https://developer.apple.com/library/content/technotes/tn2339/_index.html
苹果设备App合法性验证
当iOS设备安装app时,会执行以下操做:
1. 解包ipa文件
2. 拿出provisioning file,经过内置的苹果公钥验证provisioning file的合法性。(Provisioning file是被苹果用私钥签过名的)
3. 根据provisioning file中的信息验证app的合法性。确保provisoning file记录的信息和app信息一致(好比bundle id)
4. 从provisioning file中得到签名的证书
5. 经过苹果公钥(iOS系统内置)来验证证书合法性(证书是被苹果私钥签名的)
6. 经过证书中的公钥来验证每一个文件的摘要信息,确保每一个文件都没有被篡改过。
重签名工具
其实只要有了provisioning file,证书咱们能够把一个ipa重签名为任何其余名称(provisioning file中定义)的app。只需将ipa解包,而后按照XCode的流程对app从新进行签名便可。下面的工具便可实现。(经过这种途径理论上能够修改ipa的文件而后从新用新的bundle id安装。这样至关于hack了app。)
https://github.com/lbwxly/ios-app-signer