From f8c832d80db96841d2ac1bc50dca9d64c2cd2c83 Mon Sep 17 00:00:00 2001 From: Erick Zhao Date: Thu, 11 Apr 2024 13:41:58 -0700 Subject: [PATCH] docs: update ASAR integrity tutorial (#41828) * docs: document windows asar integrity * docs: update ASAR integrity tutorial * fix lint --------- Co-authored-by: Samuel Attard --- docs/tutorial/asar-integrity.md | 122 ++++++++++++++++++++++++++------ 1 file changed, 100 insertions(+), 22 deletions(-) diff --git a/docs/tutorial/asar-integrity.md b/docs/tutorial/asar-integrity.md index 44d9aa9b13ba..7db53810f644 100644 --- a/docs/tutorial/asar-integrity.md +++ b/docs/tutorial/asar-integrity.md @@ -5,40 +5,50 @@ slug: asar-integrity hide_title: false --- -## Platform Support +ASAR integrity is an experimental feature that validates the contents of your app's +[ASAR archives](./asar-archives.md) at runtime. -Currently ASAR integrity checking is only supported on macOS. +## Version support -## Requirements +Currently, ASAR integrity checking is supported on: -### Electron Forge / Electron Packager +* macOS as of `electron>=16.0.0` +* Windows as of `electron>=30.0.0` -If you are using `>= @electron/packager`, `>= electron-packager@15.4.0` or `>= @electron-forge/core@6.0.0-beta.61` then all these requirements are met for you automatically and you can skip to [Toggling the Fuse](#toggling-the-fuse). +In order to enable ASAR integrity checking, you also need to ensure that your `app.asar` file +was generated by a version of the `@electron/asar` npm package that supports ASAR integrity. -### Other build systems +Support was introduced in `asar@3.1.0`. Note that this package has since migrated over to `@electron/asar`. +All versions of `@electron/asar` support ASAR integrity. -In order to enable ASAR integrity checking you need to ensure that your `app.asar` file was generated by a version of the `asar` npm package that supports asar integrity. Support was introduced in version `3.1.0`. +## How it works -Your must then populate a valid `ElectronAsarIntegrity` dictionary block in your packaged apps `Info.plist`. An example is included below. +Each ASAR archive contains a JSON string header. The header format includes an `integrity` object +that contain a hex encoded hash of the entire archive as well as an array of hex encoded hashes for each +block of `blockSize` bytes. -```plist -ElectronAsarIntegrity - - Resources/app.asar - - algorithm - SHA256 - hash - 9d1f61ea03c4bb62b4416387a521101b81151da0cfbe18c9f8c8b818c5cebfac - - +```json +{ + "algorithm": "SHA256", + "hash": "...", + "blockSize": 1024, + "blocks": ["...", "..."] +} ``` -Valid `algorithm` values are currently `SHA256` only. The `hash` is a hash of the ASAR header using the given algorithm. The `asar` package exposes a `getRawHeader` method whose result can then be hashed to generate this value. +Separately, you need to define a hex encoded hash of the entire ASAR header when packaging your Electron app. -## Toggling the Fuse +When ASAR integrity is enabled, your Electron app will verify the header hash of the ASAR archive on runtime. +If no hash is present or if there is a mismatch in the hashes, the app will forcefully terminate. -ASAR integrity checking is currently disabled by default and can be enabled by toggling a fuse. See [Electron Fuses](fuses.md) for more information on what Electron Fuses are and how they work. When enabling this fuse you typically also want to enable the `onlyLoadAppFromAsar` fuse otherwise the validity checking can be bypassed via the Electron app code search path. +## Enabling ASAR integrity in the binary + +ASAR integrity checking is currently disabled by default in Electron and can +be enabled on build time by toggling the `EnableEmbeddedAsarIntegrityValidation` +[Electron fuse](fuses.md). + +When enabling this fuse, you typically also want to enable the `onlyLoadAppFromAsar` fuse. +Otherwise, the validity checking can be bypassed via the Electron app code search path. ```js @ts-nocheck const { flipFuses, FuseVersion, FuseV1Options } = require('@electron/fuses') @@ -53,3 +63,71 @@ flipFuses( } ) ``` + +:::tip Fuses in Electron Forge + +With Electron Forge, you can configure your app's fuses with +[@electron-forge/plugin-fuses](https://www.electronforge.io/config/plugins/fuses) +in your Forge configuration file. + +::: + +## Providing the header hash + +ASAR integrity validates the contents of the ASAR archive against the header hash that you provide +on package time. The process of providing this packaged hash is different for macOS and Windows. + +### Using Electron tooling + +Electron Forge and Electron Packager do this setup automatically for you with no additional +configuration. The minimum required versions for ASAR integrity are: + +* `@electron/packager@18.3.1` +* `@electron/forge@7.4.0` + +### Using other build systems + +#### macOS + +When packaging for macOS, you must populate a valid `ElectronAsarIntegrity` dictionary block +in your packaged app's `Info.plist`. An example is included below. + +```xml title='Info.plist' +ElectronAsarIntegrity + + Resources/app.asar + + algorithm + SHA256 + hash + 9d1f61ea03c4bb62b4416387a521101b81151da0cfbe18c9f8c8b818c5cebfac + + +``` + +Valid `algorithm` values are currently `SHA256` only. The `hash` is a hash of the ASAR header using the given algorithm. +The `@electron/asar` package exposes a `getRawHeader` method whose result can then be hashed to generate this value +(e.g. using the [`node:crypto`](https://nodejs.org/api/crypto.html) module). + +### Windows + +When packaging for Windows, you must populate a valid [resource](https://learn.microsoft.com/en-us/windows/win32/menurc/resources) +entry of type `Integrity` and name `ElectronAsar`. The value of this resource should be a JSON encoded dictionary +in the form included below: + +```json +[ + { + "file": "resources\\app.asar", + "alg": "sha256", + "value": "9d1f61ea03c4bb62b4416387a521101b81151da0cfbe18c9f8c8b818c5cebfac" + } +] +``` + +::: info + +For an implementation example, see [`src/resedit.ts`](https://github.com/electron/packager/blob/main/src/resedit.ts) +in the Electron Packager code. + +:::