-
-
Notifications
You must be signed in to change notification settings - Fork 100
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
Feature Request: node script for decrypting bookmarks #105
Comments
Hi @abudden , I don't have time to look at this right now, but it shouldn't be too difficult to adapt existing code into a Node script. I can give you the gist then yourself or someone else could give it a go. The functions required to decrypt bookmarks data are:
xBrowserSync uses the browser's implementation of the Web Crypto API, unfortunately Node does not yet include such an implementation, but the Node It might look scary but it's less than 100 lines of code combined! Definitely doable. Give it a go and see how you get on. |
@nero120 Thanks for the notes. I've had another go (starting from scratch rather than my previous attempt with copying and pasting the xbrowsersync source code). As a javascript novice, I still feel like I'm fumbling in the dark, but I've included my first attempt below. It looked promising to me, but there are at least two major issues:
Do you have time to have a look through what I've tried to see if you can spot the problems? This is literally my first ever time using node, so I doubt I've written the code in anywhere near the best way... const crypto = require('crypto');
const util = require('util');
// The raw entered password (50 characters in my case)
var PASSWORD = '';
// The sync ID extracted from the xbrowsersync UI (32 characters)
var SYNC_ID = '';
// The hashed password, extracted with Chrome
// console (44 characters, base64):
//
// > console.log(localStorage['xBrowserSync-password']);
//
// NOTE that I couldn't get chrome.storage.local.get to work
// in the extension background inspect or popup inspect: in
// both cases it said that chrome.storage is undefined.
var HASHED_PASSWORD = '';
// Encrypted bookmarks, extracted for testing from Chrome
// console (44296 characters in my case, base64):
//
// > console.log(localStorage['xBrowserSync-cachedBookmarks']);
//
var ENCRYPTED_BOOKMARKS = '';
const pbkdf2 = util.promisify(crypto.pbkdf2);
function getPasswordHash(password, syncId) {
var encoder = new util.TextEncoder('utf-8');
var keyData = encoder.encode(password);
var salt = encoder.encode(syncId);
// Key length of 32 was chosen as it seems to produce a result
// that matches (in length, if not in value) the hashed password
// from Chrome localStorage.
return pbkdf2(keyData, salt, 250000, 32, 'sha256')
.then(function(derivedKey) {
return derivedKey.toString('base64');
});
}
var encrypted_bytes = Buffer.from(ENCRYPTED_BOOKMARKS, 'base64');
var iv = encrypted_bytes.slice(0, 16);
var enc = encrypted_bytes.slice(16);
getPasswordHash(PASSWORD, SYNC_ID)
.then((key) => {
if (key.toString('base64') !== HASHED_PASSWORD) {
// ERROR: This shouldn't print out, but it does
console.log('Hashed password seems wrong: ', key.toString('base64'));
}
// ERROR Produces UnhandledPromiseRejectionWarning: Error: Invalid key length
var decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
// 'hex' parameter is just a guess...
var decrypted = decipher.update(enc, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}).then((decrypted) => {
// TODO: Write the decrypted data to a file...
console.log(decrypted);
});
|
Most of that looks fine, I've had a play and made a few small changes. However my version fails due to a wierd Node crypto behaviour, I've logged an issue with them so let's see what they say... |
Working version: https://gist.github.com/nero120/e878e40b14655c9526680472376b4f8c You'll need to run Hope that helps! |
Fantastic, thanks @nero120 I've implemented it on my server and it works like a dream. |
Glad to hear it! 😄 |
I wasn't sure whether this should be raised on the API or APP issue page; apologies if I've judged it wrong.
I use the Chrome extension to back up to my home server. At the moment, I'm keeping historical backups (so if I ever accidentally delete something I can plausibly go in and hack the database to load an old version) using a simple script:
It would be really useful to actually be able to read the bookmarks from a script on the server (I could then implement things like backups of the actual bookmarked websites, see what has actually changed in the bookmark history etc).
The problem is: the bookmarks are encrypted. This is a good thing, but I know the sync id and password and I would love to have a script that took
export.json
from the above script (or just used the REST api) along with the sync id and password and spat out the decrypted bookmarks. I can do this manually with the backup feature, but I want to stick this in a cron job and have it run on the server regularly.I had a go experimenting with a copy of bits of the app source code and
node.js
, but kept getting pages of error messages; my javascript knowledge isn't up to resolving all of them sadly.I've raised this on the app page as that's where most of the decryption code exists. I'm hoping that someone good at javascript could somehow import utility.js and write a few short lines of code to make it work.
The text was updated successfully, but these errors were encountered: