密钥轮替

Robert Ferens
Robert Ferens
Demián Renzulli
Demián Renzulli

本文档提供了有关独立 Web 应用 (IWA) 的密钥 轮替流程的重要信息,包括何时需要进行密钥 轮替,以及开发者在密钥丢失或泄露时必须遵循的步骤。

IWA 的密钥轮替

密钥轮替是一种机制,允许在私钥泄露或丢失时替换用于为 IWA 签名的私钥。此过程可确保应用正常运行,并保持稳定的软件包 ID 和来源,从而确保应用的发布和更新不会中断。

密钥轮替流程不需要管理员或用户进行任何更改,如果正确执行,他们不会察觉到任何变化。在初始许可名单流程中建立的受信任联系 渠道对于 启用密钥轮替至关重要。

密钥轮替的必要性

在以下两种主要情况下,必须进行密钥轮替:

  • 密钥泄露或泄露风险: 如果您的私有签名密钥泄露或可能泄露,您必须立即启动密钥轮替流程以保护您的应用。泄露的密钥可能会被用来冒充您,对您的应用用户造成损害,并危及您公司的声誉。
  • 密钥丢失: 如果您无法访问您的私有签名密钥,并且无法为新更新签名,则需要进行密钥轮替,以重新建立发布应用的能力。

开发者要求

在启动密钥轮替之前,您必须满足以下条件:

  • 已列入许可名单的应用: 只有已列入许可名单的应用才能进行 密钥轮替。
  • 受信任的电子邮件地址: 您必须使用在许可名单流程中提供的受信任电子邮件地址来请求密钥轮替。

重新签署托管应用并发布新版本

轮替密钥后,所有未用有效密钥签名的已安装应用实例都会被屏蔽。为避免用户体验受到影响,您必须提供使用新密钥(或两个密钥)签名的应用。如需了解 重新签署软件包的技术详情,请参阅 如何使用多个密钥为软件包签名部分。 根据您的具体情况,有以下几种不同的情形:

情形 A:密钥未丢失(例如主动轮替或泄露)

您必须使用两个密钥(旧密钥和新密钥)为应用签名,并通过以下任一方式将应用提供给用户:

  • 发布新应用版本(将新版本添加到更新清单),或
  • 更新托管的 .swbn 文件(在更新清单中链接),使其使用两个密钥签名。借助 CLI 工具,您可以向现有 swbn 软件包添加另一个签名。

必须在 Google 处理密钥轮替之前完成此操作,以确保您的用户不会注意到更改。

情形 B:密钥丢失

由于无法使用丢失的密钥为应用签名,因此这种情况更为复杂。 请请求密钥轮替,并向您的 Google 联系人咨询后续步骤。系统可能会要求您按照以下说明将新签名添加到托管软件包。

密钥轮替流程

密钥轮替流程包括以下步骤:

步骤 操作 详细信息 负责人
1 请求密钥轮替 开发者/合作伙伴通过许可名单流程 中提供的受信任电子邮件地址与其 Google 联系人(合作伙伴工程团队或其他联系人)联系,并说明原因,请求获取密钥轮替说明。如果密钥泄露,我们建议您附上使用旧密钥和新密钥签名的软件包的更新清单,以加快流程。 开发者 / 合作伙伴
2 回复请求者 Google 联系人向请求者提供进一步的说明和问题。此步骤可能涉及多次来回沟通。 Google 联系人
3 提供数据 开发者/合作伙伴按照说明操作,其中可能包括:
  • 使用新密钥重新签署软件包。
  • 更新或提供包含更新应用的更新清单。
  • 提供更多信息。例如,情况详情、危险或技术详情,如合作伙伴的应用发布周期。
  • 确认已准备好进行轮替:我们建议在更新客户端应用并确保它们已更新后至少三天再执行此操作。
开发者 / 合作伙伴
4 处理请求并
提供反馈
Google 会审核密钥轮替请求,并在一个工作周内回复,批准或拒绝该请求,或与开发者联系以询问更多问题。获得批准后,Google 会轮替密钥并提供反馈。 Google 联系人

更新渠道和版本固定

管理员有时会使用自定义更新渠道或版本固定,以便管理客户端设备上的应用版本。密钥轮替后,所有使用无效密钥安装的应用都会失效并被屏蔽。为防止这种情况发生,还必须更新在 update_manifest.json 中提供的链接下托管的应用的早期版本,并在密钥轮替之前使用两个签名进行签名。如果您的旧密钥丢失,并且无法使用两个密钥为应用签名,请立即通知您的 Google 联系人。我们将与您合作,缓解这种情况,以便在不影响用户工作流的情况下更新应用。

如何使用多个密钥为软件包签名

