iOS App签名原理和HTTPS证书原理

前言

先来看看苹果的签名机制是为了做什么。在 iOS 出来之前,在主流操作系统(Mac/Windows/Linux)上开发和运行软件是不需要签名的,软件随便从哪里下载都能运行,导致平台对第三方软件难以控制,盗版流行。苹果希望解决这样的问题,在 iOS 平台对第三方 APP 有绝对的控制权,一定要保证每一个安装到 iOS 上的 APP 都是经过苹果官方允许的,怎样保证呢?就是通过签名机制。

非对称加密

可以说有计算机的地方就有非对称加密,我们平时说到的数字签名,就是非对称加密实现的。相对于对称加密,一个秘钥用来加密和解密,非对称加密会有已对公私钥,公钥加密只有私钥能解密,私钥加密只有公钥能解密。有很多种,比如RSA,ECC,DH,一般的RSA加密算法就是私钥加密,公钥解密,只要保证私钥不泄露,一般是很安全的。这里有两个文章详细介绍了RSA非对称加密的原理。
阮一峰RSA介绍

数字签名

可以想象现实中,一份文件的签名只要是客户画押或者签字,就能代表这份文件是出自某个客户,而且是被客户所认证过的。那么计算机中的签名也一样,通过对一段数据进行签名,传递给别人,别人就知道这份数据是出自我想要的那个人发给我的,而且是没有被篡改的。

那么有了非对称加密,就能实现这个数字签名:
在这里插入图片描述
1、首先要有一直摘要算法,针对同一份数据的摘要是一致的,而且数据有一点改动,摘要完全不同,而且长度足够短,因为RSA非对称加密的值不能太大。这里我们常用的就是SHA256活着MD5

2、作为签名方,私钥自己拿着,公钥发给需要接受数据的人

3、一般将原始数据进行摘要算法,然后用私钥加密,最后生成的签名和原始数据一同发给接收方

4、用户收到数据和签名后,用公钥解密得到摘要。同时用户用同样的算法计算原始数据的摘要,对比这里计算出来的摘要和用公钥解密签名得到的摘要是否相等,若相等则表示这份数据中途没有被篡改过,因为如果篡改过,摘要会变化。

HTTPS证书原理

有了上面非对称加密的了解和什么是数字签名后,我们来看看HTTPS的整个过程是怎么样的。
分为证书制作和证书认证过程,先看下图
在这里插入图片描述

证书制作过程

1.服务方S向第三方机构CA提交公钥、组织信息、个人信息(域名)等信息并申请认证;

2.CA通过线上、线下等多种手段验证申请者提供信息的真实性,如组织是否存在、企业是否合法,是否拥有域名的所有权等;

3.如信息审核通过,CA会向申请者签发认证文件-证书。 证书包含以下信息:申请者公钥、申请者的组织信息和个人信息、签发机构 CA的信息、有效时间、证书序列号等信息的明文,同时包含一个签名; 签名的产生算法:首先,使用散列函数计算公开的明文信息的信息摘要,然后,采用 CA的私钥对信息摘要进行加密,密文即签名;

注意点:
服务器自己有一套公钥私钥,传输是不安全的,因此介入了CA权威机构,申请的时候把公钥给CA进行验证,然后CA拿着公钥一起其他信息弄成证书。先把证书理解成一段数据,然后把这个数据进行HASH摘要算法,然后CA公司有自己的私钥,拿着这个私钥把摘要进行RAS加密,加密后的数据就是签名。因此证书就是明文公钥等其他信息,加上CA公司用他们自己私钥签名的一个文件。详细可以看上面的证书图

证书验证过程

在这里插入图片描述
SSL握手

首先明白网络各层的协议和作用,可以参考文章头部的链接。SSL握手是发生在TCP三次握手之后的

第一阶段:ClientHello

客户端发起请求,以明文传输请求信息,包含版本信息,加密套件候选列表,压缩算法候选列表,随机数random_C,扩展字段等信息。

第二阶段:ServerHello-ServerHelloDone

如上图可以看出这个阶段包含4个过程( 有的服务器是单条发送,有的是合并一起发送)。服务端返回协商的信息结果,包括选择使用的协议版本,选择的加密套件,选择的压缩算法、随机数random_S等,其中随机数用于后续的密钥协商。服务器也会配置并返回对应的证书链Certificate,用于身份验证与密钥交换。然后会发送ServerHelloDone信息用于通知服务器信息发送结束。

这里1和2的随机数现在客户端和服务端都有了,后续会用到

第三阶段:证书校验

客户端这边还需要对服务器返回的证书进行校验。只有证书验证通过后,才能进行后续的通信。

简单介绍下:

