electron-incremental-update 1.2.0 → 2.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +131 -10
- package/dist/chunk-RSLOPAIZ.js +247 -0
- package/dist/decrypt-BNBcodiO.d.cts +4 -0
- package/dist/decrypt-BNBcodiO.d.ts +4 -0
- package/dist/index.cjs +131 -336
- package/dist/index.d.cts +96 -161
- package/dist/index.d.ts +96 -161
- package/dist/index.js +97 -269
- package/dist/provider.cjs +227 -0
- package/dist/provider.d.cts +37 -0
- package/dist/provider.d.ts +37 -0
- package/dist/provider.js +98 -0
- package/dist/types-DxPmQmaq.d.cts +61 -0
- package/dist/types-seJf3Wbc.d.ts +61 -0
- package/dist/utils.cjs +140 -117
- package/dist/utils.d.cts +31 -76
- package/dist/utils.d.ts +31 -76
- package/dist/utils.js +35 -11
- package/dist/{pure-GoN_3MEj.d.cts → version-CffZWDhZ.d.cts} +8 -7
- package/dist/{pure-GoN_3MEj.d.ts → version-CffZWDhZ.d.ts} +8 -7
- package/dist/vite.js +71 -119
- package/package.json +12 -6
- package/provider.d.ts +1 -0
- package/provider.js +1 -0
- package/dist/chunk-7ET4GMTZ.js +0 -236
- package/dist/chunk-CXHA5TF7.js +0 -236
- package/dist/chunk-HWUYTDEF.js +0 -236
- package/dist/chunk-RQCTJY4L.js +0 -236
- package/dist/vite.d.ts +0 -372
package/README.md
CHANGED
|
@@ -10,7 +10,9 @@ The new `${electron.app.name}.asar`, which can download from remote or load from
|
|
|
10
10
|
|
|
11
11
|
All **native modules** should be packaged into `app.asar` to reduce `${electron.app.name}.asar` file size, [see usage](#use-native-modules). Therefore, auto upgrade of portable app is possible.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Support bytecode protection, [see details](#bytecode-protection)
|
|
14
|
+
|
|
15
|
+
No `vite-plugin-electron-renderer` config
|
|
14
16
|
|
|
15
17
|
- inspired by [Obsidian](https://obsidian.md/)'s upgrade strategy
|
|
16
18
|
|
|
@@ -159,16 +161,27 @@ module.exports = {
|
|
|
159
161
|
|
|
160
162
|
### Use in main process
|
|
161
163
|
|
|
162
|
-
To use electron's `net` module for updating, the `checkUpdate` and `download` functions must be called after the app is ready by default.
|
|
163
|
-
|
|
164
|
-
However, you have the option to customize the download function when creating the updater.
|
|
164
|
+
To use electron's `net` module for updating, the `checkUpdate` and `download` functions must be called after the app is ready by default. You have the option to customize the download function when creating the updater.
|
|
165
165
|
|
|
166
166
|
**NOTE: There should only one function and should be default export in the entry file**
|
|
167
167
|
|
|
168
|
+
in `electron/entry.ts`
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
initApp({
|
|
172
|
+
updater: {
|
|
173
|
+
overrideFunctions: {
|
|
174
|
+
downloadJSON: (url: string, headers: Record<string, any>) => {}
|
|
175
|
+
// ...
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
})
|
|
179
|
+
```
|
|
180
|
+
|
|
168
181
|
in `electron/main/index.ts`
|
|
169
182
|
|
|
170
183
|
```ts
|
|
171
|
-
import { startupWithUpdater } from 'electron-incremental-update'
|
|
184
|
+
import { startupWithUpdater, UpdaterError } from 'electron-incremental-update'
|
|
172
185
|
import { getPathFromAppNameAsar, getVersions } from 'electron-incremental-update/utils'
|
|
173
186
|
import { app } from 'electron'
|
|
174
187
|
|
|
@@ -185,10 +198,12 @@ export default startupWithUpdater((updater) => {
|
|
|
185
198
|
console.log(percent)
|
|
186
199
|
}
|
|
187
200
|
updater.logger = console
|
|
201
|
+
updater.receiveBeta = true
|
|
202
|
+
|
|
188
203
|
updater.checkUpdate().then(async (result) => {
|
|
189
204
|
if (result === undefined) {
|
|
190
205
|
console.log('Update Unavailable')
|
|
191
|
-
} else if (result instanceof
|
|
206
|
+
} else if (result instanceof UpdaterError) {
|
|
192
207
|
console.error(result)
|
|
193
208
|
} else {
|
|
194
209
|
console.log('new version: ', result.version)
|
|
@@ -213,7 +228,16 @@ export default startupWithUpdater((updater) => {
|
|
|
213
228
|
|
|
214
229
|
All the **native modules** should be set as `dependency` in `package.json`. `electron-rebuild` only check dependencies inside `dependency` field.
|
|
215
230
|
|
|
216
|
-
If you are using `electron-builder` to build distributions, all the native modules with its **large relavent `node_modiles`** will be packaged into `app.asar` by default.
|
|
231
|
+
If you are using `electron-builder` to build distributions, all the native modules with its **large relavent `node_modiles`** will be packaged into `app.asar` by default.
|
|
232
|
+
|
|
233
|
+
Luckily, `Esbuild` can bundle all the dependencies. Just follow the steps:
|
|
234
|
+
|
|
235
|
+
1. setup `nativeModuleEntryMap` option
|
|
236
|
+
2. Manually copy the native binaries in `postBuild` callback
|
|
237
|
+
3. Exclude all the dependencies in `electron-builder`'s config
|
|
238
|
+
4. call the native functions with `loadNativeModuleFromEntry` in your code
|
|
239
|
+
|
|
240
|
+
#### Example
|
|
217
241
|
|
|
218
242
|
in `vite.config.ts`
|
|
219
243
|
|
|
@@ -224,6 +248,7 @@ const plugin = electronWithUpdater({
|
|
|
224
248
|
entry: {
|
|
225
249
|
nativeModuleEntryMap: {
|
|
226
250
|
db: './electron/native/db.ts',
|
|
251
|
+
img: './electron/native/img.ts',
|
|
227
252
|
},
|
|
228
253
|
postBuild: async ({ copyToEntryOutputDir }) => {
|
|
229
254
|
// for better-sqlite3
|
|
@@ -248,9 +273,8 @@ in `electron/native/db.ts`
|
|
|
248
273
|
|
|
249
274
|
```ts
|
|
250
275
|
import Database from 'better-sqlite3'
|
|
251
|
-
import { getPaths } from 'electron-incremental-update/utils'
|
|
252
276
|
|
|
253
|
-
const db = new Database(':memory:', { nativeBinding:
|
|
277
|
+
const db = new Database(':memory:', { nativeBinding: './better_sqlite3.node' })
|
|
254
278
|
|
|
255
279
|
export function test() {
|
|
256
280
|
db.exec(
|
|
@@ -295,7 +319,11 @@ module.exports = {
|
|
|
295
319
|
|
|
296
320
|
### Bytecode protection
|
|
297
321
|
|
|
298
|
-
|
|
322
|
+
From v1.2, the vite plugin is able to generate bytecode to protect your application.
|
|
323
|
+
|
|
324
|
+
It will automatically protect your `SIGNATURE_CERT` by default.
|
|
325
|
+
|
|
326
|
+
credit to [electron-vite](https://github.com/alex8088/electron-vite/blob/master/src/plugins/bytecode.ts), and improve the string protection (see [original issue](https://github.com/alex8088/electron-vite/issues/552))
|
|
299
327
|
|
|
300
328
|
```ts
|
|
301
329
|
electronWithUpdater({
|
|
@@ -311,6 +339,99 @@ electronWithUpdater({
|
|
|
311
339
|
|
|
312
340
|
### Types
|
|
313
341
|
|
|
342
|
+
#### Updater
|
|
343
|
+
|
|
344
|
+
```ts
|
|
345
|
+
export interface UpdaterOption {
|
|
346
|
+
/**
|
|
347
|
+
* public key of signature, which will be auto generated by plugin,
|
|
348
|
+
* generate by `selfsigned` if not set
|
|
349
|
+
*/
|
|
350
|
+
SIGNATURE_CERT?: string
|
|
351
|
+
/**
|
|
352
|
+
* repository url, e.g. `https://github.com/electron/electron`
|
|
353
|
+
*
|
|
354
|
+
* you can use the `repository` in `package.json`
|
|
355
|
+
*
|
|
356
|
+
* if `updateJsonURL` or `releaseAsarURL` are absent,
|
|
357
|
+
* `repository` will be used to determine the url
|
|
358
|
+
*/
|
|
359
|
+
repository?: string
|
|
360
|
+
/**
|
|
361
|
+
* URL of version info json
|
|
362
|
+
* @default `${repository.replace('github.com', 'raw.githubusercontent.com')}/master/version.json`
|
|
363
|
+
* @throws if `updateJsonURL` and `repository` are all not set
|
|
364
|
+
*/
|
|
365
|
+
updateJsonURL?: string
|
|
366
|
+
/**
|
|
367
|
+
* URL of release asar.gz
|
|
368
|
+
* @default `${repository}/releases/download/v${version}/${app.name}-${version}.asar.gz`
|
|
369
|
+
* @throws if `releaseAsarURL` and `repository` are all not set
|
|
370
|
+
*/
|
|
371
|
+
releaseAsarURL?: string
|
|
372
|
+
/**
|
|
373
|
+
* whether to receive beta update
|
|
374
|
+
*/
|
|
375
|
+
receiveBeta?: boolean
|
|
376
|
+
overrideFunctions?: UpdaterOverrideFunctions
|
|
377
|
+
downloadConfig?: UpdaterDownloadConfig
|
|
378
|
+
}
|
|
379
|
+
export type Logger = {
|
|
380
|
+
info: (msg: string) => void
|
|
381
|
+
debug: (msg: string) => void
|
|
382
|
+
warn: (msg: string) => void
|
|
383
|
+
error: (msg: string, e?: Error) => void
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
export type UpdaterOverrideFunctions = {
|
|
387
|
+
/**
|
|
388
|
+
* custom version compare function
|
|
389
|
+
* @param version1 old version string
|
|
390
|
+
* @param version2 new version string
|
|
391
|
+
* @returns if version1 < version2
|
|
392
|
+
*/
|
|
393
|
+
isLowerVersion?: (version1: string, version2: string) => boolean | Promise<boolean>
|
|
394
|
+
/**
|
|
395
|
+
* custom verify signature function
|
|
396
|
+
* @param buffer file buffer
|
|
397
|
+
* @param signature signature
|
|
398
|
+
* @param cert certificate
|
|
399
|
+
* @returns if signature is valid, returns the version or `true` , otherwise returns `false`
|
|
400
|
+
*/
|
|
401
|
+
verifySignaure?: (buffer: Buffer, signature: string, cert: string) => string | false | Promise<string | false>
|
|
402
|
+
/**
|
|
403
|
+
* custom download JSON function
|
|
404
|
+
* @param url download url
|
|
405
|
+
* @param header download header
|
|
406
|
+
* @returns `UpdateJSON`
|
|
407
|
+
*/
|
|
408
|
+
downloadJSON?: (url: string, headers: Record<string, any>) => Promise<UpdateJSON>
|
|
409
|
+
/**
|
|
410
|
+
* custom download buffer function
|
|
411
|
+
* @param url download url
|
|
412
|
+
* @param headers download header
|
|
413
|
+
* @param total precaculated file total size
|
|
414
|
+
* @param onDownloading on downloading callback
|
|
415
|
+
* @returns `Buffer`
|
|
416
|
+
*/
|
|
417
|
+
downloadBuffer?: (url: string, headers: Record<string, any>, total: number, onDownloading?: (progress: DownloadingInfo) => void) => Promise<Buffer>
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
export type UpdaterDownloadConfig = {
|
|
421
|
+
/**
|
|
422
|
+
* download user agent
|
|
423
|
+
* @default 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36'
|
|
424
|
+
*/
|
|
425
|
+
userAgent?: string
|
|
426
|
+
/**
|
|
427
|
+
* extra download header, `accept` and `user-agent` is set by default
|
|
428
|
+
*/
|
|
429
|
+
extraHeader?: Record<string, string>
|
|
430
|
+
}
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
#### Plugin
|
|
434
|
+
|
|
314
435
|
```ts
|
|
315
436
|
type ElectronWithUpdaterOptions = {
|
|
316
437
|
/**
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
// src/utils/electron.ts
|
|
9
|
+
import { existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
10
|
+
import { dirname, join } from "node:path";
|
|
11
|
+
import { app } from "electron";
|
|
12
|
+
var isDev = __EIU_IS_DEV__;
|
|
13
|
+
var isWin = process.platform === "win32";
|
|
14
|
+
var isMac = process.platform === "darwin";
|
|
15
|
+
var isLinux = process.platform === "linux";
|
|
16
|
+
function getPathFromAppNameAsar(...path) {
|
|
17
|
+
return isDev ? "DEV.asar" : join(dirname(app.getAppPath()), `${app.name}.asar`, ...path);
|
|
18
|
+
}
|
|
19
|
+
function getAppVersion() {
|
|
20
|
+
return isDev ? getEntryVersion() : readFileSync(getPathFromAppNameAsar("version"), "utf-8");
|
|
21
|
+
}
|
|
22
|
+
function getEntryVersion() {
|
|
23
|
+
return app.getVersion();
|
|
24
|
+
}
|
|
25
|
+
function requireNative(moduleName) {
|
|
26
|
+
return __require(join(app.getAppPath(), __EIU_ENTRY_DIST_PATH__, moduleName));
|
|
27
|
+
}
|
|
28
|
+
function restartApp() {
|
|
29
|
+
app.relaunch();
|
|
30
|
+
app.quit();
|
|
31
|
+
}
|
|
32
|
+
function setAppUserModelId(id) {
|
|
33
|
+
isWin && app.setAppUserModelId(id ?? `org.${app.name}`);
|
|
34
|
+
}
|
|
35
|
+
function disableHWAccForWin7() {
|
|
36
|
+
if (__require("node:os").release().startsWith("6.1")) {
|
|
37
|
+
app.disableHardwareAcceleration();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function singleInstance(window) {
|
|
41
|
+
const result = app.requestSingleInstanceLock();
|
|
42
|
+
result ? app.on("second-instance", () => {
|
|
43
|
+
if (window) {
|
|
44
|
+
window.show();
|
|
45
|
+
if (window.isMinimized()) {
|
|
46
|
+
window.restore();
|
|
47
|
+
}
|
|
48
|
+
window.focus();
|
|
49
|
+
}
|
|
50
|
+
}) : app.quit();
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
function setPortableAppDataPath(dirName = "data") {
|
|
54
|
+
const portablePath = join(dirname(app.getPath("exe")), dirName);
|
|
55
|
+
if (!existsSync(portablePath)) {
|
|
56
|
+
mkdirSync(portablePath);
|
|
57
|
+
}
|
|
58
|
+
app.setPath("appData", portablePath);
|
|
59
|
+
}
|
|
60
|
+
function waitAppReady(timeout = 1e3) {
|
|
61
|
+
return app.isReady() ? Promise.resolve() : new Promise((resolve, reject) => {
|
|
62
|
+
const _ = setTimeout(() => {
|
|
63
|
+
reject(new Error("app is not ready"));
|
|
64
|
+
}, timeout);
|
|
65
|
+
app.whenReady().then(() => {
|
|
66
|
+
clearTimeout(_);
|
|
67
|
+
resolve();
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
function loadPage(win, htmlFilePath = "index.html") {
|
|
72
|
+
isDev ? win.loadURL(process.env.VITE_DEV_SERVER_URL + htmlFilePath) : win.loadFile(getPathFromAppNameAsar("renderer", htmlFilePath));
|
|
73
|
+
}
|
|
74
|
+
function getPathFromPreload(...paths) {
|
|
75
|
+
return isDev ? join(app.getAppPath(), __EIU_ELECTRON_DIST_PATH__, "preload", ...paths) : getPathFromAppNameAsar("preload", ...paths);
|
|
76
|
+
}
|
|
77
|
+
function getPathFromPublic(...paths) {
|
|
78
|
+
return isDev ? join(app.getAppPath(), "public", ...paths) : getPathFromAppNameAsar("renderer", ...paths);
|
|
79
|
+
}
|
|
80
|
+
function getPathFromEntryAsar(...paths) {
|
|
81
|
+
return join(app.getAppPath(), __EIU_ENTRY_DIST_PATH__, ...paths);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// src/utils/zip.ts
|
|
85
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync } from "node:fs";
|
|
86
|
+
import { brotliCompress } from "node:zlib";
|
|
87
|
+
async function zipFile(filePath, targetFilePath = `${filePath}.gz`) {
|
|
88
|
+
if (!existsSync2(filePath)) {
|
|
89
|
+
throw new Error(`path to be zipped not exist: ${filePath}`);
|
|
90
|
+
}
|
|
91
|
+
const buffer = readFileSync2(filePath);
|
|
92
|
+
return new Promise((resolve, reject) => {
|
|
93
|
+
brotliCompress(buffer, (err, buffer2) => {
|
|
94
|
+
if (err) {
|
|
95
|
+
reject(err);
|
|
96
|
+
}
|
|
97
|
+
writeFileSync(targetFilePath, buffer2);
|
|
98
|
+
resolve(null);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// src/utils/unzip.ts
|
|
104
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
105
|
+
import { brotliDecompress } from "node:zlib";
|
|
106
|
+
async function unzipFile(gzipPath, targetFilePath = gzipPath.slice(0, -3)) {
|
|
107
|
+
if (!existsSync3(gzipPath)) {
|
|
108
|
+
throw new Error(`path to zipped file not exist: ${gzipPath}`);
|
|
109
|
+
}
|
|
110
|
+
const compressedBuffer = readFileSync3(gzipPath);
|
|
111
|
+
return new Promise((resolve, reject) => {
|
|
112
|
+
brotliDecompress(compressedBuffer, (err, buffer) => {
|
|
113
|
+
rmSync(gzipPath);
|
|
114
|
+
if (err) {
|
|
115
|
+
reject(err);
|
|
116
|
+
}
|
|
117
|
+
writeFileSync2(targetFilePath, buffer);
|
|
118
|
+
resolve(null);
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// src/utils/version.ts
|
|
124
|
+
function handleUnexpectedErrors(callback) {
|
|
125
|
+
process.on("uncaughtException", callback);
|
|
126
|
+
process.on("unhandledRejection", callback);
|
|
127
|
+
}
|
|
128
|
+
function parseVersion(version) {
|
|
129
|
+
const match = /^(\d+)\.(\d+)\.(\d+)(?:-([a-z0-9.-]+))?/i.exec(version);
|
|
130
|
+
if (!match) {
|
|
131
|
+
throw new TypeError(`invalid version: ${version}`);
|
|
132
|
+
}
|
|
133
|
+
const [major, minor, patch] = match.slice(1, 4).map(Number);
|
|
134
|
+
const ret = {
|
|
135
|
+
major,
|
|
136
|
+
minor,
|
|
137
|
+
patch,
|
|
138
|
+
stage: "",
|
|
139
|
+
stageVersion: -1
|
|
140
|
+
};
|
|
141
|
+
if (match[4]) {
|
|
142
|
+
let [stage, _v] = match[4].split(".");
|
|
143
|
+
ret.stage = stage;
|
|
144
|
+
ret.stageVersion = Number(_v) || -1;
|
|
145
|
+
}
|
|
146
|
+
if (Number.isNaN(major) || Number.isNaN(minor) || Number.isNaN(patch) || Number.isNaN(ret.stageVersion)) {
|
|
147
|
+
throw new TypeError(`invalid version: ${version}`);
|
|
148
|
+
}
|
|
149
|
+
return ret;
|
|
150
|
+
}
|
|
151
|
+
function isLowerVersionDefault(oldVer, newVer) {
|
|
152
|
+
const oldV = parseVersion(oldVer);
|
|
153
|
+
const newV = parseVersion(newVer);
|
|
154
|
+
function compareStrings(str1, str2) {
|
|
155
|
+
if (str1 === "") {
|
|
156
|
+
return str2 !== "";
|
|
157
|
+
} else if (str2 === "") {
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
return str1 < str2;
|
|
161
|
+
}
|
|
162
|
+
for (let key of Object.keys(oldV)) {
|
|
163
|
+
if (key === "stage" && compareStrings(oldV[key], newV[key])) {
|
|
164
|
+
return true;
|
|
165
|
+
} else if (oldV[key] !== newV[key]) {
|
|
166
|
+
return oldV[key] < newV[key];
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
function isUpdateJSON(json) {
|
|
172
|
+
const is = (j) => !!(j && j.minimumVersion && j.signature && j.size && j.version);
|
|
173
|
+
return is(json) && is(json?.beta);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// src/utils/crypto/decrypt.ts
|
|
177
|
+
import { createDecipheriv, createVerify } from "node:crypto";
|
|
178
|
+
|
|
179
|
+
// src/utils/crypto/utils.ts
|
|
180
|
+
import { createHash } from "node:crypto";
|
|
181
|
+
function hashString(data, length) {
|
|
182
|
+
const hash = createHash("SHA256").update(data).digest("binary");
|
|
183
|
+
return Buffer.from(hash).subarray(0, length);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// src/utils/crypto/decrypt.ts
|
|
187
|
+
function decrypt(encryptedText, key, iv) {
|
|
188
|
+
const decipher = createDecipheriv("aes-256-cbc", key, iv);
|
|
189
|
+
let decrypted = decipher.update(encryptedText, "base64url", "utf8");
|
|
190
|
+
decrypted += decipher.final("utf8");
|
|
191
|
+
return decrypted;
|
|
192
|
+
}
|
|
193
|
+
function verifySignatureDefault(buffer, signature2, cert) {
|
|
194
|
+
try {
|
|
195
|
+
const [sig, version] = decrypt(signature2, hashString(cert, 32), hashString(buffer, 16)).split("%");
|
|
196
|
+
const result = createVerify("RSA-SHA256").update(buffer).verify(cert, sig, "base64");
|
|
197
|
+
return result ? version : void 0;
|
|
198
|
+
} catch (error) {
|
|
199
|
+
return void 0;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// src/utils/crypto/encrypt.ts
|
|
204
|
+
import { createCipheriv, createPrivateKey, createSign } from "node:crypto";
|
|
205
|
+
function encrypt(plainText, key, iv) {
|
|
206
|
+
const cipher = createCipheriv("aes-256-cbc", key, iv);
|
|
207
|
+
let encrypted = cipher.update(plainText, "utf8", "base64url");
|
|
208
|
+
encrypted += cipher.final("base64url");
|
|
209
|
+
return encrypted;
|
|
210
|
+
}
|
|
211
|
+
function signature(buffer, privateKey, cert, version) {
|
|
212
|
+
const sig = createSign("RSA-SHA256").update(buffer).sign(createPrivateKey(privateKey), "base64");
|
|
213
|
+
return encrypt(`${sig}%${version}`, hashString(cert, 32), hashString(buffer, 16));
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export {
|
|
217
|
+
__require,
|
|
218
|
+
handleUnexpectedErrors,
|
|
219
|
+
parseVersion,
|
|
220
|
+
isLowerVersionDefault,
|
|
221
|
+
isUpdateJSON,
|
|
222
|
+
isDev,
|
|
223
|
+
isWin,
|
|
224
|
+
isMac,
|
|
225
|
+
isLinux,
|
|
226
|
+
getPathFromAppNameAsar,
|
|
227
|
+
getAppVersion,
|
|
228
|
+
getEntryVersion,
|
|
229
|
+
requireNative,
|
|
230
|
+
restartApp,
|
|
231
|
+
setAppUserModelId,
|
|
232
|
+
disableHWAccForWin7,
|
|
233
|
+
singleInstance,
|
|
234
|
+
setPortableAppDataPath,
|
|
235
|
+
waitAppReady,
|
|
236
|
+
loadPage,
|
|
237
|
+
getPathFromPreload,
|
|
238
|
+
getPathFromPublic,
|
|
239
|
+
getPathFromEntryAsar,
|
|
240
|
+
unzipFile,
|
|
241
|
+
zipFile,
|
|
242
|
+
hashString,
|
|
243
|
+
decrypt,
|
|
244
|
+
verifySignatureDefault,
|
|
245
|
+
encrypt,
|
|
246
|
+
signature
|
|
247
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
declare function decrypt(encryptedText: string, key: Buffer, iv: Buffer): string;
|
|
2
|
+
declare function verifySignatureDefault(buffer: Buffer, signature: string, cert: string): string | undefined | Promise<string | undefined>;
|
|
3
|
+
|
|
4
|
+
export { decrypt as d, verifySignatureDefault as v };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
declare function decrypt(encryptedText: string, key: Buffer, iv: Buffer): string;
|
|
2
|
+
declare function verifySignatureDefault(buffer: Buffer, signature: string, cert: string): string | undefined | Promise<string | undefined>;
|
|
3
|
+
|
|
4
|
+
export { decrypt as d, verifySignatureDefault as v };
|