美文网首页iOS开发常用知识点
理解iOS开发的签名原理

理解iOS开发的签名原理

作者: YesWeCan | 来源:发表于2018-11-23 15:26 被阅读489次

    一 概述

    之前我在做iOS项目开发时,由于采用的是自己的开发者账号,在Xcode的General配置中勾选上Automatically manager signing 便再也不用管证书等一些问题,所有的一切都是由xcode自己来给你做。但是当涉及到团队开发,有时候需要共享一个数字证书和mobileprovision文件时,便有层出不穷的问题。尽管有些google一下也能解决,但是并不了解其实质原理,为何要这么做。
    如果你对Provision profile(称为配置文件or描述文件)、CertificateSigningRequestP12Cer等等这些证书一知半解,相信本文可以解答你心中的疑惑。
    本文会从原理出发,一步步解释iOS签名的各个处理流程,主要章节如下:

    • 摘要算法
    • 对称加密算法
    • 非对称加密算法
    • 数字签名
    • 数字证书
    • iOS签名机制与配置文件
    • iOS上build的处理流程
    • iOS app从appStore下载的验证流程
    • 加密算法在 HTTPS上的应用

    二 摘要算法

    摘要算法又称为哈希算法,可以将任意长度的数据流通过hash计算,输出固定长度的数据,相同输入的数据始终得到相同的输出。
    常用的hash算法有:
    MD5 输出长度:128bit
    SHA-1 输出长度:160bit
    SHA-256 输出长度:256bit
    由于输出长度是固定的并且输出输入的长度不固定,这就意味着两个不同的输入可能得到相同的输出,这就是碰撞的问题。所以在设计Hash算法时尽量使其碰撞率低,并且安全的hash算法很难从输入反推出输入,只能依靠暴力穷举。
    特征: 不同数据的计算结果不同、不可逆

    三 对称加密算法

    对称加密,也称单钥加密,同一个密钥可以加密和解密。由于其速度快,对称性加密通常在消息发送方需要加密大量数据时使用。该加密算法的安全性不仅取决于加密算法本身,密钥管理更为重要,如何将密钥安全地传递到解密者手上就成了必须要解决的问题。
    常用的对称加密:

    1. DES 数据对称加密标准,因为加密强度不够用得少;
    2. 3DES 使用三个密钥对相同的数据进行三次加密;
    3. AES 高级密码加密,美国安全局使用,Apple钥匙串便采用该种方式。
      该算法特点:算法公开、计算量小、加密速度快,但是密钥管理成问题。

    四 非对称加密

    非对称加密算法是指,加密密钥和解密密钥是不同的,一般加密密钥和解密密钥是成对出现的。公私钥具有以下重要特性:

    • 对于一个私钥,有且只有一个与其对应的公钥;
    • 公钥是公开的,但是不能通过公钥推导出私钥;
    • 私钥加密的文件可用公钥解密,同样公钥加密的文件可用私钥进行解密。

    目前使用最广泛的公钥密码算法是RSA。RSA的名字有3位开发者,即Ron Rivest、Adi Shamir、Leonard Adleman的姓氏首字母组成。

    非对称加密虽然安全性较高,但是加密速度较慢,不适合对大量数据进行加密.
    了解了以上知识点,接下来便是数字签名原理

    五 数字签名

    数字签名实际上就是将摘要算法非对称加密算法结合起来,其设计的目的是保证数据文件的完整性,防止中途被中间人篡改。

    数字签名处理流程图.png

    如上图,当我们手上数据内容需要上传到服务器端,则首先将数据内容采用MD5的hash算法生成一个32个字符摘要,然后在用RSA公钥进行加密生成密文,即数字签名。
    而上传到服务器的内容则由数据内容和数字签名构成,服务器拿到数据包后先将数字签名采用RSA的私钥进行解密拿到之前的摘要,再将获取到的数据内容采用md5算法得到该内容的hash摘要值,最后将这两个摘要进行对比,如果一致则数据完好无锁。
    note:加密后为128位(bit),按照16进制(4位一个16进制数)编码后,就成了32个字符
    这个过程仅对md5加密是为了减少非对称加解密所耗费的时间。数字签名可以快速的验证文本的安全性合法性。理解了数字签名,可以进一步来理解数字证书。

    六 数字证书

    签名过程看起来已经足够安全,数据接收方通过发送公钥对签名进行解密,便可以验证发送者的数据完整性和安全性。但是如果接收方手中的公钥已经被中间人劫持,而真正到达发送者手中的公钥是来自于中间人给的,那么这个过程便又不安全,具体过程可以看如下图:


    数据劫持.png

    服务器端发送的公钥让中间人劫持了,中间人把自己的公钥发给用户,而用户便用此公钥加密数据发送给服务器,而此时的服务器其实已经是中间人了。中间人再次劫持用户的数据并用自己的私钥解密,然后用真正服务器端的公钥加密自己篡改的数据发送给服务器。
    对于这样的问题,有一种目前通用的解决方案。找一个可以信任的数字证书机构(Certificate Authority,CA),将我们的公钥和注册信息交给CA。CA将我们的合法信息和公钥利用非对称加密(CA自己的私钥)生成密文(即数字签名),再将签名和我们的公钥信息打包成证书给我们。下次用户如果需要向我们发送消息,需要先去CA上请求CA公钥,然后我们给用户证书,用户再去用CA公钥解密签名,以此来验证我们给出的公钥是否正确。


    CA颁发证书.png
    数字证书和生活中的证书一样,例如驾驶证、英语四六级证书等等,数字证书的签发机构也有若干,例如苹果公司就可以签发apple开发相关证书,而web相关的证书也有几家国际公认的机构进行签发,这些机构称为CA。

    七 iOS签名机制与配置文件

    iOS签名机制的作用:保证安装到手机上的app都是经过Apple官方验证和许可的。不管真机调试,还是发布App,开发者都必须经过一些列复杂的步骤,下面我将详细的说明这些。

    • 第一步 上传本地开发者的公钥信息到MC
      具体操作就是从mac上钥匙串中生成一个CertificateSigningRequest.certSigningRequest文件,该文件中主要包含以下信息:
    1. 申请者信息,此信息是用申请者的私钥加密的
    2. 申请者公钥,此信息是申请者使用的私钥对应的公钥
    3. 摘要算法和公钥加密算法

    可以采用openssl来解析文件中内容:

    openssl asn1parse -i -in CertificateSigningRequest.certSigningRequest
    
    CertificateSigningRequest.certSigningRequest.png

    为什么要上传这个信息呢?因为后续我们在用xcode构建项目时,需要对可执行文件进行签名(即采用本地摘要算法先进行hash计算,然后在使用本地私钥进行加密),如果MC拿不到我们的公钥,那么如何进行非对称解密,如何验证我们app是否完整呢!
    拿到CRS文件后上传到MC。

    • 第二步 从MC下载apple颁发的Cer证书
      上一步上传完CSR文件后,可以根据我们的需求配置证书相关的信息,例如bundleID,Push、Apple Pay等等,然后我们将MC生成的证书下载并安装到本地钥匙串中,如下图:
      cer证书下载.png
      其实MC在拿到我们上传CSR文件后,提取里面的公钥,它需要做的便是将MC中关于我的账号信息和刚刚提交的公钥打包,再进行数字签名,最后封装到cer证书中。
      我们可以用openssl来看一下cer文件内容:
    openssl x509 -inform der -in ios_development.cer -noout -text
    

    也可以直接在mac上按住空格预览,截图如下:


    cer证书内容.png

    其中主要包含摘要算法和RSA加密公钥,以及一个apple的签名。双击安装证书后,KeyChain子自动将这公钥和本地私钥关联起来。后续程序在真机上build时,会使用本地私钥进行代码签名,而公钥会附带人mobileprovision文件中去,打包进app。

    note: 实际上公钥是放在了mobileprovision文件中,并不是随代码一同打包的,所以我认为我们mac上安装的证书没有实际用处,因为mobileprovision是MC为我们生成的。其实安装证书的主要目的应该是区别对应的私钥,真正用于签名的是私钥,如果本地有多个不同的证书,那就有多个私钥,所以需要依靠不同证书来区分到底用哪种私钥进行codesign。mobileprovision我会在后面讲解。所以,有证书却没有私钥还是没用的。

    既然私钥是某台电脑上生成的,那么团队如何开发呢?
    其实我们可以从钥匙串中给安装好的证书导出.p12文件,在其他机器上安装即可共享私钥和证书了。
    我们下载下来的证书也是有很多种类的,就好像你需要驾驶证才能开机动车,你需要护照才能出国,用途不同,证书也不同。如下是展示部分证书类型:

    1. iOS App Development。开发、真机调试用
    2. Apple Push Notification service SSL (Sandbox)。开发阶段使用苹果的推送服务
    3. App Store and Ad Hoc。上架和AdHoc方式发布时用
    4. Apple Push Notification service SSL (Production)。上架后使用苹果推送服务
      5.0 In-House。企业版发布,需$299才能拥有,还需邓氏编码
    • 第三步 配置iOS mobileprovision文件
      证书只保证了app的所属和完整性,却不能保证app的某些功能和服务是被苹果认可的,例如APNs和apple pay等等。所以,苹果想出了坑爹作死的mobileprovision
      可以用如下命令查看描述文件的内容:
    security cms -D -i embedded.mobileprovision
    

    截图如下:


    配置文件1.png
    配置文件2.png

    描述文件主要包含了:

    1. AppId。
    2. 使用哪些证书。
    3. 功能授权列表
    4. 可安装的设备列表。对于AdHoc方式发布的app或者真机调试时,会有一个列表,这个列表里面是iOS设备的UDID,每台iOS设备出厂的UDID都不同。
    5. 苹果的签名。这里的签名是apple的私钥签名的,不是我们本地的私钥,我们除了从MC中下载,没有其他方法,如果我们篡改了相关信息,则文件失效。因此app的各种权利完全被apple牢牢掌控着。

    如果采用Adhoc发布呢?
    Adhoc允许将beta版发布给最多100台设备安装,apple便是通过这里描述文件的第四条来牢牢掌控,只需要描述文件中有相关设备的UDID便可以,而这些UDID需要事先添加到MC的Devices中去。

    以上便是iOS签名机制和描述文件的详细讲解,下面会继续嗨聊iOS作死的代码签名。

    八 iOS上build的处理流程

    我们平时用VS或者clion编一些C/C++时,几乎都是走code-build-link-run流程,无需其他什么认证,但是由于apple的严格生态规则,必须要验证开发者身份和权限。
    8.1 build
    当我们在xcode上进行build时,apple首先去验证开发者,根据用户所选的证书从钥匙串中匹配到相应的私钥,再利用私钥对代码和资源文件签名生成一个_CodeSignature文件,然后与资源文件、app文件、描述文件、Framework文件一同打包到.ipa压缩包中。
    我们可以打开一个.ipa压缩包,

    unzip -q <name> -d <destination>
    

    显示截图如下:


    ipa压缩包.png

    其中,_CodeSignature文件中保存着一个plist文件,其内容是程序包中所有文件的签名,不包含Frameworks文件的签名。mobileprovision文件是打包时使用的,从MC上生成的。Frameworks文件中是引入的第三方框架,每个框架结构类似一个app,也有自己的代码签名。


    iipa文件内容.png

    8.2 校验
    当ipa文件复制到iOS设备上,iOS设备会先拿到描述文件,然后先利用iOS设备本地存储的apple MC的公钥来验证描述文件的签名,已确保描述文件没有问题。之后取出描述文件中的数字证书,同样利用本地apple MC的公钥来验证证书签名,确保证书没有被篡改,没有问题的情况下继续出去证书中保存的Mac本地的公钥,利用公钥来验证_CodeSignature代码签名文件没有问题,最后按照描述文件中配置的app功能权限检测app是否有越权行为,以上验证都没有问题则可以在iOS设备上安装app了。

    8.3 iOS真机调试的整个流程
    首先mac设备本地存有公钥私钥,用于加解密项目文件;然后MC上(即apple Member center)存有apple的私钥,用于加密供我们下载使用的数字证书和描述文件;最后在iOS设备上会存着apple的私钥,用于解密描述文件和数字证书中的签名。结构如下图所示:

    各种密钥及其存储.png
    下图是真机调试的整个流程图:
    ipa安装和验证全流程.png

    整个过程主要是围绕App完整性和验证开发者的权限设计的。大致思路如下:

    1. 将Mac公钥等核心信息上传至MC,MC会用apple私钥签好名一起打包到数字证书中;
    2. 在MC上配置app权限和任务会生成相应的配置文件,该文件会被MC用apple私钥做签名,然后一起打包放入mobileprovision文件中,以供用户下载安装到xcode中;
    3. 当xcode在真机上调试app,我们的代码资源会被mac私钥加密签名生成数字签名,然后与描述文件一起打包进ipa压缩包中;
    4. iOS设备接收到ipa压缩包,会先用本地存储的apple公钥进行签名验证,查看描述文件是否安全;
    5. 如果4安全,则提取描述文件中的数字证书,并用apple公钥来验证数字证书是否安全,如果安全,则取出证书中的Mac公钥
    6. 将取出的Mac公钥用于验证App的代码签名,如果验证没问题,再按照mobileprovision文件查看app所有权限和功能,如果everything ok,那么app就可以安装在真机上了。

    九 iOS app从appStore下载的验证流程

    appstore下载验证流程.png
    从appStore下载验证流程就简单的多,通过pp助手等第三方工具下载一些线上的ipa文件,你会发现它里面没有mobileprovision文件。处理流程如下:
    1 当从appstore下载app,appStore会用apple私钥对app进行数字签名;
    2 iOS设备拿到资源包后,会用本地apple公钥来验证数字签名是否正确,如果正确,则安装。
    因为数据是来自于apple服务器,所以apple只需要保证app的完整性就好,防止中途被篡改。

    签名小结

    至此,我已经大致介绍了Xcode本地构建和iOS设备上的一些身份验证机制,其实整套流程就是对摘要算法和非对称加密的封装和应用。同时apple未来加强对于xcode本地构建项目的权限而设计了一个mobileprovision文件的概念,这里只要区分好Hash摘要算法、非对称加密算法、数字签名、证书、描述文件等等概念,其实整套验证机制就不那么困难了,下次再遇到证书问题、签名问题,就不在需要不断google问别人怎么做的,直接对症下药了。

    最后,为了更好的理解摘要算法非对称加密算法,我再讲解一下HTTPS的实现原理。

    十 加密算法在 HTTPS上的应用

    HTTP是常见的应用层协议,是超文本传输协议的总称,其传输内容都是明文的,对此有一万种方式来劫持数据流,所以非常不安全。Https便应运而生,稍微牺牲一些速度而换取数据的传输安全,其中“s”表示SSL或TLS协议,就是在原有http的基础上加上一层数据加解密的安全层。
    整个HTTPs的处理流程如下图:(PS画图不易哇!)

    HTTPs流程图.png
    对照该流程图,我将分步详细说明:
    1. 对于一个服务器开发商而言,想要采用SSL/TSL协议,则必须先从CA机构获取证书。这需要先将服务器支持的非对称加密的公钥(本文简称Server公钥)和服务器运营商的注册信息等一起发给CA去审核;
    2. CA审核通过后,会将Server公钥和网站注册信息以及一个CA的数字签名一同打包到数字证书中。其中数字签名是用CA私钥加密的,需要CA公钥来验证,而CA公钥是分发到各个操作系统中的;
    3. 当服务器有了数字证书,之后浏览器或者客户端在向该服务器的站点发送request,便可以将CA证书返回;
    4. 浏览器或者客户端向服务器站点发送request,需要先把其所支持的Hash算法、对称加密算法、非对称加密算法,以及浏览器的一些配置信息发送出去;
    5. 服务器在收到后,从这些算法中选择自己也支持的Hash、对称、非对称算法和CA数字证书一同发送给请求者;
    6. 客户端本地拿到CA证书之后,会用本地CA公钥先进行数字签名的验证,如果验证失败,则断开连接,否则取出CA证书中的server公钥
    7. 客户端生成一个随机的key,并且用server公钥进行加密,生成一个key的密文;然后用key对本次握手进行Hash计算,并将计算结果用key进行对称加密,生成一个握手消息的密文。最后将这两个密文一起发送给服务器;
    8. 服务器拿到两个密文后,先用本地server公钥解密获取key,然后用key对握手消息密文解密拿到该hash值,并且自己也用相同摘要算法对握手消息进行hash计算,将两个hash值进行对比,如果不一致,则断开连接,否则用key对称加密服务器端信息,然后发送给请求者。至此基于安全协议SSL的握手阶段结束,后续客户端和服务器都会用key来对收发的消息进行对称加密解密。
      上述过程属于单向认证的SSL协议的握手规则,但也有双向的认证的SSL协议的通讯,即要求服务器和用户双方都要有证书,双方都验证对方的证书的数字签名。

    总结

    1. 本文主要先介绍了摘要算法、对称加密算法、非对称加密算法,在于此基础上讲解了何为数字签名、何为数字证书,以及两者的关联和作用;
    2. 接着本文家讲解了Xcode上打包ipa的处理流程,以及在真机上build的apple验证机制。同时也解释了appstore上下载app的验证流程;
    3. 最后未来更好了帮助大家理解这些加密算法的应用场景,例举了HTTPs的通讯原理。
      希望本文对大家有所帮助,如果不当之处,还希望大家及时给我留言,共勉!

    相关文章

      网友评论

        本文标题:理解iOS开发的签名原理

        本文链接:https://www.haomeiwen.com/subject/mwjxqqtx.html