Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release v3 #72

Merged
merged 28 commits into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
0e7b549
Update package description
sleeyax Apr 18, 2024
fe595bd
Remove trashify patch
sleeyax Apr 18, 2024
cddbf4c
Adjust bloat patch to only write zero bytes
sleeyax Apr 18, 2024
d8f8bd3
Remove unused helpers
sleeyax Apr 18, 2024
87f33b1
Update commander
sleeyax Apr 18, 2024
6b37208
Remove deprecation warning
sleeyax Apr 18, 2024
b173d33
Update dependencies
sleeyax Apr 18, 2024
9e68ee7
Migrate from babel-jest to ts-jest
sleeyax Apr 18, 2024
fa25968
Bump lint-staged dependency
sleeyax Apr 18, 2024
ac2c9fb
Replace deprecated `asar` dependency with `@electron/asar`
sleeyax Apr 18, 2024
d15d769
Add script tto compile and run CLI
sleeyax Apr 18, 2024
ab90ed7
Update node-gyp, node-addon-api dependencies
sleeyax Apr 18, 2024
6e4897e
Update README.md
sleeyax Apr 18, 2024
c0890a8
Encrypt existing asar file (closes #42)
sleeyax Apr 19, 2024
3924c13
Update node example
sleeyax Apr 19, 2024
637ca7d
Fix node example test
sleeyax Apr 19, 2024
a79e08c
Name Node.js example
sleeyax Apr 19, 2024
414e020
Update electron example
sleeyax Apr 19, 2024
2c26000
Update README.md
sleeyax Apr 19, 2024
1ba3d45
Handle encryption keys only internally (closes #61)
sleeyax Apr 19, 2024
82300dc
Remove unused LOC
sleeyax Apr 19, 2024
6aac8ed
Fix missing await
sleeyax Apr 19, 2024
1c1dc49
Try to fix node example test
sleeyax Apr 19, 2024
a480308
Install dependencies with scripts enabled
sleeyax Apr 19, 2024
14b98e6
Update CLI examples
sleeyax Apr 19, 2024
78c5584
Support resolution of unencrypted code from plaintext asar file (clos…
sleeyax Apr 19, 2024
111e92f
Update package description
sleeyax Apr 19, 2024
d089424
3.0.0
sleeyax Apr 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,20 @@ jobs:
fail-fast: false
matrix:
node-version:
- 16
- 18
- 20
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- run: npm install --ignore-scripts
# test project
- run: npm install
- run: npm run prepare
- run: npm test
- run: npm test
# test node example
- working-directory: example/node
name: Test Node.js example
run: |
npm install
npm run build
npm test
3 changes: 0 additions & 3 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx lint-staged
6 changes: 6 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"typescript.tsdk": "node_modules/typescript/lib",
"cSpell.words": [
"asar"
]
}
154 changes: 56 additions & 98 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,68 +1,60 @@
# asarmor
CLI tool and library that can patch and encrypt your asar file to protect it from extraction (e.g by executing `asar extract`).
This is not bulletproof, but can be useful as a first level of protection.
Protects asar files from extraction (with `asar extract`).
The methods provided by asarmor are not bulletproof, but can be useful as a first level of protection.

## installation
Install as local library: `$ npm install --save-dev asarmor`
## Usage
You can use asarmor as a CLI tool or as a library in your project. The CLI tool is useful for quick and easy protection of your asar files or for trying out asarmor. The library is useful for more advanced use cases, such as integrating asarmor into your Electron project.

Install as global CLI app: `$ npm install -g asarmor`
### CLI

## usage
Installation:

### CLI
```
$ asarmor --help
`npm install --save-dev asarmor`

Usage:

```
Usage: asarmor [options]

Options:
-V, --version output the version number
-a, --archive <archive> input asar file (required)
-o, --output <output> output asar file (required)
-b, --backup create backup
-r, --restore restore backup
-bl, --bloat [gigabytes] add huge random files to disk on extraction attempt
-t, --trashify [junkfiles...] add fake files to the archive
-e, --encrypt <src> encrypt file contents
-ek, --key <file path> key file to use for encryption
-h, --help display help for command
-V, --version output the version number
-a, --archive <archive> input asar file (required)
-o, --output <output> output asar file (required)
-b, --backup create backup
-r, --restore restore backup
-bl, --bloat [gigabytes] fill the drive with useless data on extraction attempt
-e, --encryption encrypt the JavaScript files stored in the archive
-h, --help display help for command

Examples:
$ asarmor -a app.asar -o asarmor.asar --bloat 1000
$ asarmor -a app.asar -o asarmor.asar --trashify bee-movie.txt foo.js bar.ts
$ asarmor -a app.asar -o asarmor.asar --trashify --backup
$ asarmor -a app.asar --restore
$ asarmor -a app.asar -o asarmor.asar --backup --bloat 1000
$ asarmor -a plaintext.asar -o encrypted.asar --encryption
```

### library
### Library

Installation:

`npm install -g asarmor`

Usage:

```javascript
const asarmor = require('asarmor');
const { encrypt } = require('asarmor/encryption');

(async () => {
// Encrypt the contents of the asar archive.
await encrypt({
src: './dist', // source or transpiled code to encrypt
dst: './app.asar', // target asar file
// Encrypt the JavaScript file contents stored withing the asar file.
await asarmor.encrypt({
src: './app.asar', // target asar file to encrypt
dst: './encrypted.asar', // output asar file
});

// Read & parse the (optionally encrypted) asar file.
// This can take a while depending on the size of your file.
const archive = await asarmor.open('app.asar');
const archive = await asarmor.open('encrypted.asar');

// Create a backup, which can be restored at any point in time through CLI or code.
await archive.createBackup({backupPath: '~/Documents/backups/app.asar.backup'});

// Apply customized trash patch.
// The trash patch by itself will make sure `asar extract` fails.
archive.patch(asarmor.createTrashPatch({
filenames: ['foo', 'bar'],
beforeWrite: (filename) => {
const extensions = ['js', 'ts', 'tsx', 'txt'];
const extension = extensions[Math.floor(Math.random() * extensions.length)];
return filename + '.' + extension;
}
}));
await archive.createBackup({backupPath: '~/Documents/backups/encrypted.asar.backup'});

// Apply customized bloat patch.
// The bloat patch by itself will write randomness to disk on extraction attempt.
Expand All @@ -74,30 +66,7 @@ const { encrypt } = require('asarmor/encryption');
})();
```

#### advanced
```javascript
const asarmor = require('asarmor');

(async () => {
const archive = await asarmor.open('app.asar');

// Apply a fully customized patch.
// Play around with the different values to see what works best for you.
archive.patch({
header: {
files: {
'foo.js': {offset: 0, size: -999},
'bar.js': {offset: -123, size: 1337},
}
},
});

// Write result back to file.
await archive.write('protected.asar');
})();
```

### electron-builder
## `electron-builder`
You can easily include asarmor in your packaging process using an [afterPack](https://www.electron.build/configuration/configuration.html#afterpack) hook:
```javascript
const asarmor = require('asarmor');
Expand All @@ -116,35 +85,25 @@ exports.default = async ({ appOutDir, packager }) => {
};
```

<details>
<summary>Encryption support (click to expand)</summary>

Asarmor now finally supports file content encryption. No Electron recompilation required! Huge thanks to toyobayashi's wonderful [electron-asar-encrypt-demo](https://github.com/toyobayashi/electron-asar-encrypt-demo) for making this possible. I won't be going into too many details on how this works exactly. If you're interested in the details I higly recommend you to check out the `electron-asar-encrypt-demo` repository.
### Encryption
Asarmor can encrypt the contents of your asar file. No Electron recompilation required! Huge thanks to [toyobayashi's](https://github.com/toyobayashi) wonderful [electron-asar-encrypt-demo](https://github.com/toyobayashi/electron-asar-encrypt-demo) for making this possible. I won't be going into too many details on how this works exactly. If you're interested in the details I highly recommend you check out the [electron-asar-encrypt-demo](https://github.com/toyobayashi/electron-asar-encrypt-demo) repository.

There's a few more steps involved to make this work, though. See [example/electron](https://github.com/sleeyax/asarmor/tree/master/example/electron) if you'd like to skip ahead to the code.
There's a few more steps involved to make this work. See [example/electron](https://github.com/sleeyax/asarmor/tree/master/example/electron) if you'd like to skip ahead to the code.

Steps:

1. Update [afterPack.js](https://github.com/sleeyax/asarmor/blob/master/example/electron/afterPack.js):
```diff
exports.default = async ({ appOutDir, packager }) => {
try {
+ const asarPath = join(packager.getResourcesDir(appOutDir), 'app.asar');
+
+ // encrypt file contents first
+ const src = join(packager.info.projectDir, 'release', 'app');
+ const dst = asarPath;
+ console.log(`asarmor encrypting contents of ${src} to ${dst}`);
+ const asarPath = join(packager.getResourcesDir(appOutDir), 'app.asar');
+ console.log(`asarmor is encrypting all JavaScript files stored in ${asarPath}`);
+ await encrypt({
+ // path to your source code (e.g. src, build or dist)
+ src,
+ // destination asar file to write to
+ dst,
+ // path to the encryption key file; asarmor should generate a new one every time it's installed as a dev-dependency.
+ keyFilePath: join(__dirname, '..', 'node_modules', 'asarmor', 'src', 'encryption', 'key.txt'),
+ // path to the input asar file
+ src: asarPath,
+ // path to the output asar file
+ dst: asarPath,
+ });
+
+ // then patch the header
- const asarPath = join(packager.getResourcesDir(appOutDir), 'app.asar');
console.log(`asarmor applying patches to ${asarPath}`);
const archive = await asarmor.open(asarPath);
Expand Down Expand Up @@ -210,13 +169,12 @@ Don't forget to update `package.json` as well:
- "main": "./dist/main/main.js",
```

4. Load any hooks at the start of the [main process](https://github.com/sleeyax/asarmor/blob/master/example/electron/src/main/main.ts) file (optional):
4. **Optional**: load configuration hooks at the start of the [main process](https://github.com/sleeyax/asarmor/blob/master/example/electron/src/main/main.ts) file:
```ts
// main.ts
import { hookNodeModulesAsar } from 'asarmor/src/encryption/hooks';
import { allowUnencrypted } from 'asarmor';

// load hooks at the start of the file
hookNodeModulesAsar(); // enables resolution of non-encrypted dependencies from node_modules.asar
allowUnencrypted(['node_modules']); // enables resolution of non-encrypted dependencies from `node_modules.asar`
```

5. Update your `BrowserWindow.webPreferences` configuration settings:
Expand All @@ -238,7 +196,7 @@ await mainWindow.webContents.executeJavaScript(`!function () {
}()`);
```

7. Export a default function in the main process, accepting the decryption key as a paramater.
7. Export a default function in the main process, accepting the decryption key as a parameter.
```ts
module.exports = function bootstrap(k: Uint8Array) {
// sanity check
Expand All @@ -265,29 +223,29 @@ module.exports = function bootstrap(k: Uint8Array) {
}
};
```
</details>

### examples
## Examples
See [examples](example) for detailed code examples.

## FAQ
**Do protections affect my (electron) app performance?**

It depends. If you have a huge archive and applied encryption, then yes. Otherwise, electron should still be able read your asar file at the same speed as if nothing changed.
The same should be true for other frameworks that utilise the asar format (unless the implementation differs drastically for some reason, which is out of my control).
The same should be true for other frameworks that utilize the asar format (unless the implementation differs drastically for some reason, which is out of my control).

## sponsors
## Sponsors

---

> Maintenance of this project is made possible by all the lovely contributors and sponsors.
If you'd like to sponsor this project and have your avatar or company logo appear in this section, click [here](https://github.com/sponsors/sleeyax). 💖

## support
## Support
Found a bug or have a question? [Open an issue](https://github.com/sleeyax/asarmor/issues) if it doesn't exist yet. Pull Requests are welcome, but please open an issue first if you're adding major changes!

## related projects
* [asar](https://www.npmjs.com/package/asar)
## Credits
A special thanks to the following projects for making this project possible:
* [asar](https://github.com/electron/asar)
* [asarbreak](https://www.npmjs.com/package/asarbreak)
* [patch-asar](https://www.npmjs.com/package/patch-asar)
* [patch-asar](https://github.com/L1lith/patch-asar)
* [electron-asar-encrypt-demo](https://github.com/toyobayashi/electron-asar-encrypt-demo)
6 changes: 0 additions & 6 deletions babel.config.js

This file was deleted.

Loading
Loading