1.明白证书的组成,就是上面那段介绍证书制作的过程,服务器把证书传输给客户端的时候,我们是能看到证书公钥信息,过期时间,序列号等明文信息的,还有一个CA的签名(签名算法很重要,用来身份验证)。

2.如果没有这个签名,我们直接拿到明文公钥信息,鬼知道是不是真的?重点来了,签名是RAS了摘要算法,RSA的密钥就是CA的密钥,那么解密只能用CA的公钥解。这里千万区分开了,这里的公钥和我们服务器的公钥是不一样的,整个过程是有两对RSA密钥的。千万别搞错了。这就涉及到了电脑,手机等硬件里面的根证书列表的。正常情况下,生产的时候就会把权威机构的例如CA的公钥加入进去。然后Apple给我们提供了这个方法 SecTrustEvaluate 用来验证证书的。一样先用系统的根证书列表拿到对应的公钥进行解密服务器传过来证书里面的签名,这里解出来的是例如是MD5的摘要值,这个值是我们之前拿公钥去CA认证的时候摘要出来的。然后客户端也拿出证书的明文进行MD5,把这两个值一比对,如果相同,可以验证两个观点。


第一,认证服务器的公开密钥的是真实有效的数字证书认证机构。(因为公私药是成对的,能解开说明是CA机构的)

第二,服务器的公开密钥是值得信赖的。(MD5没变,说明是原装的,肯定是值得信赖的公钥,没被篡改)

先记得一点,这种验证,只能说明这个证书是正规机构颁发的而已,而且信息没被篡改,但是如何确定是我自己服务器的证书?就需要强域名校验或者证书公钥匹配了

第四阶段:ClientKeyExchange-Finished

服务器返回的证书验证合法后, 客户端计算产生随机数字Pre-master Key(预设主密钥),并用server证书中公钥加密,发送给服务器。同时客户端会根据已有的三个随机数根据相应的生成协商密钥(主密钥+两个随机数通过复杂算法生成真正的传输密钥)。客户端会通知服务器后续的通信都采用协商的通信密钥和加密算法进行加密通信。然后客户端发送Finished消息用于通知客户端信息发送结束。

第五阶段:服务器端生成协商密钥

服务器也会根据已有的三个随机数使用相应的算法生成协商密钥,会通知客户端后续的通信都采用协商的通信密钥和加密算法进行加密通信。然后发送Finished消息用于通知服务器信息发送结束。

第六阶段:握手结束

在握手阶段结束后,客户端和服务器数据传输开始使用协商密钥进行加密通信。

详细的过程可以看我之前写的HTTPS文章

iOS App签名验证安装过程

对HTTPS的过程有了基本的了解,那么我们先大概抛出一个结论。
相对于HTTPS过程而言,Apple相当于CA,App相当于网站。
我们开发中或者上传AppStore,怎么确保能安装能到手机上,而且是被Apple信任认证过的?

最简单的方式 iOS App Store Deployment

Apple生成一对公私钥,我们上传的包Apple通过私钥进行签名,iOS设备上都内置公钥,商店下载的时候根据包里面的证书签名进行公钥解密验签,如果匹配上,说明是Apple后台认证过的,而且是未经过修改的,这样就能保证每个安装到的iOS设备上的App都是受Apple信任的。
在这里插入图片描述

Development

但是我们日常开发中还有三种安装包的方式
1、开发者模式Developement 证书打包用于调试
2、Ad_Hoc 可以理解为预发布环境的包,但是设备受限,可以模拟线上的行为
3、Enterprise也成In_House,企业证书发布的包,企业内部分发用

先来看看Development开发时安装App,这个时候我们不需要把App上传到Apple后台,但是我们开发安装的App也要是被Apple信任的。可以通过上面HTTPS的过程来理解,本地的公私钥类似服务器,Apple公私钥类似CA,我们需要去像Apple认证,就像去CA认证一样,这样安装传输的东西就是Apple或者CA信任的东西了。
在这里插入图片描述
1、在你的Mac电脑生成一对公私钥,公钥M和私钥M,M代表Mac
2、Apple后台生成一对公私钥,公钥A和私钥A,A代表Apple,私钥在后台,公钥在所有iOS设备上
3、把公钥M上传到Apple后台,然后Apple在私钥A去签名公钥M,生成一份证书,该证书包含了公钥M和公钥M等数据的签名,这份证书可以理解为HTTPS CA颁发的证书,这里的CA就是Apple认证
4、开完后运行到手机,会用本地的私钥M对这个App信息进行签名,同时会把上一步得到的证书一起打包进App里,安装到手机上。一般第一次签名会看到这个,就是通过证书找到本地匹配的私钥,需要验证身份
在这里插入图片描述
5、安装前,iOS取得系统根证书列表中的证书,通过系统内置的公钥A,去验证这个数字证书的数字签名是否正确,如果验证成功,代表证书内的公钥M和信息是Apple认证过的,而且未被修改,可以使用。(这里的证书验证,如果被后台Revoke后,是会崩溃的,和HTTPS证书一样,如果被吊销,一样不能使用,这应该还是会有去后台判断证书是否被吊销了)然后拿到证书内的公钥M,用这个公钥M再去验证外部的App签名,这里就通过证书的方式,间接验证了安装的行为是被Apple允许的受控的。


