Skip to content

Commit

Permalink
Simpler crypt for admin tools.
Browse files Browse the repository at this point in the history
  • Loading branch information
ricmoo committed Sep 21, 2019
1 parent 238fcba commit 828c8cf
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 43 deletions.
2 changes: 1 addition & 1 deletion admin/cmds/publish.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ if (process.argv.length > 2) {

// Load the token from the encrypted store
try {
token = await config.get("token");
token = await config.get("npm-token");
} catch (error) {
switch (error.message) {
case "wrong password":
Expand Down
16 changes: 16 additions & 0 deletions admin/cmds/set-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"use strict";

const { prompt } = require("../../packages/cli");
const config = require("../config");

if (process.argv.length !== 3) {
console.log("Usage: set-config KEY");
process.exit(1);
}

const key = process.argv[2];

(async function() {
const value = await prompt.getPassword("Value: ");
await config.set(key, value);
})();
111 changes: 69 additions & 42 deletions admin/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ const computeHmac = require("../packages/sha2").computeHmac;

const colorify = require("./log").colorify;

function getConfigFilename() {
return resolve(os.homedir(), ".ethers-dist");
}

function getScrypt(message, password, salt) {
let progressBar = prompt.getProgressBar(message);
return new Promise((resolve, reject) => {
Expand All @@ -28,60 +24,91 @@ function getScrypt(message, password, salt) {
});
}

async function loadConfig(dkey) {
let config = { };

let filename = getConfigFilename();
if (fs.existsSync(filename)) {
let data = JSON.parse(fs.readFileSync(filename));
let ciphertext = Buffer.from(data.ciphertext, "base64");
let iv = Buffer.from(data.iv, "base64");
let aes = new AES.ModeOfOperation.ctr(dkey.slice(0, 32), new AES.Counter(iv));
let plaintext = aes.decrypt(ciphertext);
let hmac = computeHmac("sha512", dkey.slice(32, 64), plaintext);
if (hmac !== data.hmac) {
throw new Error("wrong password");
}
config = JSON.parse(Buffer.from(plaintext).toString());
function Config(filename) {
this.salt = null;
this.dkey = null;
this.values = { };
this.filename = filename;
}

Config.prototype.load = async function() {
if (this.dkey) { return; }

let data = null;
if (fs.existsSync(this.filename)) {
data = JSON.parse(fs.readFileSync(this.filename));
} else {
data = {
salt: Buffer.from(randomBytes(32)).toString("hex")
};
}

return config;
}
this.salt = data.salt;

async function getConfig(key) {
let password = await prompt.getPassword(colorify("Password (seesion-store): ", "bold"));
let dkey = await getScrypt(colorify("Decrypting", "bold"), password, key);
const password = await prompt.getPassword(colorify("Password (config-store): ", "bold"));

let config = await loadConfig(dkey);
return config[key];
}
this.dkey = await getScrypt(colorify("Unlocking config", "bold"), password, this.salt);

async function setConfig(key, value) {
let password = await prompt.getPassword(colorify("Password (seesion-store): ", "bold"));
let dkey = await getScrypt("Encrypting", password, key);
if (data.ciphertext) {
const ciphertext = Buffer.from(data.ciphertext, "base64");
const iv = Buffer.from(data.iv, "base64");
const aes = new AES.ModeOfOperation.ctr(this.dkey.slice(0, 32), new AES.Counter(iv));
const plaintext = aes.decrypt(ciphertext);
const hmac = computeHmac("sha512", this.dkey.slice(32, 64), plaintext);
if (hmac !== data.hmac) {
throw new Error("wrong password");
}

let config = await loadConfig(dkey);
config[key] = value;
config._junk = Buffer.from(randomBytes(16 + parseInt(Math.random() * 48))).toString("base64")
this.values = JSON.parse(Buffer.from(plaintext).toString());
}
};

let plaintext = Buffer.from(JSON.stringify(config));
Config.prototype.save = function() {
this.values._junk = Buffer.from(randomBytes(16 + parseInt(Math.random() * 48))).toString("base64")

let iv = Buffer.from(randomBytes(16));
let hmac = computeHmac("sha512", dkey.slice(32, 64), plaintext);
const plaintext = Buffer.from(JSON.stringify(this.values));

let aes = new AES.ModeOfOperation.ctr(dkey.slice(0, 32), new AES.Counter(iv));
let ciphertext = Buffer.from(aes.encrypt(plaintext));
const iv = Buffer.from(randomBytes(16));
const hmac = computeHmac("sha512", this.dkey.slice(32, 64), plaintext);

let data = {
const aes = new AES.ModeOfOperation.ctr(this.dkey.slice(0, 32), new AES.Counter(iv));
const ciphertext = Buffer.from(aes.encrypt(plaintext));

const data = {
ciphertext: ciphertext.toString("base64"),
iv: iv.toString("base64"),
salt: this.salt,
hmac: hmac
};

fs.writeFileSync(getConfigFilename(), JSON.stringify(data, null, 2));
fs.writeFileSync(this.filename, JSON.stringify(data, null, 2));
}

Config.prototype.get = async function(key) {
await this.load();
return this.values[key];
};

Config.prototype.set = async function(key, value) {
await this.load();
this.values[key] = value;
this.save();
};

Config.prototype.lock = function() {
this.salt = this.dkey = null;
}

const config = new Config(resolve(os.homedir(), ".ethers-dist"));

module.exports = {
get: getConfig,
set: setConfig
get: function(key) {
return config.get(key);
},
set: function(key, value) {
config.set(key, value);
},
lock: function() {
config.lock();
}
}

0 comments on commit 828c8cf

Please sign in to comment.