OC

iOS签名机制

Posted by sunzhongliang on December 24, 2021

从0开始深入理解iOS的签名机制

前言

假设AliceBob两个人现在要互相发信息,但有一个不怀好意的Eve想要窃听他们之间的消息

如何防止被不怀好意的人窃听? 通过一个加密手段,消息的发送者通过一个密钥将消息的内容加密后,然后再发送给接收方Bob,Bob收到加密的消息内容之后,然后再利用密钥进行解密即可
由于监听者Eve没有密钥,此时它只能监听到加密的内容,无法查看真正的消息内容

根据密钥的使用方法,可以将密码分为两类:

  • 对称密码
  • 公钥密码(非对称密码)

对称密码

对称密码中,加密、解密用的都是同一个密钥
常见的对称加密算法有:

  1. DES(Data Encryption Standard)
    • 一种将64bit明文加密成64bit密文的对称密码算法,密钥长度是56bit
    • 目前可以比较容易被破解出来,所以不建议使用
  2. 3DES
    • 使用DES用3个不同的密钥重复3次计算所得到的的一种密码算法
    • 如果3个密钥都相同,则结果与普通的DES是等价的
  3. AES(Advanced Encryption Standard)
    • 取代DES称为新标准的一种对称密码算法
    • AES的密钥有128、192、256bit三种
    • 已经取代DES3DES称为主流的对称密码算法

密钥配送问题

由于对称加密的密钥都是同一个,所以存在一个密钥配送的问题,如果密钥一旦被窃听者截取,那么加密就如同虚设
所以就存在了如何安全的进行密钥交换,目前主要有以下方式:

  • 事先共享密钥
  • 密钥分配中心
  • Diffie-Hellman密钥交换
  • 公钥密码(非对称加密)

公钥密码

公钥密码(Public-key Cryptography),也叫做非对称加密,密钥分为加密密钥解密密钥两个,他们并不是同一个密钥也不相等
公钥密码加密有以下特点

  • 加密密钥一般是公开的,因此该密钥被称为公钥(public key)
  • 解密密钥由消息接收者自己保管,不公开,因此称为私钥(private key)
  • 公钥私钥是一一对应的,不能单独生成
  • 公钥加密的密文,必须使用私钥才能解密
  • 私钥加密的密文,必须使用公钥才能解密

利用公钥密码就可以解决密钥配送的问题

目前使用最广泛的公钥密码算法是RSA RSA的名字是由它的3位创造者的名字首字母组合而来的(Ron Rivest、Adi Shamir、Leonard Adleman)

混合密码系统

对称密码的缺点是不能很好的解决密钥配送问题
公钥密码的缺点是加解密的速度又有点慢
所以也就诞生了混合密码系统(Hybrid Cryptosystem),它是将对称密码和公钥密码的优势相结合的方法;解决了公钥密码加解密速度慢的问题,同时又解决了对称密码的密钥配送问题

网络上的密码通讯所使用的的SSL/TLS都运用了混合密码系统

混合密码-加密

会话密钥(session key)作为本次通信随机生成的临时密钥,同时又作为对称密码的密钥,用于加密消息,以此来提高速度

加密步骤

  1. 首先,消息发送者要拥有消息接收者的公钥
  2. 生成会话密钥,作为对称密码的密钥,用于加密消息
  3. 用消息接收者的公钥,加密会话秘钥
  4. 将前两步生成的加密结果,一并发送给消息接收者

发送出去的内容包括

  • 用会话密钥加密的消息(加密方法:对称密码)
  • 用公钥加密的会话密钥(加密方法:公钥密码)

混合密码-解密

解密步骤

  1. 消息接收者用自己的私钥解密出会话秘钥
  2. 再用第一步解密出来的会话密钥,解密消息

混合密码-完整流程

Alice 发送消息给 Bob
发送过程,加密过程

  1. Bob先生成一队公钥、密钥
  2. Bog把公钥功效给Alice
  3. Alice随机生成一个会话密钥(临时密钥)
  4. Alice用会话密钥加密需要发送的消息(使用对称加密)
  5. Alice用Bob的公钥加密会话密钥(使用非对称加密)
  6. Alice把第4、5步的结果,一同发送给Bob

接收过程,解密过程

  1. Bob利用自己的私钥解密会话密钥(使用非对称加密)
  2. Bob利用会话密钥解密发送过来的信息(使用对称加密)

单向散列函数

单向散列函数(One-way hash function)是指可以根据消息内容计算出散列值
散列值的长度和消息的大小无关,无论消息是1bit,1M等等,单向散列函数都会计算出固定长度的散列值
有以下特点:

  • 计算速度快
  • 消息不同,散列值也不同
  • 具备单向性(无法根据散列值反向得到消息内容)