以上的操作步骤,证书中只有一个公钥,解决了安装的行为是被Apple控制的,但是还没解决如何限制设备和具体的包,依然是参考HTTPS证书,先看下证书

在这里插入图片描述
证书是可以扩展很多类型,但是也仅仅是针对证书的信息而已,如果像我们后台配置的BundleID,设备ID,推送开关,iCloud,后台运行等配置是不可能再加入到证书内部的,因此就有了一个Provisioning Profile,俗称PP文件,再包一层,把证书独立出来,然后再加上我们配置的参数信息,再多重签名后打包进App进行安装前校验,ipa包内部的显示方式为embedded.mobileprovision。因此,在我们申请完开发者账号后,我们第一步要申请个证书,然后配置包的BundleID,最基本的还得把设备ID填进去,最后我们拉到最后,选择PP文件的类型,里面把上述信息都组装起来弄成一个齿轮文件,我们经常看到的那个
在这里插入图片描述
一般主账号下申请一套东西下来问题不大,如果你要给其他开发者真机调试,就要把你做好的PP文件给到他,然后还要把你本地私钥导出成P12文件,有了这两个,就相当于具备了安装调试的所有功能了,具体的后面在统一整理介绍。先看下完整的流程图

在这里插入图片描述
这个证书已经变得很复杂了,有很多额外信息,实际上除了 设备 ID / AppID,还有其他信息也需要在这里用苹果签名,像这个 APP 里 iCloud / push / 后台运行 等权限苹果都想控制,苹果把这些权限开关统一称为 Entitlements,它也需要通过签名去授权。

实际上一个“证书”本来就有规定的格式规范,上面我们把各种额外信息塞入证书里是不合适的,于是苹果另外搞了个东西,叫 Provisioning Profile,一个 Provisioning Profile 里就包含了证书以及上述提到的所有额外信息,以及所有信息的签名。

完整流程

1、在你的Mac电脑生成一对公私钥,公钥M和私钥M,M代表Mac
2、Apple后台生成一对公私钥,公钥A和私钥A,A代表Apple,私钥在后台,公钥在所有iOS设备上
3、把公钥M上传到Apple后台,然后Apple在私钥A去签名公钥M,生成一份证书,该证书包含了公钥M和公钥M等数据的签名,这份证书可以理解为HTTPS CA颁发的证书,这里的CA就是Apple认证
4、申请完证书,我们会配置BundleID,设备ID和App使用权限,然后拉到最后,选择Provisioning Profile,按步骤把我们第三步制作的证书,BundleID,设备ID和权限控制融合成一个配置文件,俗称PP文件
5、开完后运行到手机,会用本地的私钥M对这个App信息进行签名,同时会把上一步得到的Provisioning Profile文件一起打包进App里,显示为embedded.mobileprovision,安装到手机上。
5、安装前,iOS取得系统根证书列表中的证书,通过系统内置的公钥A,先去验证embedded.mobileprovision这个文件中的数字签名是否正确,正确的话那么BundleID,证书,设备ID以及权限都是Apple认证下发的,可靠的,未被篡改的,然后再去验证这个数字证书的数字签名是否正确,如果验证成功,代表证书内的公钥M和信息是Apple认证过的,而且未被修改,可以使用。(这里的证书验证,如果被后台Revoke后,是会崩溃的,和HTTPS证书一样,如果被吊销,一样不能使用,这应该还是会有去后台判断证书是否被吊销了)然后拿到证书内的公钥M,用这个公钥M再去验证外部的App签名,BundleID是否正确,设备ID是否包含,都验证通过,就能把App安装到iOS设备上,这里就通过证书的方式,间接验证了安装的行为是被Apple允许的受控的。

概念梳理

1、从证书的颁发机构申请,本地会生成一对公私钥,证书制作请求过程中是需要一个CSR文件CertificateSigningRequest,该文件包含了本地公钥, 私钥保存在Mac电脑上

2、请求后这时候会有两个证书,一个是第一步生成的,一个是下载回来的,keychain会把这两个证书做关联,因为公私钥是成对的。因此我们在Xcode --- Target --- General --- Signing中如果手动选择证书,选择的是我们下载下来的证书,实际上打包的时候会找到keychai中对应的私钥去进行签名,前面说过,公私钥是成对的。那么现在只有这个Mac有私钥,如果其他同事需要开发调试,我们就需要导出一个东西叫P12。从Keychain中导出对应的私钥,就会出现个P12文件,其他Mac打开后就导入了这个私钥。

