Electron ASAR 完整性校验(ASAR Integrity)原理与接入指南
Electron ASAR 完整性校验ASAR Integrity原理与接入指南【免费下载链接】electron:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS项目地址: https://gitcode.com/GitHub_Trending/el/electronASAR Integrity 是 Electron 提供的运行时安全校验机制开启后应用会在运行时对自身app.asar的内容与打包期写入的哈希进行一致性校验一旦发现文件被篡改便直接强制终止进程从而防止应用代码被静态修改后重新分发。本文以本仓库官方教程 docs/tutorial/asar-integrity.md 为骨架结合 Electron 源码、fuse 体系与集成测试系统讲解 ASAR Integrity 的版本支持、工作原理、fuse 开关、macOS/Windows 双平台的打包期哈希注入方法以及校验失败时的真实表现。ASAR Integrity 是什么ASARAtom Shell Archive是 Electron 用来打包应用源码的归档格式格式说明见 asar-archives 教程。普通 ASAR 归档没有防篡改能力攻击者拿到应用包后可以解包、修改其中任意 JS 再重新打包由于可执行文件并未对归档内容做校验被篡改的代码照样会被加载执行。ASAR Integrity 正是针对这一缺口设计的安全特性。它的核心思想是**“打包期计算哈希运行期验证哈希”**在打包时把整个 ASAR 头的哈希header hash嵌入到可执行文件的元数据里在运行时Electron 校验 ASAR 头的哈希是否一致同时在按需读取文件内容时对照归档内嵌的逐文件/逐块哈希做校验若头哈希缺失或对不上、或读取的内容校验失败应用会强制终止forcefully terminate而不是带着被篡改的数据继续运行。按官方教程描述该特性仍处于实验阶段experimental默认关闭需要打包期显式开启。它针对的核心攻击面是对分发渠道上应用包的静态篡改让篡改后的应用无法正常启动。版本支持情况平台支持起始版本macOSelectron 16.0.0Windowselectron 30.0.0除了 Electron 本身版本要满足要求之外还需要打包app.asar时使用的 asar 工具支持生成完整性元数据asar3.1.0首次引入了完整性支持此后该 npm 包迁移更名为electron/asar所有版本的electron/asar均支持 ASAR integrity当前仓库的 devDependency 即为electron/asar^4.3.0。关于 Mac App StoreMAS构建官方文档特别说明ASAR integrity 在 MASMac App Store构建中完全支持且被推荐作为最佳实践。需要理解的是通过 MAS 安装的应用其Resources/目录已被系统保护目录属主为 root普通进程无法写入系统层面已有只读防护即便如此ASAR integrity 仍能提供额外一层安全纵深如果你使用 Electron 的 MAS 构建产物、却通过非 App Store 渠道分发例如官网直接下载这类安装不具备系统级只读保护此时 ASAR integrity 尤为重要。工作原理两级哈希体系理解 ASAR Integrity 需要区分“归档内部”与“归档外部”两级哈希归档头 JSON 中的 integrity 元数据ASAR 文件本身是一段Pickle化的头部 文件数据区。每个 ASAR 归档内含一段 JSON 字符串形式的 headerheader 中会包含integrity对象其结构如下取自官方教程示例{ algorithm: SHA256, hash: ..., blockSize: 1024, blocks: [..., ...] }字段含义algorithm哈希算法标识当前仅支持SHA256hash十六进制编码的完整内容哈希blockSize分块大小单位字节即每个块包含多少个字节blocks十六进制编码的逐块哈希数组数组中每个元素对应当前内容的一个blockSize大小的数据块。需要说明的是这个 JSON 示例是归档内“受保护数据段”的完整哈希 分块哈希结构。它的实际粒度由打包工具electron/asar决定——从本仓库的解析代码看archive 打开时会遍历 header 的 file table逐节点读取其integrity字段algorithm/hash/blockSize/blocks并挂到对应条目的元数据上见 shell/common/asar/archive.cc。因此blockSize/blocks的分块粒度通常是按归档内文件条目组织的大文件可被切成多个块分别做哈希从而支持“读到哪块验到哪块”的增量校验避免一次性读取并哈希整个文件。仓库集成测试里构造的测试归档即采用 4MB4 * 1024 * 1024的块大小并刻意在每块开头写入标记以便精准篡改某个块参见 spec/asar-integrity-spec.ts。打包期单独注入的“整个 ASAR 头”哈希与上面的归档内元数据不同你还必须在打包应用时另外定义一个对整个 ASAR header 的十六进制哈希header hash并把它写入应用的可执行文件macOS 为Info.plistWindows 为 exe 资源详见后文“提供 header hash”一节。这个“外部”哈希是整个校验链路的第一道闸门运行期打开可被校验的 asar 归档时Electron 先取出这个外部头哈希对归档实际读出的 header JSON 字节流计算 SHA256 并比对如果外部没有提供哈希、或者哈希不匹配应用会直接强制终止。对应的实现见 shell/common/asar/archive.cc在Archive::Init()中若归档需要校验load_integrity且外部提供了 integrity 配置会先取HeaderIntegrity()拿不到就LOG(FATAL) Failed to get integrity for validatable asar archive随后对 header 字节调用ValidateIntegrityOrDie验证通过才把header_validated_置真此后 header 内嵌的逐文件哈希才被信任用于内容读取校验。读取路径上的逐块校验头哈希校验通过后还有一层内容级校验所有通过归档读出的数据都会对照条目自身哈希做验证。核心兜底函数是 shell/common/asar/asar_util.cc 中的ValidateIntegrityOrDievoid ValidateIntegrityOrDie(base::spanconst uint8_t input, const IntegrityPayload integrity, std::string_view what) { if (integrity.algorithm HashAlgorithm::kSHA256) { const std::string hex_hash base::ToLowerASCII(base::HexEncode(crypto::hash::Sha256(input))); if (integrity.hash ! hex_hash) { LOG(FATAL) Integrity check failed for asar archive entry what ...; } } else { LOG(FATAL) Unsupported hashing algorithm in ValidateIntegrityOrDie; } }这里的设计要点比较是对整个条目内容哈希做全量比对失败即 FATAL。而对于流式读取如渲染进程经 network service 读取文件数据则通过 Mojo 的FilteredDataSource::Filter机制按块增量验证——对应的AsarFileValidator记录当前块与已累计哈希字节数在每次读块结束时核对当前块的哈希见 shell/browser/net/asar/asar_file_validator.h。archive.cc中FillFileInfoWithNode读取条目 integrity、并携带header_validated_标记就是为了保证“只有头哈希被验证过的归档其内嵌分块哈希才可用于内容校验”见 shell/common/asar/archive.cc。在可执行文件中开启相关 FuseASAR Integrity 校验默认关闭需要在打包构建期通过切换 Electron fuse 来开启。fuse 是写在 Electron 二进制中的“魔法位”打包期翻转、之后随应用一起代码签名被签名保护后便无法在分发后被改回系统层由 macOS Gatekeeper / Windows AppLocker 之类的签名校验机制兜底。关于 fuse 的整体机制与全部开关参见 fuses 文档。涉及本特性的两个 fuseEnableEmbeddedAsarIntegrityValidation默认关闭electron/fuses 选项FuseV1Options.EnableEmbeddedAsarIntegrityValidation作用在 macOS 与 Windows 上开启对app.asar内容加载时的完整性校验。性能影响官方描述该特性“设计上追求最小性能影响”但可能让从app.asar内部读取文件的速度略有下降因为读取多了一重哈希计算。OnlyLoadAppFromAsar强烈建议同时开启默认关闭electron/fuses 选项FuseV1Options.OnlyLoadAppFromAsar作用默认情况下 Electron 按app.asar→app→default_app.asar的顺序搜索应用代码开启该 fuse 后只允许从app.asar加载应用代码。官方教程明确警告开启完整性校验 fuse 时通常应同时开启onlyLoadAppFromAsar。否则完整性校验可以通过“Electron 应用代码搜索路径”即让它从未受校验的app目录加载代码被绕过。两者结合才能保证“不可能加载未经校验的代码”。开启示例使用electron/fusesconst { flipFuses, FuseVersion, FuseV1Options } require(electron/fuses) flipFuses( // E.g. /a/b/Foo.appmacOS 上指向 .app 包Windows 上指向 exe pathToPackagedApp, { version: FuseVersion.V1, [FuseV1Options.EnableEmbeddedAsarIntegrityValidation]: true, [FuseV1Options.OnlyLoadAppFromAsar]: true } )需要留意flipFuses会改写二进制因此翻转 fuse 之后、正式发布之前必须重新做代码签名否则 macOS 的 ad-hoc/正式签名失效仓库集成测试在翻转前显式设置resetAdHocDarwinSignature: true以重新生成 ad-hoc 签名见 spec/asar-integrity-spec.ts。最终由操作系统签名校验保证 fuse 位在分发后不可被反转。提示若使用 Electron Forge可通过electron-forge/plugin-fuses插件在 Forge 配置文件中完成 fuse 配置见 Forge fuses 插件说明。提供 header hash打包期注入完整性校验比对的对象是打包时你提供的那个归档头哈希。提供方式因平台而异且不同打包工具链的处理方式完全不同。使用 Electron 官方工具链推荐如果你使用Electron Forge 或 Electron Packager只要启用了asar它们会自动完成上述 macOS/Windows 的哈希注入无需额外配置。使用本特性所需的最低版本为electron/packager18.3.1electron/forge7.4.0使用其他构建系统macOSmacOS 打包时必须在产物应用的Info.plist中填充一个合法的ElectronAsarIntegrity字典块。示例keyElectronAsarIntegrity/key dict keyResources/app.asar/key dict keyalgorithm/key stringSHA256/string keyhash/key string9d1f61ea03c4bb62b4416387a521101b81151da0cfbe18c9f8c8b818c5cebfac/string /dict /dict说明合法的algorithm取值目前仅有SHA256外层 key如Resources/app.asar是归档相对Contents/的相对路径hash是用指定算法对该归档的 ASAR header计算得到的哈希生成方法electron/asar包暴露了getRawHeader方法对其返回结果的headerString做哈希即可。对应到 Electron 源码侧macOS 下Archive::HeaderIntegrity()从主 bundle 的Info.plist读取ElectronAsarIntegrity字典用归档相对Contents的路径RelativePath()查表并校验algorithm必须为SHA256后才返回哈希载荷见 shell/common/asar/archive_mac.mm。借助node:crypto计算头哈希的参考脚本与本仓库集成测试中的headerHash辅助函数一致见 spec/asar-integrity-spec.tsconst { createHash } require(node:crypto) const { getRawHeader } require(electron/asar) const hash createHash(sha256) .update(getRawHeader(/path/to/app.asar).headerString) .digest(hex) // 将 hash 写入 Info.plist 的 ElectronAsarIntegrity 字典使用其他构建系统WindowsWindows 打包时必须在可执行文件中填充一个合法的资源resource条目资源类型typeIntegrity资源名称nameElectronAsar资源值一个 JSON 编码的字典数组形式如下[ { file: resources\\app.asar, alg: sha256, value: 9d1f61ea03c4bb62b4416387a521101b81151da0cfbe18c9f8c8b818c5cebfac } ]其中file为归档相对资源目录assets 目录的路径alg为小写算法名value为十六进制哈希值。这一格式并非随意约定它必须与 Electron 侧解析逻辑严格一致。Windows 端实现见 shell/common/asar/archive_win.cc通过 Win32 APIFindResource/LoadResource从当前模块exe中查找类型为Integrity、名称为ElectronAsar的资源将资源内容作为 JSON 解析要求顶层必须是数组逐项校验字段file非空字符串、alg小写后必须等于sha256、value非空校验通过后以“小写化后的文件路径”为 key 建缓存表供Archive::HeaderIntegrity()查询。若归档路径在表中找不到对应项会直接LOG(FATAL)。macOS 与 Windows 两条读取路径虽然平台 API 不同但都归结为返回一个IntegrityPayloadalgorithm HashAlgorithm::kSHA256 十六进制hash供Archive::Init()做头哈希比对。官方文档给出的 Windows 实现参考是 Electron Packager 源码中的src/resedit.ts通过resedit等库改写 PE 资源。仓库集成测试中也用resedit的NtExecutableResource以相同形状向 exe 写入Integrity/ElectronAsar资源见 spec/asar-integrity-spec.ts。校验失败时的真实行为源码与测试佐证官方教程的核心行为承诺是若没有任何哈希、或哈希不匹配应用将被强制终止。仓库的集成测试 spec/asar-integrity-spec.ts 对这一行为做了非常系统的验证可归纳为以下几个层面1. fuse 开关本身决定是否生效EnableEmbeddedAsarIntegrityValidation开启时正常未篡改的归档可正常启动退出退出码 0篡改归档头后启动进程崩溃macOS 上表现为SIGABRT/SIGTRAPWindows 上为非零退出码输出中包含Integrity check failed for asar archive同一篡改在 fuse 关闭时完全不做任何校验应用照常运行退出码 0。这组对照实验直接证明了“fuse 是总开关”以及“运行期校验确实会以终止进程为代价”。2. 不同加载路径上的篡改检测测试分别篡改了不同语义的内容并断言应用终止篡改主进程加载的 JS进程以状态码 1 退出并打印ASAR Integrity Violation: got a hash mismatch篡改渲染进程读取的内容如require-trusted-types-for这类 renderer 资源进程崩溃输出包含Failed to validate block while ending ASAR file stream篡改fs.open一族的文件读取路径测试覆盖fd、stream、handle、copy四种模式全部无法读到原内容以状态码 1 退出并报 hash mismatch且输出中不会出现*-read-ok标记。3. 多块条目的增量校验语义对于包含多个 4MB 块的归档条目测试进一步验证了块级校验的精确语义篡改第 N 块后流式读取到达被篡改块之前的数据可以正常流出一旦流推进到被篡改的块便终止且被篡改块的任何一个字节都不会被交付当只有较靠后的块被篡改时只读取完好块的区间请求range read依然成功——说明校验是按被实际读取的块粒度发生的不影响与篡改块无关的读取整文件读取readFile遇到含篡改块的文件则必然失败甚至在“某块先被完整读取过、随后又被就地篡改、再次读取”的场景下依然能检测到哈希不匹配——说明读取不会无条件信任此前的结果。这些用例一方面印证了“读到哪块验到哪块”的增量设计配合 asar_file_validator.h 的块级 Mojo Filter另一方面也说明从主进程 fs API 到渲染进程网络读取的整条数据通路都被纳入了校验范围。使用前提与注意点小结在项目里落地 ASAR Integrity建议按如下顺序检查确认平台与版本macOS 需要 Electron ≥ 16Windows 需要 Electron ≥ 30若使用 MAS 构建并走非 App Store 分发务必开启。确认 asar 工具使用支持 integrity 的electron/asarasar3.1.0起其后所有版本均可。打包期开启 fuse翻转EnableEmbeddedAsarIntegrityValidation并同时翻转OnlyLoadAppFromAsar以防绕过翻转后重新签名。注入头哈希优先使用 Electron Packager≥ 18.3.1/ Electron Forge≥ 7.4.0自动完成自定义构建系统时macOS 写Info.plist的ElectronAsarIntegrity字典算法仅支持SHA256哈希用getRawHeader(...).headerString经node:crypto生成Windows 写入类型Integrity、名称ElectronAsar的 JSON 数组资源。理解性能与失败模型开启后从app.asar内部读文件可能略有变慢一旦头哈希缺失/不匹配或读取内容哈希不一致Electron 会以 Fatal 方式终止应用因此要保证打包流水线生成的哈希与最终归档严格对应任何“打包后改 asar”的流程都会导致应用无法启动。综上ASAR Integrity 提供了一条从“明文归档可被任意篡改”到“归档头 文件内容双层哈希、篡改即终止”的加固路径其全部机制都围绕 asar 归档格式、fuse 打包期开关 以及 archive 运行时校验 三块代码实现展开适合作为 Electron 应用发布安全加固的首选方案之一。【免费下载链接】electron:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS项目地址: https://gitcode.com/GitHub_Trending/el/electron创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考