如何理解 iOS 的签名证书机制

来自:https://juejin.im/entry/58ff10bf1b69e60058abb6b8

要理解 iOS 中的签名和证书机制,首先我们要理解什么是签名(Signature),什么是证书(Certificate)。

签名

在数据传输的过程中,我们最关心的就是两件事:可靠性和数据完整性。我们可不想打开身份不明的开发者的程序,或是打开已经损坏/被修改过的程序。
为校验数据包的完整性,数据发送端通常会利用 [MD5 算法]来将需要发送的信息进行“摘要”,而后发送端利用私钥将摘要加密,得到签名,
连同数据包一起发送给接受方,接受方收到数据包和签名后,接受方利用公钥解密签名,拿到发送方的 MD5 数据,再对数据包进行 MD5 操作并与发送方 MD5 进行对比,
以验证数据完整性。上述的过程,摘要的加、解密步骤,验证了数据发送方的身份,而两次 MD5 操作验证了数据完整性。

一般情况下仅对 md5 内容进行加密,是为了节省加密、解密的时间。

证书

上述签名过程看起来已经足够安全了,接受方通过**发送方公钥**对签名进行解密,就能够验证数据包发送者的身份。
但这都是建立在我们手中的公钥是正确的前提下的,一旦我们的公钥被替换,我们便无法解开对应发送方的签名,但更危险的是,伪造公钥的第三方,可以发送数据给我们,而我们拿着“假”的公钥,能正确解开其签名,从而误以为该数据源于我们所信任的发送方。
那么如何确保公钥的安全性呢?一个很自然的想法就是为公钥进行加密。通常的做法是,我们找到一个可信任的数字证书认证机构(Certificate Authrotiy,简称 CA),将我们自己的**公钥**交给 CA,随后该机构运用上述签名类似流程,用 CA 私钥加密我们的公钥,然后暴露一个 CA 公钥供使用者验解密。
这个被 CA 私钥所加密的我们自己的密钥(当然还有一些像有效期、用户信息等其它内容)一般被称为证书。但这里也引入了另一个问题:解密证书所需要的公钥,同样存在被冒充的风险,如何规避这其中的风险呢?这里我并没有查到详细的资料,我想,这里公钥的正确性,便是由这些具有公信力的 CA 所保证的,而平时我们自己做业务,在网络安全方面,是难以达到这样的安全标准的。

小结

有了上面的储备知识,我们知道,想要在网络上安全的传输数据,我们一般需要两对密钥:自己的业务服务器公私钥以及 CA 的公私钥。接下来让我们看看苹果是如何执行这样的思想的。

iOS 的签名证书机制

接下来我们看看 iOS 上的签名机制,下文只讨论 AppStore 以及本地 build 这两种情况(本文编写时,Xcode 版本为 8.3 (8E162),若是更早的版本,macOS 上证书的生成与导入可能需要手动完成)。

为什么需要

相信大家入门程序员的时候,大多都是在 VC 或 VS 上打 C/C++ 入门的,那时候一切都很简单,code-build-link-run,并没有什么认证过程,而由于苹果对其生态圈管理严格,任何在 iOS 上跑的程序都需要经过苹果的“同意”。所以,不论是 AppStore,还是 Xcode 本地 build 的项目,苹果都需要验证这个应用的身份。

从 AppStore 下载的应用验证流程非常简单,Apple 用私钥签名 App 后,iOS 设备下载签名和 App,利用 Apple 公钥验证签名并安装。由于 iOS 设备内置 Apple 公钥,而数据包直接由苹果服务器下载,因此此处的安全是有保障的,同时,签名验证能通过,证明该安装包是从苹果服务器下载的,也就满足了苹果对 App 安装的控制。

Xcode Build

从 AppStore 分发应用的过程是非常简单的,但在日常开发中,上述的验证过程是不能被接受的,我们不可能每次 build 都将应用打包上传,经过苹果的加密后再下载运行。
于是苹果想出了这么一套认证体系。从 AppStore 下载应用时,iOS 设备会用 Apple 公钥验证应用安装包,以确保该应用来源于 Apple 服务器。而在本地调试模式下,设备会把对 App 的验证,改为对开发者的验证:

此处的开发者账号,就是在 Apple Developer Center 中所申请的开发者账号,一旦信任之后,**每次 build 的时候,iOS 设备就将验证该开发者身份,而不是验证你 build 的 App**。
如此一来,便省去了应用包上传、下载的过程。我们知道,验证 App 是通过签名机制,来确定安装包来源的,而此处的验证开发者身份,又是怎样的机制呢?

