签名

概述

我们的 代码签名 在独立的任务中进行,这既是为了性能考虑,也是为了限制哪些机器可以访问签名服务器和密钥。

通常,待签名的二进制文件在一个任务中生成,而请求签名则在第二个任务中进行。我们通过 信任链 验证请求,签名二进制文件,然后将签名的二进制文件或原始二进制文件 + 分离签名作为工件上传。

任务的工作原理

Scriptworker 验证任务定义和上游任务,直到它确定该图来自受信任的树;这是 信任链 验证。此验证的一部分是下载并验证任务有效负载中 upstreamArtifacts 的 sha 值。

一个签名任务有效负载示例

{
  "payload": {
    "upstreamArtifacts": [{
      "paths": ["public/build/target.dmg"],
      "formats": ["macapp"],
      "taskId": "abcde",
      "taskType": "build"
    }, {
      "paths": ["public/build/target.tar.gz"],
      "formats": ["autograph_gpg"],
      "taskId": "12345",
      "taskType": "build"
    }]
  }
}

在上面的示例中,scriptworker 将从任务 abcde 下载 target.dmg,从任务 12345 下载 target.tar.gz,并通过 信任链 验证来验证它们的 sha 值和任务定义。然后它将启动 signingscript,后者从签名服务器池请求签名令牌。

Signingscript 确定它想要使用 macapp 格式对 target.dmg 进行签名,使用 autograph_gpg 格式对 target.tar.gz 进行签名。每个 签名格式 都有其自己的行为。在执行任何特定于格式的检查或优化后,它调用 signtool 将文件提交到签名服务器并轮询它们以获取签名的输出。一旦它下载了所有签名的输出文件,它就会退出,并且 scriptworker 将上传签名的二进制文件。

我们可以为给定的一组格式指定来自单个任务的多个路径,以及为给定的一组路径指定多种格式。

签名类型

我们目前有多种签名类型。这些可以分为几个类别

构建内部签名:某些软件包类型需要对内部进行签名。对于某些软件包类型,例如 exe 或 dmg,我们会提取内部二进制文件(例如 xul.dll)并对其进行签名。对于某些 zip 文件、exe 和 dmg 来说确实如此;我们需要先对内部进行签名,然后才能 [重新]创建软件包。对于 Linux tarball,我们不需要特殊的打包,因此我们可以在此任务中对所有内容进行签名。这些类型包括 build-signingshippable-l10n-signingrelease-eme-free-repack-signingrelease-partner-repack-signing

构建重新打包签名:一旦我们获取签名的内部文件并对其进行打包(称为 repackage),某些格式需要一个签名的外部软件包。如果我们从签名的内部文件中创建了一个更新 MAR 文件,则 MAR 文件也需要签名。这些类型包括 repackage-signingrelease-eme-free-repack-repackage-signingrelease-partner-repack-repackage-signing

release-source-signingpartials-signing 对发布源 tarball 和部分更新 MAR 进行签名。

Mac 签名和公证:对于 Mac,我们有 *-mac-signing,它对应用程序和 pkg 进行签名,*-mac-notarization 提交给 Apple 并将生成的票据钉合到二进制文件中。

我们在发布目录的顶部生成签名的校验和,例如在 60.0 中。为了生成这些校验和,我们有校验和签名类型,包括 release-generate-checksums-signingchecksums-signingrelease-source-checksums-signing

签名格式

已知的 signingscript 格式列在 签名密码文件 的第四列中。

格式在 upstreamArtifacts 字典列表中指定。 autograph_gpg 签名会生成一个分离的 .asc 签名文件。由于其性质,如果为给定的一组文件提供了多种格式,我们将在最后进行 gpg 签名。

jar 签名是 Android apk 签名。签名后,我们会 zipalign apk。这包括 focus-jar 格式,这只是为 Focus 应用程序指定一组不同的密钥的一种方式。

macapp 签名接受 dmgtar.gz;在提交到签名服务器之前,它会将 dmg 文件转换为 tar.gz。签名的二进制文件为 tar.gz

authenticode 签名接受单个二进制文件或 zip 文件。我们对单个文件或 zip 文件的内部进行签名,跳过任何已签名的文件和少数几个被列入黑名单的文件(使用 should_sign_windows 函数)。它根据输入返回一个签名的单个二进制文件或包含签名的内部文件的 zip 文件。此格式包括 autograph_authenticodeautograph_authenticode_stub

mar 签名对我们的更新文件(Mozilla ARchive)进行签名。 mar_sha384 相同,但使用不同的散列算法。

autograph_widevine 也与视频相关;请参阅 widevine 网站。我们对软件包内的特定文件进行签名,并重新构建用于更新的 precomplete 文件。

证书级别

证书级别是我们分离签名权限的方式。我们有以下级别

depdepend 的缩写,是 Netscape 时代的术语。(这指的是不会覆盖构建的构建,因此它们保留了来自先前构建的依赖项对象文件缓存。)这些证书和密钥旨在用于我们不打算发布的 Try 或推送构建。其中许多是自签名的,没有很高的安全价值;它们旨在用于测试目的。

nightly 指的是 Nightly 产品和渠道。我们使用这些密钥来对 nightly 构建进行签名和发布,以及在 beta 渠道上的 Devedition。由于这些是发布密钥,因此它们受到限制;只有部分分支可以请求使用这些密钥。

release 指的是我们的发布版本,来自 beta、release 或 esr 渠道。这些是限制最严格的密钥。

我们通过范围请求特定的证书级别:project:releng:signing:cert:dep-signingproject:releng:signing:cert:nightly-signingproject:releng:signing:cert:release-signing。每个签名任务都必须具有其中一个范围,并且只有启用 nightly 和 release 的分支才能使用后两个范围。如果在未列入允许列表的分支上使用其中一个受限范围调度任务,则信任链验证将引发异常。

签名 scriptworker workerTypes

linux-depsigning 池处理所有非 Mac dep 签名。它们在 try 和 autoland 上被大量使用,但也用于其他分支。它们验证 信任链 工件,但不验证其签名,并且它们没有 gpg 密钥来签名自己的信任链工件。这是设计使然;如果生产 scriptworker 是 depsigning worker 的下游,则信任链应该并且将会断开。

linux-signing 池是生产签名池;它处理 nightly 和 release 签名请求。因此,它验证上游信任链和所有签名,并对其信任链工件进行签名。

**linux-devsigning** 池用于 signingscript 和 scriptworker 的开发。由于它未用于任何面向 Firefox 开发者的分支,因此 Mozilla Releng 可以对该池进行重大更改,而不会影响其他团队。

类似地,我们还有 **mac-depsigning** 和 **mac-signing** 池,分别用于处理 CI 以及 nightly/release 版本的签名。