ASAR文件
什么是ASAR文件
ASAR 文件是一种专有格式,常用于 Electron 应用程序中。ASAR 文件的全称是 "Atom Shell Archive",是一个档案文件格式,类似于 ZIP 或 TAR,用于将多个文件打包成一个文件。
使用electron-builder或者electron-forge打包的electron程序,一般在程序安装目录的resources文件夹下能找到ASAR文件。
特点和用途
- 文件打包:ASAR 文件可以将一个应用程序的多个文件打包成一个单一的文件,以简化分发和部署。
- 快速读取:虽然 ASAR 文件是一个档案文件,但它可以直接从档案中读取文件,而无需先解压缩。这提高了文件读取的速度。
- 应用安全性:通过将文件打包成 ASAR 格式,可以一定程度上防止用户轻易修改应用程序的源文件,提高了应用的安全性(注:asar文件并没有加密,只是在一定程度上增加了篡改源文件的复杂度)。
生成或提取ASAR文件
要生成或者提取ASAR文件,可以借助 @electron/asar 来实现;
使用方式:
Usage:
asar [options] [command]
Commands:
pack|p <dir> <output>
create asar archive
list|l <archive>
list files of asar archive
extract-file|ef <archive> <filename>
extract one file from archive
extract|e <archive> <dest>
extract archive
Options:
-h, --help output usage information
-V, --version output the version number
使用asar extract 命令可以提取ASAR文件; 使用asar pack 命令可以生成ASAR文件;
探索ASAR文件格式
前文提到,ASAR就是档案文件格式,是将多个文件打包放到一个文件里面的;因此可以很合理的猜测:ASAR文件一定有固定的文件结构,用于后续的文件提取。
ASAR整体结构
用记事本打开ASAR文件,可以看见:
- 文件头有几个乱码,暂时还不知什么意思;
- 之后的文本看起来像是JSON,记录了每个被打进ASAR的文件的文件名,大小和偏移量;
- 再之后就每个文件的内容。
JSON内容作用
将代表JSON内容的n内容复制出来格式化后,可以看到JSON的结构如下:
通过分析,总结这段JSON有以下两个作用:
- JSON特殊的树形结构记录了源文件的目录结构;
- ASAR对每个资源文件都是扁平化存储的,所以在JSON中记录了每个文件的大小和ASAR中的偏移量,用于后续文件读取;
文件头内容
现在我们只知道在ASAR中存储了一个用于描述源文件的JSON,但是想正确的解析出JSON内容,还必须知道它在ASAR中的偏移量和JSON stringify后的大小。
根据上文对整个ASAR结构的分析,这部分内容一定存储在文件头中。
在 @electron/asar 的源码中,是这么来处理文件头的:
module.exports.readArchiveHeaderSync = function (archive) {
const fd = fs.openSync(archive, 'r')
let size
let headerBuf
try {
const sizeBuf = Buffer.alloc(8)
if (fs.readSync(fd, sizeBuf, 0, 8, null) !== 8) {
throw new Error('Unable to read header size')
}
const sizePickle = pickle.createFromBuffer(sizeBuf)
size = sizePickle.createIterator().readUInt32()
headerBuf = Buffer.alloc(size)
if (fs.readSync(fd, headerBuf, 0, size, null) !== size) {
throw new Error('Unable to read header')
}
} finally {
fs.closeSync(fd)
}
const headerPickle = pickle.createFromBuffer(headerBuf)
const header = headerPickle.createIterator().readString()
return { headerString: header, header: JSON.parse(header), headerSize: size }
}
这段代码大概做了:
- 读取前8个字节,通过pickle计算出JSON stringify后的大小;
- 再根据JSON大小和偏移量读取JSON实际内容;
也就是说:ASAR的前8个字节以一种固定的形式记录JSON的大小; 至于pickle是什么,请移步这里:chromium-pickle-js
最后
至此,ASAR的文件格式已经很清楚了,如下图:
ASAR可分为三个部分:文件头,描述JSON,所以源文件内容;其中文件头固定8字节,以pickle形式记录了描述JSON的长度;描述JSON记录了每个源文件的大小和ASAR中的偏移量以及原始文件结构。
到这里,就很好解释为什么ASAR文件并不安全了,它的文件格式是固定的,按照指定格式就能读取源文件内容;
但是将源文件打包成ASAR有个好处就是:能有效解决windows下资源路径的长度限制问题,避免在资源路径过长导致的报错问题。
ASAR文件提取及生成,可以查看源码: @electron/asar