Key rotation

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

This document provides essential information regarding the process of key rotation for an Isolated Web App (IWA), including when it is necessary and the steps developers must follow if a key is lost or compromised.

Key rotation for IWAs

Key rotation is a mechanism that allows the private keys used to sign your IWA to be replaced in the event of a leak or loss. This process keeps the app functional and maintains a stable bundle ID and origin, ensuring the continuity of your app's distribution and updates.

The key rotation process doesn't require any administrator or user changes, and if performed correctly, won't be perceptible to them. The trusted contact channels established during the initial allowlisting process are essential for enabling key rotation.

The need for key rotation

Key rotation is strictly necessary in two primary scenarios:

  • Key leak or compromise: If your private signing key is compromised or potentially leaked, you must immediately start the key rotation process to secure your application. A leaked key can be used to impersonate you, cause harm to your app users, and endanger your company's reputation.
  • Key loss: If you lose access to your private signing key and cannot sign new updates, key rotation is required to re-establish your ability to distribute your application.

Developer requirements

Before initiating a key rotation, you must meet the following criteria:

  • Allowlisted app: Only allowlisted apps can be subject to a key rotation.
  • Trusted email: You must use the trusted email address provided during the allowlisting process to request a key rotation.

Resigning hosted apps and releasing new versions

After rotating a key, all installed app instances that are not signed with a valid key are blocked. To prevent disruptions for your users, you must deliver an app signed with the new key (or both keys). The technical details of resigning bundles can be found in the section How to sign a bundle with multiple keys. Depending on your specific situation, there are different scenarios:

Scenario A: The key is not lost (for example, proactive rotation or leak)

You must sign the app with both keys (the old and the new one) and deliver them to users by either:

  • Releasing a new app version (adding the new version to your update manifests), or
  • Updating your hosted .swbn files (linked in your update manifests) to be signed with both keys. The CLI tool lets you add another signature to the existing swbn bundle.

This must be done before the key rotation is processed by Google to ensure your users won't notice the change.

Scenario B: The key is lost

Because the app cannot be signed with the lost key this case is more complex. Request the key rotation and ask your Google contact for further steps. You might be asked to add the new signatures to your hosted bundles following these instructions.

Key rotation process

The process for key rotation involves the following steps:

Step Action Details Responsible
1 Request key rotation Developer/partner reaches out to their Google contact (Partner Engineering or other point of contact) through trusted email provided in allowlisting process and asks for the key rotation instructions explaining the reason. In the key compromised case we recommend attaching the update manifest with bundles signed with old and new keys to speed up the process. Developer / Partner
2 Response to requestor Google contact provides further instructions and questions to the requestor. This step may involve a few back-and-forths. Google Contact
3 Provide data Developer/partner follows instructions, which among others may involve:
  • Resigning bundles with new keys.
  • Updating or providing your update manifest with updated apps.
  • Providing more information. For example, situation details, dangers, or technical details like a partner's app release cycle.
  • Acknowledging the readiness for rotation: we suggest doing that after at least three days after updating client apps and making sure they were updated.
Developer / Partner
4 Request processing and
providing feedback
Google reviews the key rotation request and responds within one business week, either approving or denying it, or contacting the developer with further questions. Upon approval, Google rotates the key and provides feedback. Google Contact

Update channel and version pinning

Administrators sometimes use custom update channels or version pinning, which lets them manage app versions on their client devices. After a key rotation, all apps installed with invalid keys become invalid and are blocked. To prevent this, earlier versions of apps hosted under links provided in the update_manifest.json must also be updated and signed with two signatures prior to the key rotation. If your old key is lost and the app cannot be signed with two keys, notify your Google contact immediately. We will work with you to mitigate the situation so the app can be updated without disturbing your users' workflows.

How to sign a bundle with multiple keys

This section describes how you can sign your web bundles with one or two keys through CLI tools, or Webpack/Rollup/Vite plugins configuration. CLI tools also enable adding one more signature to existing swbn bundles, which might be useful in key-lost cases or updating the previous hosted bundles.

CLI Tools

First, ensure you have the wbn-sign package installed with npm:

$ npm i wbn-sign

Add -g to install the package globally instead of doing it only in the current folder.

Signing with one key

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

Signing with two keys

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

The --web-bundle-id <id> argument can be skipped, if old_key is the first key the initial version of the app was signed with, then the bundle ID will be derived from the key. You can verify the bundle ID with wbn-sign info signed.swbn command.

Adding a signature to the existing bundle

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

Use -o if you don't want to override the bundle but create a new double-signed.

More information about CLI Tool

For more information on using CLI tool check the npm wbn-sign page. Alternatively, use: wnb-sign help.

Webpack plugin

Signing with one key

To configure the Webpack plugin to sign your IWA using a single private key:

  • Set up the WebBundlePlugin to automatically derive the required Base URL directly from this key.
  • Use a single NodeCryptoSigningStrategy to produce your signed .swbn file.
// 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)
    }
  })
)

Signing with two keys

When you need to double-sign your application during a key rotation:

  • Define the webBundleId and Base URL based on your original (old_key) to ensure the app's identity remains stable for your users.
  • Use an array of signing strategies to apply both your old and new private keys.
// 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 or Vite plugin

Signing with one key

To use the Rollup or Vite plugin to sign your application with a single private key, similar to the Webpack setup, the plugin uses a single signing strategy and handles deriving the Base URL from the provided key to generate your signed output.

// 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'
})

Signing with two keys

To double-sign your application using Rollup or Vite, you must configure the plugin to accept multiple keys. This snippet applies both the old and new private keys using the strategies array. It ensures a seamless transition by explicitly maintaining the Base URL and webBundleId derived from your original, existing key.

// 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'
})

Conclusion

Successfully managing key rotation for your IWA is crucial for maintaining the security and continuity of your application's distribution. Independently on your specific situation (for example, whether the key is lost or not), following the outlined steps ensures that your users experience minimal disruption. By utilizing the provided CLI tools or plugin configurations for Webpack, Rollup, or Vite, you can efficiently manage your app's signatures and navigate the key rotation process smoothly. In emergency scenarios, remember to communicate promptly with your Google contact through your designated trusted email.