service auth | Decrypt passwords.json | Cell 2 | Search

This code securely stores user credentials by encrypting them using AES-256-CTR and managing them in a JSON file, ensuring data privacy and protection.

Run example

npm run import -- "Add encrypted to passwords.json"

Add encrypted to passwords.json

var fs = require('fs');
var crypto = require('crypto');
var path = require('path');

var PROFILE_PATH = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE || '';
var PASS_FILE = path.join(PROFILE_PATH, '.credentials', 'password.txt');
var PASSWORDS_FILE = path.join(PROFILE_PATH, '.credentials', 'passwords.json');
var pass = process.env.SELENIUM_PASS || fs.readFileSync(PASS_FILE).toString();

function encrypt(text) {
    var cipher = crypto.createCipher('aes-256-ctr', pass);
    var crypted = cipher.update(text, 'binary', 'hex');
    crypted += cipher.final('hex');
    return crypted;
}

function encryptSet(set) {
    var resultSet = {};
    for (var i in set) {
        if (set.hasOwnProperty(i)) {
            if (i == 'added' || i == 'host') {
                resultSet[i] = set[i];
                continue;
            }
            resultSet[i] = encrypt(set[i]);
        }
    }
    return resultSet;
}

function saveCredentials(passwordAddJson) {
    // TODO: passAdd from file?
    var passwords = JSON.parse(fs.readFileSync(PASSWORDS_FILE).toString());
    passwordAddJson.added = new Date();
    var encrypted = encryptSet(passwordAddJson);
    if (passwordAddJson.host) {
        passwords = passwords.filter(function (el) {
            return el.host.toLowerCase() != passwordAddJson.host.toLowerCase()
                && (el.username || '').toLowerCase() != passwordAddJson.username.toLowerCase();
        });
    }
    passwords[passwords.length] = encrypted;
    var passwordString = JSON.stringify(passwords, null, 4);
    //var compressed = zlib.gzipSync(passwordString).toString('base64');
    console.log('Passwords: Saving encrypted file');
    fs.writeFileSync('passwords-new.json', passwordString);
    fs.renameSync(PASSWORDS_FILE, 'passwords-backup.json');
    fs.renameSync('passwords-new.json', PASSWORDS_FILE);
    fs.unlinkSync('passwords-backup.json');
    if (typeof passAdd !== 'undefined' && fs.existsSync(passAdd)) {
        console.log('Passwords: Deleting input file: ' + passAdd);
        fs.unlinkSync(passAdd);
    }
    return encrypted;
}

module.exports = saveCredentials;
saveCredentials;

What the code could have been:

const fs = require('fs');
const path = require('path');
const crypto = require('crypto');

const PROFILE_PATH = process.env.HOME ||
                    process.env.HOMEPATH ||
                    process.env.USERPROFILE ||
                    '';
const PASS_FILE = path.join(PROFILE_PATH, '.credentials', 'password.txt');
const PASSWORDS_FILE = path.join(PROFILE_PATH, '.credentials', 'passwords.json');

const getPass = () => {
    return process.env.SELENIUM_PASS || fs.readFileSync(PASS_FILE).toString();
};

const encrypt = (text) => {
    const cipher = crypto.createCipher('aes-256-ctr', getPass());
    return cipher.update(text, 'binary', 'hex') + cipher.final('hex');
};

const encryptSet = (set) => {
    const resultSet = {};
    for (const key in set) {
        if (Object.prototype.hasOwnProperty.call(set, key)) {
            if (key === 'added' || key === 'host') {
                resultSet[key] = set[key];
                continue;
            }
            resultSet[key] = encrypt(set[key]);
        }
    }
    return resultSet;
};

const saveCredentials = (passwordAddJson) => {
    try {
        const passwords = JSON.parse(fs.readFileSync(PASSWORDS_FILE, 'utf8'));
        const encrypted = encryptSet(passwordAddJson);
        if (passwordAddJson.host) {
            passwords = passwords.filter((el) => {
                return el.host.toLowerCase()!== passwordAddJson.host.toLowerCase() && (!el.username || '').toLowerCase()!== passwordAddJson.username.toLowerCase();
            });
        }
        passwords.push(encrypted);
        const passwordString = JSON.stringify(passwords, null, 4);
        fs.writeFileSync('passwords-new.json', passwordString);
        fs.renameSync(PASSWORDS_FILE, 'passwords-backup.json');
        fs.renameSync('passwords-new.json', PASSWORDS_FILE);
        fs.unlinkSync('passwords-backup.json');
        const passFile = process.env.SELENIUM_PASS || PASS_FILE;
        if (fs.existsSync(passFile)) {
            console.log(`Deleting input file: ${passFile}`);
            fs.unlinkSync(passFile);
        }
        console.log('Passwords: Saved encrypted file successfully');
        return encrypted;
    } catch (err) {
        console.error('Error saving credentials:', err);
        if (fs.existsSync(PASSWORDS_FILE)) {
            fs.renameSync(PASSWORDS_FILE, 'passwords-backup.json');
        }
        throw err;
    }
};

module.exports = saveCredentials;

This code snippet handles the encryption and storage of credentials.

Here's a breakdown:

  1. Setup:

  2. Encryption:

  3. Saving Credentials:

In essence, this code securely stores user credentials by encrypting them and managing them in a JSON file.