@lvce-editor/main-process 6.19.1 → 6.19.2
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/dist/mainProcessMain.js +98 -9
- package/package.json +2 -1
package/dist/mainProcessMain.js
CHANGED
|
@@ -11,6 +11,7 @@ import { dirname, join as join$1, isAbsolute } from 'node:path';
|
|
|
11
11
|
import { homedir, tmpdir } from 'node:os';
|
|
12
12
|
import { pbkdf2Sync, createDecipheriv, createHash } from 'node:crypto';
|
|
13
13
|
import { DatabaseSync } from 'node:sqlite';
|
|
14
|
+
import dbus, { Variant } from 'dbus-native';
|
|
14
15
|
import { MessageChannel } from 'node:worker_threads';
|
|
15
16
|
|
|
16
17
|
const scheme = 'lvce-oss';
|
|
@@ -4613,6 +4614,7 @@ const beep$1 = () => {
|
|
|
4613
4614
|
};
|
|
4614
4615
|
|
|
4615
4616
|
const chromeV10Prefix = Buffer.from('v10');
|
|
4617
|
+
const chromeV11Prefix = Buffer.from('v11');
|
|
4616
4618
|
const chromeV10Key = pbkdf2Sync('peanuts', 'saltysalt', 1, 16, 'sha1');
|
|
4617
4619
|
const chromeV10Iv = Buffer.alloc(16, 0x20);
|
|
4618
4620
|
const domainHashLength = 32;
|
|
@@ -4622,13 +4624,25 @@ class UnsupportedChromeCookieEncryptionError extends Error {
|
|
|
4622
4624
|
this.name = 'UnsupportedChromeCookieEncryptionError';
|
|
4623
4625
|
}
|
|
4624
4626
|
}
|
|
4625
|
-
const
|
|
4627
|
+
const isV11 = encryptedValue => {
|
|
4628
|
+
return Buffer.from(encryptedValue).subarray(0, chromeV11Prefix.length).equals(chromeV11Prefix);
|
|
4629
|
+
};
|
|
4630
|
+
const decrypt$1 = (hostKey, encryptedValue, databaseVersion, chromeSafeStoragePassword) => {
|
|
4626
4631
|
const buffer = Buffer.from(encryptedValue);
|
|
4627
|
-
if (buffer.length <= chromeV10Prefix.length
|
|
4632
|
+
if (buffer.length <= chromeV10Prefix.length) {
|
|
4633
|
+
throw new UnsupportedChromeCookieEncryptionError();
|
|
4634
|
+
}
|
|
4635
|
+
const prefix = buffer.subarray(0, chromeV10Prefix.length);
|
|
4636
|
+
let key;
|
|
4637
|
+
if (prefix.equals(chromeV10Prefix)) {
|
|
4638
|
+
key = chromeV10Key;
|
|
4639
|
+
} else if (prefix.equals(chromeV11Prefix) && chromeSafeStoragePassword !== undefined) {
|
|
4640
|
+
key = pbkdf2Sync(chromeSafeStoragePassword, 'saltysalt', 1, 16, 'sha1');
|
|
4641
|
+
} else {
|
|
4628
4642
|
throw new UnsupportedChromeCookieEncryptionError();
|
|
4629
4643
|
}
|
|
4630
|
-
const decipher = createDecipheriv('aes-128-cbc',
|
|
4631
|
-
const plaintext = Buffer.concat([decipher.update(buffer.subarray(
|
|
4644
|
+
const decipher = createDecipheriv('aes-128-cbc', key, chromeV10Iv);
|
|
4645
|
+
const plaintext = Buffer.concat([decipher.update(buffer.subarray(prefix.length)), decipher.final()]);
|
|
4632
4646
|
if (databaseVersion < 24) {
|
|
4633
4647
|
return plaintext.toString('utf8');
|
|
4634
4648
|
}
|
|
@@ -4661,13 +4675,13 @@ const getExpirationDate = expiresUtc => {
|
|
|
4661
4675
|
const chromeMicroseconds = BigInt(expiresUtc);
|
|
4662
4676
|
return Number(chromeMicroseconds - chromeEpochOffsetMicroseconds) / Number(microsecondsPerSecond);
|
|
4663
4677
|
};
|
|
4664
|
-
const getValue = (row, databaseVersion) => {
|
|
4678
|
+
const getValue = (row, databaseVersion, chromeSafeStoragePassword) => {
|
|
4665
4679
|
if (row.value) {
|
|
4666
4680
|
return row.value;
|
|
4667
4681
|
}
|
|
4668
|
-
return decrypt$1(row.hostKey, row.encryptedValue, databaseVersion);
|
|
4682
|
+
return decrypt$1(row.hostKey, row.encryptedValue, databaseVersion, chromeSafeStoragePassword);
|
|
4669
4683
|
};
|
|
4670
|
-
const convert$1 = (row, databaseVersion, now = Date.now() / 1000) => {
|
|
4684
|
+
const convert$1 = (row, databaseVersion, chromeSafeStoragePassword, now = Date.now() / 1000) => {
|
|
4671
4685
|
if (!row.hostKey || row.topFrameSiteKey) {
|
|
4672
4686
|
return undefined;
|
|
4673
4687
|
}
|
|
@@ -4683,7 +4697,7 @@ const convert$1 = (row, databaseVersion, now = Date.now() / 1000) => {
|
|
|
4683
4697
|
sameSite: getSameSite$1(row.sameSite),
|
|
4684
4698
|
secure,
|
|
4685
4699
|
url: `${secure ? 'https' : 'http'}://${host}/`,
|
|
4686
|
-
value: getValue(row, databaseVersion)
|
|
4700
|
+
value: getValue(row, databaseVersion, chromeSafeStoragePassword)
|
|
4687
4701
|
};
|
|
4688
4702
|
if (row.hostKey.startsWith('.')) {
|
|
4689
4703
|
details.domain = row.hostKey;
|
|
@@ -4763,6 +4777,79 @@ const readCookies$1 = path => {
|
|
|
4763
4777
|
});
|
|
4764
4778
|
};
|
|
4765
4779
|
|
|
4780
|
+
const secretServiceName = 'org.freedesktop.secrets';
|
|
4781
|
+
const secretServicePath = '/org/freedesktop/secrets';
|
|
4782
|
+
const secretServiceInterface = 'org.freedesktop.Secret.Service';
|
|
4783
|
+
const secretCollectionInterface = 'org.freedesktop.Secret.Collection';
|
|
4784
|
+
const secretItemInterface = 'org.freedesktop.Secret.Item';
|
|
4785
|
+
const propertiesInterface = 'org.freedesktop.DBus.Properties';
|
|
4786
|
+
const defaultCollectionPath = '/org/freedesktop/secrets/aliases/default';
|
|
4787
|
+
const chromeSafeStorageLabel = 'Chrome Safe Storage';
|
|
4788
|
+
const getProperties = async (bus, path) => {
|
|
4789
|
+
return bus.getService(secretServiceName).getInterface(path, propertiesInterface);
|
|
4790
|
+
};
|
|
4791
|
+
const findChromeSafeStorageItem = async (bus, service) => {
|
|
4792
|
+
const [unlocked, locked] = await service.SearchItems({
|
|
4793
|
+
application: 'chrome'
|
|
4794
|
+
});
|
|
4795
|
+
const matchingItems = [...unlocked, ...locked];
|
|
4796
|
+
if (matchingItems.length > 0) {
|
|
4797
|
+
return matchingItems[0];
|
|
4798
|
+
}
|
|
4799
|
+
const collectionProperties = await getProperties(bus, defaultCollectionPath);
|
|
4800
|
+
const items = await collectionProperties.Get(secretCollectionInterface, 'Items');
|
|
4801
|
+
for (const item of items) {
|
|
4802
|
+
const itemProperties = await getProperties(bus, item);
|
|
4803
|
+
const label = await itemProperties.Get(secretItemInterface, 'Label');
|
|
4804
|
+
if (label === chromeSafeStorageLabel) {
|
|
4805
|
+
return item;
|
|
4806
|
+
}
|
|
4807
|
+
}
|
|
4808
|
+
throw new Error('Chrome Safe Storage password was not found in the Linux keyring');
|
|
4809
|
+
};
|
|
4810
|
+
const unlockItem = async (service, item) => {
|
|
4811
|
+
const [unlocked, prompt] = await service.Unlock([item]);
|
|
4812
|
+
if (unlocked.includes(item)) {
|
|
4813
|
+
return;
|
|
4814
|
+
}
|
|
4815
|
+
if (prompt !== '/') {
|
|
4816
|
+
throw new Error('Chrome Safe Storage is locked; unlock the desktop keyring and try again');
|
|
4817
|
+
}
|
|
4818
|
+
throw new Error('Chrome Safe Storage could not be unlocked');
|
|
4819
|
+
};
|
|
4820
|
+
const readPassword = async bus => {
|
|
4821
|
+
const service = await bus.getService(secretServiceName).getInterface(secretServicePath, secretServiceInterface);
|
|
4822
|
+
const [, sessionPath] = await service.OpenSession('plain', new Variant('s', ''));
|
|
4823
|
+
const item = await findChromeSafeStorageItem(bus, service);
|
|
4824
|
+
let secrets;
|
|
4825
|
+
try {
|
|
4826
|
+
secrets = await service.GetSecrets([item], sessionPath);
|
|
4827
|
+
} catch {
|
|
4828
|
+
await unlockItem(service, item);
|
|
4829
|
+
secrets = await service.GetSecrets([item], sessionPath);
|
|
4830
|
+
}
|
|
4831
|
+
const secret = secrets[item];
|
|
4832
|
+
if (!secret) {
|
|
4833
|
+
throw new Error('Chrome Safe Storage password was not returned by the Linux keyring');
|
|
4834
|
+
}
|
|
4835
|
+
return Buffer.from(secret[2]).toString('utf8');
|
|
4836
|
+
};
|
|
4837
|
+
const getErrorMessage = error => {
|
|
4838
|
+
return error instanceof Error ? error.message : String(error);
|
|
4839
|
+
};
|
|
4840
|
+
const getChromeSafeStoragePassword = async () => {
|
|
4841
|
+
const bus = dbus.sessionBus({
|
|
4842
|
+
timeout: 5000
|
|
4843
|
+
});
|
|
4844
|
+
try {
|
|
4845
|
+
return await readPassword(bus);
|
|
4846
|
+
} catch (error) {
|
|
4847
|
+
throw new Error(`Failed to read Chrome Safe Storage password: ${getErrorMessage(error)}`);
|
|
4848
|
+
} finally {
|
|
4849
|
+
await bus.close();
|
|
4850
|
+
}
|
|
4851
|
+
};
|
|
4852
|
+
|
|
4766
4853
|
const isValidProfileDirectory = value => {
|
|
4767
4854
|
return value !== '' && value !== '.' && value !== '..' && !value.includes('/') && !value.includes('\\');
|
|
4768
4855
|
};
|
|
@@ -4972,12 +5059,14 @@ const importFromDirectory$1 = async (chromeDataDirectory, session) => {
|
|
|
4972
5059
|
rows,
|
|
4973
5060
|
version
|
|
4974
5061
|
} = readCookies$1(profile.cookieDatabasePath);
|
|
5062
|
+
const requiresChromeSafeStoragePassword = rows.some(row => !row.value && isV11(row.encryptedValue));
|
|
5063
|
+
const chromeSafeStoragePassword = requiresChromeSafeStoragePassword ? await getChromeSafeStoragePassword() : undefined;
|
|
4975
5064
|
const cookies = [];
|
|
4976
5065
|
let skipped = 0;
|
|
4977
5066
|
let unsupportedEncryption = 0;
|
|
4978
5067
|
for (const row of rows) {
|
|
4979
5068
|
try {
|
|
4980
|
-
const cookie = convert$1(row, version);
|
|
5069
|
+
const cookie = convert$1(row, version, chromeSafeStoragePassword);
|
|
4981
5070
|
if (cookie) {
|
|
4982
5071
|
cookies.push(cookie);
|
|
4983
5072
|
} else {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lvce-editor/main-process",
|
|
3
|
-
"version": "6.19.
|
|
3
|
+
"version": "6.19.2",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"lvce-editor",
|
|
6
6
|
"electron"
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"type": "module",
|
|
15
15
|
"main": "dist/mainProcessMain.js",
|
|
16
16
|
"dependencies": {
|
|
17
|
+
"dbus-native": "^0.15.1",
|
|
17
18
|
"electron": "43.2.0"
|
|
18
19
|
},
|
|
19
20
|
"engines": {
|