翻译:iOS Code Signing (一)、(二)

翻译来自 iOS Code Signing 系列第一、二篇。
原作者:SHASHIKANT JAGTAP
翻译者:Roc Zhang

如有任何问题还请留言指出。

E-mail: roczhang9673@gmail.com
Weibo: @张鹏roczhang
Twitter: @Lighters9673


Post 1: 入门

这是 iOS 代码签名教程系列的第一部分。此系列涵盖了 iOS 代码签名过程的基础知识,此系列的全部文章为:

  • iOS Code Signing: 1. Getting Started 原文 译文
  • iOS Code Signing: 2. Certificate Signing Requests 原文 译文
  • iOS Code Signing: 3. Certificates 原文
  • iOS Code Signing: 4. Provisioning Profiles 原文
  • iOS Code Signing: 5. Signing iOS App 原文

通常,iOS 设备仅能够运行被信任的开发者所签名的 app,除非是对设备进行了越狱。如果你是一个 iOS 工程师,你肯定和代码签名在某些方面打过交道。由于代码签名是每个 iOS 开发者都无法逃避且最让人痛苦和繁琐的工作之一,除非开发者能够完全理解关于代码签名的基础知识,否则代码签名和 Provisioning Profile 将会成为一个一直伴随你的烦恼。这是一篇入门介绍文章,阐述了代码签名的过程及其优点与局限。

关于此系列

iOS 应用的代码签名对每一个 iOS 开发者来说都是热门话题。尽管网络上已经有很多资源存在,并且 Apple 也给出了清晰的文档,但它看起来仍然像一个谜。在这个系列中,我们将尝试从头开始去理解代码签名,包括代码签名需要什么,以及代码签名自身的处理过程。我们同样会探讨如何使用 GUI 与命令行去实现。我们将从 Certificate Signing Request 开始得到一个 iOS 开发证书,之后我们将聊到证书和其内部组成部分。在理解证书之后,我们将会深入到 Provisioning Profiles,最后我们将能够理解代码签名的整个过程。
这个系列的文章是我自己通过研究网上的资料与 Apple 的文档所写出的,我已将这些引用材料列在了最后一篇文章中。同样我也附带了一些来自 Apple Developer 网站与 Xcode 的截图,以便于读者能够理解这些概念。我已经试图隐藏了所以的敏感内容,但如果依然有被不小心暴露出来的,还请不要黑我 🙂。

代码签名

在我们开始了解 Apple 对 iOS 应用所进行的代码签名方式之前,先让我们大体上探讨一下代码签名。在现实生活中,我们会在各种不同的合同、协议上签名。那么为什么要进行签名?为什么签名对我们而言如此重要?通常这是因为签署合同能在法律上保护我们,并且我们相信合同上的任何条款都不会被篡改。签名同样还能确保合同来自受信任的机构而非诈骗者以确保安全。这就意味着签合同能够带给我们安全、保障与信赖。

同样,代码签名是指对代码进行数字签名,以确保谁编写了代码及代码在签名时没有发生更改或损坏。代码签名使用加密哈希算法来验证软件代码的真实性与完整性。在软件的世界里,代码签名确保了作者的身份、代码的完整、构建系统与版本,使得软件的用户在使用时能感到可靠与安全。代码签名使用了多种安全项如私钥、公钥、证书、数字签名等。不同的代码签名方法会被用在如 Linux、Windows 、macOS 等不同的平台上。

iOS 代码签名

Apple 据说有着十分强大的安全机制,除去一些你最近可能在新闻中看到的小毛病。对黑客来说很难打破这种安全机制。Apple 同样也使用了非常强大的代码签名机制以保证从 Apple App Store 下载的 iOS App 的安全性与完整性。大多情况下,iOS 的代码签名就好像是发生在幕后的黑魔法。如果它工作良好,每个人都会很开心,然而一旦出现问题则会让每个人都陷入恐慌。大多数 iOS 工程师对这幕后的签名过程都不甚了解。最近 Apple 发布了 ‘Automatic Signing (自动签名)’ 功能以帮助减少代码签名所带来的痛苦,不让代码签名打断主要开发流程。Apple 平台上的代码签名依赖于 X.509 标准的公钥加密,我们稍后将在此系列中讨论这些工具和技术。

