From c7956ae9b228054d57897ea338ad4154cc0b7221 Mon Sep 17 00:00:00 2001 From: Caine Date: Sun, 15 Feb 2026 09:41:49 +0000 Subject: Initial commit: susan automation scripts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Overnight transcoding, music discovery/import, system health reports, stats page generator, and bookmark management. Secrets stored in /etc/automation/ — not in repo. --- decrypt_bookmarks.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 decrypt_bookmarks.js (limited to 'decrypt_bookmarks.js') diff --git a/decrypt_bookmarks.js b/decrypt_bookmarks.js new file mode 100644 index 0000000..e73c4e4 --- /dev/null +++ b/decrypt_bookmarks.js @@ -0,0 +1,34 @@ +#!/usr/bin/env node +// Decrypt Floccus bookmarks +// Usage: node decrypt_bookmarks.js [password] + +const crypto = require('crypto'); +const fs = require('fs'); + +const BOOKMARKS_PATH = '/var/www/webdav/bookmarks.xbel'; +const password = process.argv[2] || process.env.BOOKMARKS_PASSWORD || JSON.parse(require('fs').readFileSync('/etc/automation/bookmarks.json', 'utf8')).password; + +const data = JSON.parse(fs.readFileSync(BOOKMARKS_PATH, 'utf8')); +const ciphertext = Buffer.from(data.ciphertext, 'base64'); +const salt = data.salt; // Floccus uses salt as UTF-8 string, not hex-decoded + +// Floccus encryption: PBKDF2-SHA256, 250000 iterations +const key = crypto.pbkdf2Sync(password, salt, 250000, 32, 'sha256'); + +// 16-byte IV at start, then ciphertext, then 16-byte GCM tag at end +const iv = ciphertext.slice(0, 16); +const encrypted = ciphertext.slice(16, -16); +const tag = ciphertext.slice(-16); + +try { + const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv); + decipher.setAuthTag(tag); + + let decrypted = decipher.update(encrypted); + decrypted = Buffer.concat([decrypted, decipher.final()]); + + console.log(decrypted.toString('utf8')); +} catch (e) { + console.error('Decryption failed:', e.message); + process.exit(1); +} -- cgit v1.2.3