3、证书配置好之后一般会配置BundleID, 设备ID和权限,然后统一制作一个Provisioning Profile文件包起来,下载下来即可

4、打包的时候会把第二步下载的证书,找到本地对应的私钥,用本地私钥去签名App,把Provisioning Profile文件命名为embedded.mobileprovision打包进去。这里对App的签名会分成两部分,一部分是对Mach-O文件的签名,是直接写入文件中,还有一部分是对资源文件的签名会保存在_CodeSignature目录下。
在这里插入图片描述

5、基本概念
证书:公钥或者私钥,由其他权威机构组成的数据包
Entitlements:包含App权限列表
CertificateSigningRequest:本地公钥
p12:本地私钥,可以导入到其他电脑
Provisioning Profile:包含证书,Entitlements等数据,由Apple后台私钥签名的数据包

6.为什么给别人P12和Provisioning Profile文件,别人就可以开发安装了?
现在应该能理解了把,P12其实就是私钥,从申请者Mac电脑导出的,然后再有了PP文件,这两者就是对应上面的图的第五步,然后iOS设备已经内置了公钥A,层层验证后解除本地公钥M,然后就能解出这个P12文件中私钥M签名的App文件了,验证后,就可以安装App到iOS设备上了。

Ad_hoc

该模式签名打包验证和Development是一样的,只是证书类型不同而已。看个图,其他都是一样的
在这里插入图片描述

Enterprise

企业证书,我个人的理解是企业处于安全以及自主分发能力的需求而出的一个证书,完全自出控制,那么安装企业级App,你经常会看到一个描述文件的信任问题。不知道大家对Charles第三方中间人抓包HTTPS的原理了解不,不了解可以看看我的另一个文章HTTPS详解
Charles作为中间人,会自己生成一个证书,一般的流程是客户端对服务端,当客户端握手之前,服务端会发送证书回来给到客户端校验,这个时候客户端会从内置的证书信任列表那里拿出公钥进行解签名,信任列表里面一般权威的CA都在里面,验证成功,代表https证书是正规的CA颁发的,就是妥妥的没问题,然后,Charles中间人抓包原理简单来说就是,握手之前先和中间人Charles交互,然后Charles把自己的证书发回给客户端,客户端从根证书列表那,发现解不了,这就无法抓包了,因此Charles有个行为就是让用户手动信任描述文件,这个行为就是把Charles生成的公钥放入根证书列表进行匹配,那么下次SSL的时候,就能认证过了,接着TCP就会发送包数据给Charles,然后Charles就作为客户端把数据发送给服务器,服务器返回,他也能拿到数据,抓包工具显示数据,然后再原样返回给客户端,也可以做点手脚返回给客户端。

OK,介绍了Charles的原理,现在能解释企业证书原理了,按我的理解,企业证书,不需要让Apple认证,企业就是相当于模拟了Appstore的角色,有着自主分发App的能力,自己有一套公私钥,那么就需要用户通过和Charles抓包信任一样,把企业的公钥放入根证书列表进行匹配,这里的iOS设备校验规则可能不是根证书,但是原理应该一样,就是之前存放Apple内置在iOS设备中公钥的地方,多放几个公钥而已,就能认证过,就能安装企业证书了。

小问题

我们看到前面说的签名流程很绕很复杂,经常出现各种问题,像有 Provisioning Profile 文件但证书又不对,本地有公钥证书没对应私钥等情况,不理解原理的情况下会被绕晕,我的疑问是,这里为什么不能简化呢?还是以开发证书为例,为什么一定要用本地 Mac 生成的私钥去签名?苹果要的只是本地签名,私钥不一定是要本地生成的,苹果也可以自己生成一对公私钥给我们,放在 Provisioning Profile 里,我们用里面的私钥去加密就行了,这样就不会有 CertificateSigningRequest 和 p12 的概念,跟本地 keychain 没有关系,不需要关心证书,只要有 Provisioning Profile 就能签名,流程会减少,易用性会提高很多,同时苹果想要的控制一点都不会少,也没有什么安全问题,为什么不这样设计呢?

这种设计的话我感觉第一种原因就是为了卖Mac电脑,哈哈。。。。。。
不过如果放在PP文件中,别人拿到了PP文件相当于拿到了私钥,就可以给其他App签名了,如果PP文件中去掉私钥,那么完整性校验就不会过,毕竟数据和原先App下发不一样了嘛,也就验签不过,虽然无法给别人拿到私钥签名,但是自己也无法验签了。

参考文章:
Bang神

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值