为什么要学习 iOS 代码签名

现如今代码签名的大多数工作都由 Xcode 处理,那么为什么我们应该关心代码签名以及为什么要投入时间去了解它?

这里是一些为什么要学习代码签名内部原理的原因:

  • iOS 工程师直接从安装在本地机器上的 Xcode 部署 iOS 应用的日子已经一去不复返了。现如今的公司正使用 DevOps 和 CI/CD 来构建软件,以便于所以构建工作都能够在无需人力或与 GUI 交互的情况下自动完成。
  • 开发人员因 Xcode 代码签名失败,试图通过重新生成与修复证书和配置文件来修复代码签名问题上耗费了大量的时间。
    第三方工具如 Fastlane 可以让 iOS 开发者更加轻松地创建 build 脚本。然而,当 Apple 在底层技术上作出更改,Fastlane 将无法使用,开发人员会花费数小时、数天甚至数周时间来修复损坏的部署脚本。在某些情况下,工程师们必须等到 Fastlane 实现了新更改。
  • 如果你是一个 iOS 开发人员或工程师,并只是想一直做一个 iOS 工程师,那么你没有必要去学习这些知识。但如果你想要在你的职业生涯中成长,那么你就必须要详细了解这些底层工具、技术和整个 iOS 生态。如果你不了解这些底层技术,不管你在 iOS 开发技术上有多出色,都无法让你成为一个 iOS 技术主管或一个 iOS 技术架构师之类的角色。作为一个技术架构师,你应该能够在不依赖于 Xcode 或其他第三方工具的情况下快速修复代码签名或类似的基础架构问题。

希望这能足以证明代码签名的重要性。要学习还是离开取决于你。

先决条件

让我们进入 iOS 代码签名的世界。我们将从头开始涵盖全部所需与其在底层所做的事。开始前我们需要以下准备:

  • macOS
  • Apple Developer Membership
  • Xcode 9+

所有这些你都准备好后,就可以开始深入了解 iOS 代码签名了。

代码签名的好处

Apple 之所以要我们经历繁琐的代码签名流程是因为这对用户有一定的益处。当用户从 Apple App Store 上下载 app 时他们能感到安全,是因为代码签名保证了:

  • 合法的开发者编写了这些代码,且具有 app 作者或签发者的身份
  • 代码签名保证了代码在作者编写之后没有被其他人篡改过。它保证了作者生成的代码是原始的,并且在作者签名之后没有任何其他东西被注入到原始代码中。
  • 用户能够从他们信赖的开发人员那里下载应用,而不必担心太多安全问题。
  • 代码签名是为了保证 iOS 用户的安全,以让他们使用从 AppStore 下载的应用时感到可信赖。

代码签名的局限

尽管代码签名是为了用户的安全,但在有些方面并不总能解决安全问题。

  • 代码签名保证了代码来自 Apple 开发者计划成员认证的合法开发者,但不能保证代码本身没有安全漏洞。
  • 代码签名不能保证在 App 运行期间动态加载的插件是安全的。
  • 对已签名的代码没有数字版权管理或拷贝保护技术。

现在,我们已经了解了学习代码签名的重要性,以及代码签名的好处和局限。在下一篇文章里,我们将会了解重要概念:代码签名过程是如何开始的,即 Certificate Signing Requests 证书签名请求。


Post 2: 证书签名请求

在上一篇文章中,我们已经说到了代码签名的基础知识,它所带来的好处及局限。现在我们将开始了解一些代码签名的概念。让我们先从所有代码签名起始的地方—-证书签名请求开始。也许你已经知道我们需要一个 development (开发)和一个 distribution (发布)证书来把一个 app 构建和部署到 AppStore。创建一个 iOS 开发证书是每一个 iOS 开发者都需要做的第一步。创建证书的过程从证书签名请求开始。在这片文章中,我们将会涵盖证书签名请求的概念(Certificate Signing Request,CSR)及使用 CSR 来请求证书的过程。