常见的几种单向散列函数

  • MD5
    • 产生128bit的散列值
    • Mac终端上默认可以使用md5命令
  • SHA-1
    • 产生160bit的散列值,不太安全
  • SHA-2
    • SHA-256、SHA-384、SHA-512,散列值长度分别是256bit、384bit、512bit
  • SHA3
    • 全新标准

单向散列的应用
针对单向散列的特点,通常在实际开发当中用于做一些数据防篡改、比对的校验
比如登录系统当中的密码校验等等

数字签名

graph LR
    发送者 ==消息内容===> 接收者

消息的发送者在向接收者发送一段消息时,接收者如何确保消息的真实性(有没有被其他人篡改)?
一个比较好的解决方案:数字签名

在数字签名技术中,有以下两种行为:

  • 生成签名(由消息的发送者完成,通过签名密钥完成)
  • 验证签名(由消息接收者完成,通过验证密钥完成)

数字签名其实就是将公钥密码反过来使用(使用私钥加密,使用公钥验证)
一个完整的使用数字签名的示例:

数字签名不是为了保证机密性的,它主要的作用其实是防止内容被篡改

数字签名其实也存在一个巨大的问题,那就是中间人攻击
中间人自己生成了一份私钥公钥,通过窃取刚开始消息发送者和消息接收者之间 传输的公钥,自己保存了这个正确的公钥,然后将自己的公钥给到了发送者
而发送者后面发送的消息内容,都是经过中间人的公钥加密的,中间人就能够解出来,然后篡改其内容,再通过正确的公钥加密,最终发送给接收者,这样就完成了消息的篡改.
所以验证公钥的合法性就是最重要的了,这个时候就要用到证书

证书

证书(Certificate),都是由权威机构认证的
密码学中的证书,全称叫做公钥证书(Public-key Certificate,PKC), 里面有姓名、邮箱等个人信息,以及此人的公钥, 并由认证机构(Certificate Authority,简称CA)施加数字签名

CA就是能够认定“公钥确实属于此人”并能够生成数字签名的个人或者组织

一个简单的证书注册流程

证书的使用流程 由于消息接收者在生成密钥对的时候,并不是直接传输公钥给消息发送者,而是将公钥提交到了认证机构Trent(虚拟的), 所以在这一步中间者也就无从窃取公钥了
消息发送者是直接在认证机构获取的证书(包含公钥、数字签名), 为了验证这个证书是否合法,它还可以使用机构提供的公钥来验证数字签名是否准确,一旦验证通过后,就可以放心的使用这个证书进行加密发送消息了。

iOS签名机制

iOS签名机制的作用其实就是为了保证安装到用户手机上的APP都是经过Apple官方允许的, 签名的机制分为两种App Store的签名机制XCode开发的签名机制

App Store下载的签名机制

当 App 提交审核通过后,Apple 会对 App 进行重签名。因此,从 App Store 下载的 App ,统一都是苹果的官方签名。验证机制也较为简单。
它的主要流程:

  1. Apple 官方保存着私钥,在App提交审核通过后,会通过私钥对其进行重签名;
  2. iOS 系统内置公钥,用户从 App Store 下载 App ,iOS 系统通过公钥对其进行签名验证;
  3. 验证通过,则说明该 App 是经过苹果认证的,未经篡改的,允许运行,否则,拒绝运行。

XCode开发的签名机制

XCode中开发时,用的是开发证书。需要针对不同的开发者账号进行验证,签名机制较为复杂。

开发者身份验证

在 Apple Developer 生成证书时,为了验证开发者身份,需要在本地 keychain 中生成公私钥,公钥保存在 CertificateSigningRequest 文件中,上传到 Apple Developer ,私钥如果需要给其他开发者用,可以导出为 .p12 文件。

生成证书
Apple Developer 后台接收到开发者公钥后,利用 Apple 的私钥对其进行签名,生成证书cer。

验证设备
除了验证开发者身份,还需要验证 AppID 和设备的 UUID , 权限控制 Entitlements 等,把这些信息和上面生成的证书一起,再用 Apple 的私钥进行一次签名,生成最终的 mobileprovision 文件。

签名APP
在XCode编译后,生成 App 文件时,会对其通过开发者私钥进行签名,将 mobileprovision 文件命名为 embedded.mobileprovision 并将其打包到 App 文件中。

在通过开发者私钥签名 App 时,对于可执行文件( Mach-O ),会将签名直接写入到该文件中,而对于其他的资源文件,会统一写到 _CodeSignature 文件下的 CodeResources 文件中。

验证签名
在安装 App 文件时,首先通过 iOS 系统内置的 Apple 公钥对上面的签名进行验证,包含开发者共私钥匹配,设备 ID,App ID,权限控制 Entitlements ,证书有效期验证等。

本文首次发布于 孙忠良 Blog, 作者 [@sunzhongliang] , 转载请保留原文链接.