Skip to content

Commit 7229b9d

Browse files
authored
fix: add support for log file using split state format (#88)
1 parent 2c5b76b commit 7229b9d

File tree

5 files changed

+133
-71
lines changed

5 files changed

+133
-71
lines changed

app/lib.js

Lines changed: 50 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ const passworder = require('@metamask/browser-passworder')
44
function dedupe (arr) {
55
const result = []
66
arr?.forEach(x => {
7+
if (x == null) {
8+
return
9+
}
710
if (!result.find(y => Object.keys(x).length === Object.keys(y).length && Object.entries(x).every(([k,ex]) => y[k] === ex ))) {
811
result.push(x)
912
}
@@ -116,27 +119,55 @@ function extractVaultFromFile (data) {
116119
}
117120
}
118121

119-
// attempt 6: chromium 000005.ldb on windows
120-
const matchRegex = /Keyring[0-9][^\}]*(\{[^\{\}]*\\"\})/gu
121-
const captureRegex = /Keyring[0-9][^\}]*(\{[^\{\}]*\\"\})/u
122-
const ivRegex = /\\"iv.{1,4}[^A-Za-z0-9+\/]{1,10}([A-Za-z0-9+\/]{10,40}=*)/u
123-
const dataRegex = /\\"[^":,is]*\\":\\"([A-Za-z0-9+\/]*=*)/u
124-
const saltRegex = /,\\"salt.{1,4}[^A-Za-z0-9+\/]{1,10}([A-Za-z0-9+\/]{10,100}=*)/u
125-
const vaults = dedupe(data.match(matchRegex)?.map(m => m.match(captureRegex)[1])
126-
.map(s => [dataRegex, ivRegex, saltRegex].map(r => s.match(r)))
127-
.filter(([d,i,s]) => d&&d.length>1 && i&&i.length>1 && s&&s.length>1)
128-
.map(([d,i,s]) => ({
129-
data: d[1],
130-
iv: i[1],
131-
salt: s[1],
132-
})))
133-
if (!vaults.length) {
134-
return null
122+
{
123+
// attempt 6: chromium 000005.ldb on windows
124+
const matchRegex = /Keyring[0-9][^\}]*(\{[^\{\}]*\\"\})/gu
125+
const captureRegex = /Keyring[0-9][^\}]*(\{[^\{\}]*\\"\})/u
126+
const ivRegex = /\\"iv.{1,4}[^A-Za-z0-9+\/]{1,10}([A-Za-z0-9+\/]{10,40}=*)/u
127+
const dataRegex = /\\"[^":,is]*\\":\\"([A-Za-z0-9+\/]*=*)/u
128+
const saltRegex = /,\\"salt.{1,4}[^A-Za-z0-9+\/]{1,10}([A-Za-z0-9+\/]{10,100}=*)/u
129+
const vaults = dedupe(data.match(matchRegex)?.map(m => m.match(captureRegex)[1])
130+
.map(s => [dataRegex, ivRegex, saltRegex].map(r => s.match(r)))
131+
.filter(([d,i,s]) => d&&d.length>1 && i&&i.length>1 && s&&s.length>1)
132+
.map(([d,i,s]) => ({
133+
data: d[1],
134+
iv: i[1],
135+
salt: s[1],
136+
})))
137+
if (vaults.length) {
138+
/* istanbul ignore next */
139+
if (vaults.length > 1) {
140+
console.log('Found multiple vaults!', vaults)
141+
}
142+
return vaults[0]
143+
}
135144
}
136-
if (vaults.length > 1) {
137-
console.log('Found multiple vaults!', vaults)
145+
{
146+
// attempt 7: log file using split state format, chromium 000004.log on windows-2
147+
const vaultRegex = /KeyringController[\s\S]*?"vault":"((?:[^"\\]|\\.)*)"/g
148+
const vaults = []
149+
let match
150+
151+
while ((match = vaultRegex.exec(data)) !== null) {
152+
try {
153+
const vaultString = JSON.parse(`"${match[1]}"`)
154+
const json = JSON.parse(vaultString)
155+
vaults.push(json)
156+
} catch (err) {
157+
// Not valid JSON: continue
158+
}
159+
}
160+
161+
const dedupedVaults = dedupe(vaults)
162+
if (dedupedVaults.length) {
163+
/* istanbul ignore next */
164+
if (dedupedVaults.length > 1) {
165+
console.log('Found multiple vaults!', dedupedVaults)
166+
}
167+
return dedupedVaults[0]
168+
}
138169
}
139-
return vaults[0]
170+
return null
140171
}
141172

142173

@@ -176,5 +207,3 @@ module.exports = {
176207
extractVaultFromFile,
177208
isVaultValid,
178209
}
179-
180-

app/lib.test.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,25 @@ const FIXTURES = [
5050
'live pupil slab senior boy release lyrics shaft lazy renew potato simple',
5151
passphrase: 'correct horse battery staple',
5252
},
53+
{
54+
path: 'chrome-windows-2/000004.log',
55+
mnemonic: 'please injury labor shift much city general enemy vivid bench pottery picture',
56+
passphrase: 'correct horse battery staple',
57+
},
5358
]
5459

5560
const VAULTS = [
5661
{
5762
variant: 'vault with no key metadata',
5863
vaultData: '{"data":"s6TpYjlUNsn7ifhEFTkuDGBUM1GyOlPrim7JSjtfIxgTt8/6MiXgiR/CtFfR4dWW2xhq85/NGIBYEeWrZThGdKGarBzeIqBfLFhw9n509jprzJ0zc2Rf+9HVFGLw+xxC4xPxgCS0IIWeAJQ+XtGcHmn0UZXriXm8Ja4kdlow6SWinB7sr/WM3R0+frYs4WgllkwggDf2/Tv6VHygvLnhtzp6hIJFyTjh+l/KnyJTyZW1TkZhDaNDzX3SCOHT","iv":"FbeHDAW5afeWNORfNJBR0Q==","salt":"TxZ+WbCW6891C9LK/hbMAoUsSEW1E8pyGLVBU6x5KR8="}',
5964
mnemonic: 'spread raise short crane omit tent fringe mandate neglect detail suspect cradle',
60-
passphrase: 'correct horse battery staple',
65+
passphrase: 'correct horse battery staple',
6166
},
6267
{
6368
variant: 'vault with key metadata and 600_000 iterations',
6469
vaultData: '{"data":"WHaP1FrrtV4zUonudIppDifsLHF39g6oPkVksAIdWAHBRzax1uy1asfAJprR7u72t4/HuYz5yPIFQrnNnv+hwQu9GRuty88VKMnvMy+sq8MNtoXI+C54bZpWa8r4iUQfa0Mj/cfJbpFpzOdF1ZYXahTfTcU5WsrHwvJew842CiJR4B2jmCHHXfm/DxLK3WazsVQwXJGx/U71UelGoOOrT8NI28EKrAwgPn+7Xmv0j92gmhau30N7Bo2fr6Zv","iv":"LfD8/tY1EjXzxuemSmDVdA==","keyMetadata":{"algorithm":"PBKDF2","params":{"iterations":600000}},"salt":"nk4xdpmMR+1s5BYe4Vnk++XAQwrISI2bCtbMg7V1wUA="}',
6570
mnemonic: 'spread raise short crane omit tent fringe mandate neglect detail suspect cradle',
66-
passphrase: 'correct horse battery staple',
71+
passphrase: 'correct horse battery staple',
6772
},
6873
]
6974

@@ -88,7 +93,7 @@ describe('decryptVault', () => {
8893
VAULTS.forEach((vault) => {
8994
it(`decrypts ${vault.variant}`, async () => {
9095
const decrypted = await decryptVault(
91-
vault.passphrase,
96+
vault.passphrase,
9297
JSON.parse(vault.vaultData)
9398
);
9499

bundle.js

Lines changed: 72 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ var passworder = require('@metamask/browser-passworder');
1515
function dedupe(arr) {
1616
var result = [];
1717
arr === null || arr === void 0 ? void 0 : arr.forEach(function (x) {
18+
if (x == null) {
19+
return;
20+
}
1821
if (!result.find(function (y) {
1922
return Object.keys(x).length === Object.keys(y).length && Object.entries(x).every(function (_ref) {
2023
var _ref2 = _slicedToArray(_ref, 2),
@@ -36,7 +39,6 @@ function decodeMnemonic(mnemonic) {
3639
}
3740
}
3841
function extractVaultFromFile(data) {
39-
var _data$match;
4042
var vaultBody;
4143
try {
4244
// attempt 1: raw json
@@ -75,11 +77,11 @@ function extractVaultFromFile(data) {
7577
if (_matches2 && _matches2.length) {
7678
try {
7779
var keyringControllerStateFragment = _matches2[1];
78-
var _dataRegex = /\\"data\\":\\"([\+\/-9A-Za-z]*=*)/;
79-
var _ivRegex = /,\\"iv\\":\\"([\+\/-9A-Za-z]{10,40}=*)/;
80-
var _saltRegex = /,\\"salt\\":\\"([A-Za-z0-9+\/]{10,100}=*)\\"/;
80+
var dataRegex = /\\"data\\":\\"([\+\/-9A-Za-z]*=*)/;
81+
var ivRegex = /,\\"iv\\":\\"([\+\/-9A-Za-z]{10,40}=*)/;
82+
var saltRegex = /,\\"salt\\":\\"([A-Za-z0-9+\/]{10,100}=*)\\"/;
8183
var keyMetaRegex = /,\\"keyMetadata\\":(.*}})/;
82-
var vaultParts = [_dataRegex, _ivRegex, _saltRegex, keyMetaRegex].map(function (reg) {
84+
var vaultParts = [dataRegex, ivRegex, saltRegex, keyMetaRegex].map(function (reg) {
8385
return keyringControllerStateFragment.match(reg);
8486
}).map(function (match) {
8587
return match[1];
@@ -102,11 +104,11 @@ function extractVaultFromFile(data) {
102104
if (_matches3 && _matches3.length) {
103105
try {
104106
var _keyringControllerStateFragment = _matches3[1];
105-
var _dataRegex2 = /\\"data\\":\\"([\+\/-9A-Za-z]*=*)/;
106-
var _ivRegex2 = /,\\"iv\\":\\"([\+\/-9A-Za-z]{10,40}=*)/;
107-
var _saltRegex2 = /,\\"salt\\":\\"([A-Za-z0-9+\/]{10,100}=*)\\"/;
107+
var _dataRegex = /\\"data\\":\\"([\+\/-9A-Za-z]*=*)/;
108+
var _ivRegex = /,\\"iv\\":\\"([\+\/-9A-Za-z]{10,40}=*)/;
109+
var _saltRegex = /,\\"salt\\":\\"([A-Za-z0-9+\/]{10,100}=*)\\"/;
108110
var _keyMetaRegex = /,\\"keyMetadata\\":(.*}})/;
109-
var _vaultParts = [_dataRegex2, _ivRegex2, _saltRegex2, _keyMetaRegex].map(function (reg) {
111+
var _vaultParts = [_dataRegex, _ivRegex, _saltRegex, _keyMetaRegex].map(function (reg) {
110112
return _keyringControllerStateFragment.match(reg);
111113
}).map(function (match) {
112114
return match[1];
@@ -122,43 +124,69 @@ function extractVaultFromFile(data) {
122124
}
123125
}
124126
}
125-
126-
// attempt 6: chromium 000005.ldb on windows
127-
var matchRegex = /Keyring[0-9](?:[\0-\|~-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*(\{(?:[\0-z\|~-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*\\"\})/g;
128-
var captureRegex = /Keyring[0-9](?:[\0-\|~-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*(\{(?:[\0-z\|~-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*\\"\})/;
129-
var ivRegex = /\\"iv(?:[\0-\t\x0B\f\x0E-\u2027\u202A-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]){1,4}(?:[\0-\*,-\.:-@\[-`\{-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]){1,10}([\+\/-9A-Za-z]{10,40}=*)/;
130-
var dataRegex = /\\"(?:[\0-!#-\+\x2D-9;-hj-rt-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*\\":\\"([\+\/-9A-Za-z]*=*)/;
131-
var saltRegex = /,\\"salt(?:[\0-\t\x0B\f\x0E-\u2027\u202A-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]){1,4}(?:[\0-\*,-\.:-@\[-`\{-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]){1,10}([\+\/-9A-Za-z]{10,100}=*)/;
132-
var vaults = dedupe((_data$match = data.match(matchRegex)) === null || _data$match === void 0 ? void 0 : _data$match.map(function (m) {
133-
return m.match(captureRegex)[1];
134-
}).map(function (s) {
135-
return [dataRegex, ivRegex, saltRegex].map(function (r) {
136-
return s.match(r);
137-
});
138-
}).filter(function (_ref3) {
139-
var _ref4 = _slicedToArray(_ref3, 3),
140-
d = _ref4[0],
141-
i = _ref4[1],
142-
s = _ref4[2];
143-
return d && d.length > 1 && i && i.length > 1 && s && s.length > 1;
144-
}).map(function (_ref5) {
145-
var _ref6 = _slicedToArray(_ref5, 3),
146-
d = _ref6[0],
147-
i = _ref6[1],
148-
s = _ref6[2];
149-
return {
150-
data: d[1],
151-
iv: i[1],
152-
salt: s[1]
153-
};
154-
}));
155-
if (!vaults.length) {
156-
return null;
127+
{
128+
var _data$match;
129+
// attempt 6: chromium 000005.ldb on windows
130+
var matchRegex = /Keyring[0-9](?:[\0-\|~-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*(\{(?:[\0-z\|~-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*\\"\})/g;
131+
var captureRegex = /Keyring[0-9](?:[\0-\|~-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*(\{(?:[\0-z\|~-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*\\"\})/;
132+
var _ivRegex2 = /\\"iv(?:[\0-\t\x0B\f\x0E-\u2027\u202A-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]){1,4}(?:[\0-\*,-\.:-@\[-`\{-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]){1,10}([\+\/-9A-Za-z]{10,40}=*)/;
133+
var _dataRegex2 = /\\"(?:[\0-!#-\+\x2D-9;-hj-rt-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*\\":\\"([\+\/-9A-Za-z]*=*)/;
134+
var _saltRegex2 = /,\\"salt(?:[\0-\t\x0B\f\x0E-\u2027\u202A-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]){1,4}(?:[\0-\*,-\.:-@\[-`\{-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]){1,10}([\+\/-9A-Za-z]{10,100}=*)/;
135+
var vaults = dedupe((_data$match = data.match(matchRegex)) === null || _data$match === void 0 ? void 0 : _data$match.map(function (m) {
136+
return m.match(captureRegex)[1];
137+
}).map(function (s) {
138+
return [_dataRegex2, _ivRegex2, _saltRegex2].map(function (r) {
139+
return s.match(r);
140+
});
141+
}).filter(function (_ref3) {
142+
var _ref4 = _slicedToArray(_ref3, 3),
143+
d = _ref4[0],
144+
i = _ref4[1],
145+
s = _ref4[2];
146+
return d && d.length > 1 && i && i.length > 1 && s && s.length > 1;
147+
}).map(function (_ref5) {
148+
var _ref6 = _slicedToArray(_ref5, 3),
149+
d = _ref6[0],
150+
i = _ref6[1],
151+
s = _ref6[2];
152+
return {
153+
data: d[1],
154+
iv: i[1],
155+
salt: s[1]
156+
};
157+
}));
158+
if (vaults.length) {
159+
/* istanbul ignore next */
160+
if (vaults.length > 1) {
161+
console.log('Found multiple vaults!', vaults);
162+
}
163+
return vaults[0];
164+
}
157165
}
158-
if (vaults.length > 1) {
159-
console.log('Found multiple vaults!', vaults);
166+
{
167+
// attempt 7: log file using split state format, chromium 000004.log on windows-2
168+
var vaultRegex = /KeyringController[\s\S]*?"vault":"((?:[^"\\]|\\.)*)"/g;
169+
var _vaults = [];
170+
var match;
171+
while ((match = vaultRegex.exec(data)) !== null) {
172+
try {
173+
var vaultString = JSON.parse("\"".concat(match[1], "\""));
174+
var json = JSON.parse(vaultString);
175+
_vaults.push(json);
176+
} catch (err) {
177+
// Not valid JSON: continue
178+
}
179+
}
180+
var dedupedVaults = dedupe(_vaults);
181+
if (dedupedVaults.length) {
182+
/* istanbul ignore next */
183+
if (dedupedVaults.length > 1) {
184+
console.log('Found multiple vaults!', dedupedVaults);
185+
}
186+
return dedupedVaults[0];
187+
}
160188
}
161-
return vaults[0];
189+
return null;
162190
}
163191
function isVaultValid(vault) {
164192
return _typeof(vault) === 'object' && ['data', 'iv', 'salt'].every(function (e) {

jest.config.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ module.exports = {
4141
// An object that configures minimum threshold enforcement for coverage results
4242
coverageThreshold: {
4343
global: {
44-
branches: 95.23,
44+
branches: 95.45,
4545
functions: 100,
46-
lines: 98.57,
47-
statements: 98.64,
46+
lines: 98.75,
47+
statements: 98.8,
4848
},
4949
},
5050

33.9 KB
Binary file not shown.

0 commit comments

Comments
 (0)