验证开发者

首先,iOS 设备需要验证你的开发者身份,这是基于 macOS 的一种证书策略,如果打开钥匙串访问,选中证书,我们可以看到这样的一堆东西:

这里你可以看到你的企业证书、个人开发者证书等等,我这里还有 Charles 用来做网络代理的证书。为了更好的说明这一工作机制,我用我的 gmail 邮箱重新申请了一个开发者账号。
当你在 Xcode 添加自己的账号后,并在项目中将 Team 选择为自己的开发者账号后,钥匙串中就多出了这么一个东西:



我们可以看到,证书中存储着一个“专用密钥”,这个专用密钥,和前面 AppStore 分发过程中的 Apple 密钥作用类似,是用来给 App 安装包进行签名的。这份密钥在生成的时候,Xcode 将密钥的公钥部分上传至 Apple 服务器,由 Apple 进行签名生成证书,最后返回到本地,而私钥,则会在 Xcode 本地构建安装时,用来为 App 安装包签名。
最后,Xcode 会将签名后的安装包和本地证书打包都放到 iOS 设备中,iOS 设备接着使用 Apple 公钥来解密证书,拿到本地公钥,接着用本地公钥去解密 App 。


绕了这么一大圈,无非是为了验证两件事:
iOS 设备用 Apple 公钥解密证书,所拿到的本地证书,必定是经过 Apple 服务器签名的,也就是说,这里保证了开发者是经过苹果认证的。
上一步拿到的公钥,用于解密 App 签名,若解密成功且验证通过,证明该 App 确实是由该开发者构建的,也就保证了 App 的安全性。

或许看看流程图,能更清楚:

上述的流程唯一问题是,这个密钥是在本地生成的,如果更换了电脑,本地的密钥对就会改变。这时候,你需要将旧 mac 上的证书导出,并安装到新的电脑上。

一一对应

我们能在 mac 的钥匙串访问中找到本地的密钥证书,但其它的东西似乎就不是那么地可见了,对于一般的开发者来说,我们更熟悉的概念应该是 Provisioning Profile,Xcode 8.3 提供了很友好的可视化界面来让我们查看 Provisioning Profile 里面的东西。

 我们可以看到,Provisioning Profile 中包含了开发组名、组内设备、应用 Capabilities 配置等等,这些都是决定应用行为的一些信息。我们还注意到,Provisioning Profile 中包含了一个 Certificates,这个证书就是我们在上面说的本地公钥证书。
 其实在 Xcode 构建安装 App 时,我们不是直接将本地证书装入 iOS 设备中,而是将 Provisioninng Profile 装入设备中。如果我们开启了 Automatically manage signing,Provisioning Profile 的生成和下载都是由 Xcode 自动完成的,但其实,Provisioning Profile 的创建过程,和本地密钥证书的过程极其相似。
  如果你是付费开发者,或是加入了企业开发 team,你就能在 [证书管理](https://link.juejin.im/?target=https%3A%2F%2Fdeveloper.apple.com%2Faccount%2Fios%2Fcertificate) 看到所有的 Provisioning Profile,每个 Provisioning Profile 与 teamId 和 bundleId 唯一对应。类似的,你也需要将它下载到本地,只不过这一步很多时候 Xcode 替我们完成了。
  *Xcode 默认存储 Provisioning Profile 的文件夹*

  由于 Provisioning Profile 在 Apple 后台生成,很自然的,它也会被 Apple 私钥加密,而它的作用主要有两点:
  校验 App 的各项参数(如 Capabilities,后台获取、通用链接等配置)是否与苹果后台定义的一致。
  其中包含的 Certificates,也就是本地证书,用于校验开发者身份。

  所以,我们可以将上一部分的图进行一些细化:

这里对身份验证的原理和上一部分一致,只是多了一层封装,用于校验项目信息。

总结

至此,我们大致了解了 AppStore 以及 Xcode 本地构建时,iOS 所使用的身份验证机制了。整套验证流程其实就是对非对称加密的封装和应用,只是苹果为验证项目信息,又不想与“证书”这一专有名词混淆,加入了一个 Provisioning Profile 的概念。如果你熟悉签名、证书的概念,那么其实理解这一套验证机制也就并不困难了。

参考资料
iOS App 签名的原理
数字签名是什么?
Public-key cryptography for non-geeks

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352

推荐阅读更多精彩内容