什么是 CSR

代码签名请求 CSR 是一个由申请人向证书颁发机构发送的用于申请数字身份证书的消息。它使用了 Public Key Infrastructure 公钥基础设施,是一种用于创建、管理与分发数字证书的策略。创建 CSR 的过程在 PKI 中非常规范化,申请人需要在本地机器上生成公钥和私钥,之后申请人需要将公钥与个人信息如邮箱、县等附在 CSR 中。申请人持有私钥。CSR 需要的典型信息包括:CN(通用名称)、组织、组织单位、国家、邮箱。CSR 包含了证书请求信息、签名算法和请求者的数字签名,以防止请求伪造证书。

将 CSR 发送给 Apple

Certificate Signing Request(CSR)指的是从证书机构(CA)申请证书的过程,这里的证书机构就是 Apple,以便 Apple 能够在请求者详细信息正确的情况下发放开发者证书。请求需要从本地 macOS 机器上创建。

从 GUI 创建 CSR

CSR 可以通过 Keychain Access 来创建,Apple 编写了一些文档,但总结起来你需要做的是:

  • 在 Spotlight(聚焦搜索)中找到 Keychain Access(钥匙串访问)
  • 选择 Keychain Access(钥匙串访问) > Certificate Assistant(证书助理) > Request a Certificate From a Certificate Authority(从证书颁发机构请求证书)
  • 填写你的详细信息,如邮箱、姓名和国家,通常跟随屏幕上的指示就好
  • 选中选项 “Saved to disk(保存到磁盘)”
  • 指定一个文件名,点击保存
  • 点击继续,之后证书助理会创建一个 CSR 并将其保存在你的电脑上

从命令行创建 CSR

如果觉得用 GUI 麻烦,同样也有使用命令行创建 CSR 的方法。你可以通过运行几个快捷命令来拿到 CSR,只要将你的名字、邮箱与国家填写上去:

1
2
$ openssl genrsa -out mykey.key 2048
$ openssl req -new -key mykey.key -out CertificateSigningRequest.certSigningRequest -subj "/emailAddress=yourAddress@example.com, CN=Your Name Dev Key, C=GB”

在过程结束时,你就可以在本地 mac 上看到一个有着奇怪名字的文件:CertificateSigningRequest.certSigningRequest,这就是我们需要上传给 Apple Developer 用于生成开发与发布证书的文件。我们将在稍后介绍证书。

现在,我们的本地机器上就有了我们的 CSR。让我们来了解一下创建 CSR 时发生了些什么:

  • 在创建 CSR 时,公钥/私钥对被生成
  • 公钥被附在你的 CSR 上
  • 私钥被保存在你的本地机器中

如果你想了解更多有关公钥/私钥的知识以及他们是如何运作的,你可以阅读 Asymmetric Cryptography 非对称加密,但大体上公钥用在公共环境,私钥是私人持有的,你不应该将它分享给任何人。

现在来看一下 CSR 内部有些什么。在你的终端中运行下面的命令,这将会把 CSR 内部的基本信息显示出来。

1
$ openssl asn1parse -i -in CertificateSigningRequest.certSigningRequest

如果你想看到以文本方式显示 CSR,看到公钥算法 rsaEncryption 和签名算法 sha256WithRSAEncryption,你可以运行下面的命令:

1
$ openssl req -text -noout -in CertificateSigningRequest.certSigningRequest

这个密钥对由 RSA(2048 bit) 生成,公钥附在 CSR 中,私钥被用于实际签名,所以我们必须保持私密。在多个 macOS 上生成 CSR 不是一个好主意,因为用一台 mac 生成的密钥对不能被呈现在另一台 mac 上。直到我们创建 P12 格式的证书之前,最好使用一台 mac 来生成 CSR。

现在,我们已经看到了如何通过钥匙串访问及使用命令行来创建 CSR,在下一篇文章中,我们将会了解 iOS 开发与发布所需证书的细节。