本部分介绍如何通过 CLI 工具或 Webpack/Rollup/Vite 插件配置使用一个或两个密钥为 Web 软件包签名。CLI 工具还允许向现有 swbn 软件包添加一个签名,这在密钥丢失或更新之前的托管软件包时可能很有用。

CLI 工具

首先,确保您已使用 npm 安装 wbn-sign 软件包:

$ npm i wbn-sign

添加 -g 以全局安装软件包,而不是仅在当前文件夹中安装。

使用一个密钥签名

$ wbn-sign -i unsigned.wbn -o signed.swbn -k private.pem

使用两个密钥签名

$ wbn-sign sign webbundle.wbn old_key.pem new_key.pem -o signed.swbn --web-bundle-id <your-id-from-old-private>

如果 old_key 是应用初始版本使用的第一个密钥,则可以跳过 --web-bundle-id <id> 实参,软件包 ID 将从该密钥派生。您可以使用 wbn-sign info signed.swbn 命令验证软件包 ID。

向现有软件包添加签名

$ wbn-sign add-signature signed.swbn key3.pem --in-place

如果您不想替换软件包,而是想创建新的双签名,请使用 -o

有关 CLI 工具的更多信息

如需详细了解如何使用 CLI 工具,请查看 npm wbn-sign 页面。或者,使用:wnb-sign help.

Webpack 插件

使用一个密钥签名

如需将 Webpack 插件配置为使用单个私钥为 IWA 签名,请执行以下操作:

  • 设置 WebBundlePlugin 以直接从此密钥自动派生所需的基本网址。
  • 使用单个 NodeCryptoSigningStrategy 生成签名的 .swbn 文件。
// key is parsePemKey(private.pem)

plugins.push(
  new WebBundlePlugin({
    baseURL: new WebBundleId(key).serializeWithIsolatedWebAppOrigin(),
    static: { dir: 'public' },
    output: 'signed.swbn',
    integrityBlockSign: {
      strategy: new NodeCryptoSigningStrategy(key)
    }
  })
)

使用两个密钥签名

当您需要在密钥轮替期间为应用进行双重签名时:

  • 根据原始密钥 (old_key) 定义 webBundleId 和基本网址,以确保应用身份对用户保持稳定。
  • 使用签名策略数组同时应用旧私钥和新私钥。
// old_key is parsePemKey(old_private.pem)
// new_key is parsePemKey(new_private.pem)

plugins.push(
  new WebBundlePlugin({
    baseURL: new WebBundleId(old_key).serializeWithIsolatedWebAppOrigin(),
    static: { dir: 'public') },
    output: 'signed.swbn',
    integrityBlockSign: {
      strategies: [
        new NodeCryptoSigningStrategy(old_key),
        new NodeCryptoSigningStrategy(new_key)
      ],
      webBundleId: new WebBundleId(old_key).serialize()
    }
  })
)

Rollup 或 Vite 插件

使用一个密钥签名

如需使用 Rollup 或 Vite 插件使用单个私钥为应用签名,与 Webpack 设置类似,该插件使用单个签名策略,并处理从提供的密钥派生基本网址以生成签名输出。

// key is parsePemKey(private.pem)

plugins.push({
  ...wbn({
    baseURL: new WebBundleId(key).serializeWithIsolatedWebAppOrigin(),
    static: { dir: 'public' },
    output: 'signed.swbn',
    integrityBlockSign: {
      strategy: new NodeCryptoSigningStrategy(key)
    }
  }),
  enforce: 'post'
})

使用两个密钥签名

如需使用 Rollup 或 Vite 为应用进行双重签名,您必须将插件配置为接受多个密钥。此代码段使用策略数组同时应用旧私钥和新私钥。它通过明确维护从原始现有密钥派生的基本网址和 webBundleId,确保无缝过渡。

// old_key is parsePemKey(old_private.pem)
// new_key is parsePemKey(new_private.pem)

plugins.push({
  ...wbn({
    baseURL: new WebBundleId(old_key).serializeWithIsolatedWebAppOrigin(),
    static: { dir: 'public' },
    output: 'signed.swbn',
    integrityBlockSign: {
      strategies: [
        new NodeCryptoSigningStrategy(old_key),
        new NodeCryptoSigningStrategy(new_key)
      ],
      webBundleId: new WebBundleId(old_key).serialize()
    }
  }),
  enforce: 'post'
})

总结

成功管理 IWA 的密钥轮替对于维护应用发布的安全性至关重要。无论您的具体情况如何(例如,密钥是否丢失),按照概述的步骤操作可确保用户体验尽可能不受影响。通过利用为 Webpack、Rollup 或 Vite 提供的 CLI 工具或插件配置,您可以高效管理应用的签名并顺利完成密钥轮替流程。在紧急情况下,请务必通过指定的受信任电子邮件地址及时与您的 Google 联系人沟通。