Last active
January 20, 2023 17:26
-
-
Save nero120/e878e40b14655c9526680472376b4f8c to your computer and use it in GitHub Desktop.
A Node.js script to decrypt xBrowserSync sync data.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const crypto = require('crypto'); | |
const lzutf8 = require('lzutf8'); | |
const util = require('util'); | |
const pbkdf2 = util.promisify(crypto.pbkdf2); | |
async function getPasswordHash(password, syncId) { | |
// Generate pbkdf2 key and return as base64 string | |
const encoder = new util.TextEncoder('utf-8'); | |
const keyData = encoder.encode(password); | |
const salt = encoder.encode(syncId); | |
const derivedKey = await pbkdf2(keyData, salt, 250000, 32, 'sha256'); | |
const keyString = derivedKey.toString('base64'); | |
return keyString; | |
} | |
async function decryptData(key, encryptedBookmarks) { | |
// Get the required data arrays for decryption | |
const keyData = Uint8Array.from(Buffer.from(key, 'base64')); | |
const encrypted_bytes = Uint8Array.from(Buffer.from(encryptedBookmarks, 'base64')); | |
const iv = encrypted_bytes.slice(0, 16); | |
const tag = encrypted_bytes.slice(-16); | |
const enc = encrypted_bytes.slice(16, encrypted_bytes.length - 16); | |
// Run decryption and return buffer | |
const decipher = crypto.createDecipheriv('aes-256-gcm', keyData, iv, { authTagLength: 16 }); | |
decipher.setAuthTag(tag); | |
const decrypted = Buffer.concat([decipher.update(enc), decipher.final()]); | |
return decrypted; | |
} | |
(async () => { | |
// The raw entered password (50 characters in my case) | |
const plainTextPassword = 'asd'; | |
// The sync ID extracted from the xbrowsersync UI (32 characters) | |
const syncId = 'bdf7b0a552c347cc8479a7b287a43c00'; | |
// Encrypted bookmarks, extracted for testing from Chrome | |
const encryptedBookmarks = `dsAxxN4gQHvsr/5BPF8F1G84oxlTroAbDX++ha8JgHJgjE8iXvQH2+7t3daG3r2WPsmLRS/KWdc/FwntiAYqSZIzQQQn6VcKYFVCdA/ZeSjZhxYh3SnG8i/FA6zgI/hBWvbk4W/xgW14tvA1lNGHAYFU6ZAXhOlR`; | |
// Generate the password hash | |
const key = await getPasswordHash(plainTextPassword, syncId); | |
// Decrypt the encrypted data using password hash | |
const decryptedData = await decryptData(key, encryptedBookmarks); | |
// Decompress the decrypted data to it's original json and beautify | |
const decryptedJson = lzutf8.decompress(decryptedData); | |
const beautifiedJson = JSON.stringify(JSON.parse(decryptedJson), null, 2); | |
console.log(beautifiedJson); | |
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "xbrowsersync-node-decryption", | |
"version": "1.0.0", | |
"description": "A Node.js script to decrypt xBrowserSync sync data.", | |
"main": "index.js", | |
"dependencies": { | |
"lzutf8": "^0.5.5" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment