🏡 index : quine-global-boneyard/electron-builder.git

import { log } from "builder-util"
import { readFile, writeFile } from "fs/promises"
import * as path from "path"
import { NtExecutable, NtExecutableResource, Resource } from "resedit"
import { AsarIntegrity } from "../asar/integrity"

/** @internal */
export async function addWinAsarIntegrity(executablePath: string, asarIntegrity: AsarIntegrity) {
  const buffer = await readFile(executablePath)
  const executable = NtExecutable.from(buffer)
  const resource = NtExecutableResource.from(executable)

  const versionInfo = Resource.VersionInfo.fromEntries(resource.entries)
  if (versionInfo.length !== 1) {
    throw new Error(`Failed to parse version info in ${executablePath}`)
  }

  const languages = versionInfo[0].getAllLanguagesForStringValues()
  if (languages.length !== 1) {
    throw new Error(`Failed to locate languages in ${executablePath}`)
  }

  // See: https://github.com/electron/packager/blob/00d20b99cf4aa4621103dbbd09ff7de7d2f7f539/src/resedit.ts#L124
  const integrityList = Array.from(Object.entries(asarIntegrity)).map(([file, { algorithm: alg, hash: value }]) => ({
    file: path.win32.normalize(file),
    alg,
    value,
  }))

  resource.entries.push({
    type: "INTEGRITY",
    id: "ELECTRONASAR",
    bin: Buffer.from(JSON.stringify(integrityList)),
    lang: languages[0].lang,
    codepage: languages[0].codepage,
  })

  resource.outputResource(executable)

  await writeFile(executablePath, Buffer.from(executable.generate()))
  log.info({ executablePath: log.filePath(executablePath) }, "updating asar integrity executable resource")
}