kopia lustrzana https://github.com/robinmoisson/staticrypt
add confirmation prompt for short pwd (closes #169)
rodzic
43f8fdfdd0
commit
066fcbf2d6
|
@ -2,7 +2,7 @@ const path = require("path");
|
|||
const fs = require("fs");
|
||||
const readline = require('readline');
|
||||
|
||||
const { generateRandomSalt } = require("../lib/cryptoEngine.js");
|
||||
const { generateRandomSalt, generateRandomString} = require("../lib/cryptoEngine.js");
|
||||
const { renderTemplate } = require("../lib/formater.js");
|
||||
const Yargs = require("yargs");
|
||||
|
||||
|
@ -71,6 +71,46 @@ function prompt (question) {
|
|||
});
|
||||
}
|
||||
|
||||
async function getValidatedPassword(passwordArgument, isShortAllowed) {
|
||||
const password = await getPassword(passwordArgument);
|
||||
|
||||
if (password.length < 14 && !isShortAllowed) {
|
||||
const shouldUseShort = await prompt(
|
||||
`WARNING: Your password is less than 14 characters (length: ${password.length})` +
|
||||
" and it's easy to try brute-forcing on public files. For better security we recommend using a longer one, for example: "
|
||||
+ generateRandomString(21)
|
||||
+ "\nYou can hide this warning by increasing your password length or adding the '--short' flag." +
|
||||
" Do you want to use the short password? [y/N] "
|
||||
)
|
||||
|
||||
if (!shouldUseShort.match(/^\s*(y|yes)\s*$/i)) {
|
||||
console.log("Aborting.");
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
return password;
|
||||
}
|
||||
exports.getValidatedPassword = getValidatedPassword;
|
||||
|
||||
/**
|
||||
* Get the config from the config file.
|
||||
*
|
||||
* @param {string} configArgument
|
||||
* @returns {{}|object}
|
||||
*/
|
||||
function getConfig(configArgument) {
|
||||
const isUsingconfigFile = configArgument.toLowerCase() !== "false";
|
||||
const configPath = "./" + configArgument;
|
||||
|
||||
if (isUsingconfigFile && fs.existsSync(configPath)) {
|
||||
return JSON.parse(fs.readFileSync(configPath, "utf8"));
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
exports.getConfig = getConfig;
|
||||
|
||||
/**
|
||||
* Get the password from the command arguments or environment variables.
|
||||
*
|
||||
|
@ -93,7 +133,6 @@ async function getPassword(passwordArgument) {
|
|||
// prompt the user for their password
|
||||
return prompt('Enter your long, unusual password: ');
|
||||
}
|
||||
exports.getPassword = getPassword;
|
||||
|
||||
/**
|
||||
* @param {string} filepath
|
||||
|
@ -108,6 +147,26 @@ function getFileContent(filepath) {
|
|||
}
|
||||
exports.getFileContent = getFileContent;
|
||||
|
||||
/**
|
||||
* @param {object} namedArgs
|
||||
* @param {object} config
|
||||
* @returns {string}
|
||||
*/
|
||||
function getValidatedSalt(namedArgs, config) {
|
||||
const salt = getSalt(namedArgs, config);
|
||||
|
||||
// validate the salt
|
||||
if (salt.length !== 32 || /[^a-f0-9]/.test(salt)) {
|
||||
exitWithError(
|
||||
"the salt should be a 32 character long hexadecimal string (only [0-9a-f] characters allowed)"
|
||||
+ "\nDetected salt: " + salt
|
||||
);
|
||||
}
|
||||
|
||||
return salt;
|
||||
}
|
||||
exports.getValidatedSalt = getValidatedSalt;
|
||||
|
||||
/**
|
||||
* @param {object} namedArgs
|
||||
* @param {object} config
|
||||
|
@ -126,7 +185,6 @@ function getSalt(namedArgs, config) {
|
|||
|
||||
return generateRandomSalt();
|
||||
}
|
||||
exports.getSalt = getSalt;
|
||||
|
||||
/**
|
||||
* A dead-simple alternative to webpack or rollup for inlining simple
|
||||
|
|
74
cli/index.js
74
cli/index.js
|
@ -9,9 +9,12 @@ require('dotenv').config();
|
|||
|
||||
const cryptoEngine = require("../lib/cryptoEngine.js");
|
||||
const codec = require("../lib/codec.js");
|
||||
const { generateRandomSalt, generateRandomString } = cryptoEngine;
|
||||
const { generateRandomSalt } = cryptoEngine;
|
||||
const { encode } = codec.init(cryptoEngine);
|
||||
const { parseCommandLineArguments, buildStaticryptJS, exitWithError, isOptionSetByUser, genFile, getPassword, getFileContent, getSalt } = require("./helpers.js");
|
||||
const { parseCommandLineArguments, buildStaticryptJS, isOptionSetByUser, genFile, getPassword, getFileContent, getSalt,
|
||||
getValidatedSalt,
|
||||
getValidatedPassword, getConfig
|
||||
} = require("./helpers.js");
|
||||
|
||||
// parse arguments
|
||||
const yargs = parseCommandLineArguments();
|
||||
|
@ -24,52 +27,12 @@ async function runStatiCrypt() {
|
|||
process.exit(0);
|
||||
}
|
||||
|
||||
// validate the number of arguments
|
||||
const positionalArguments = namedArgs._;
|
||||
if (positionalArguments.length === 0) {
|
||||
yargs.showHelp();
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// parse input
|
||||
const inputFilepath = positionalArguments[0].toString(),
|
||||
password = await getPassword(namedArgs.password);
|
||||
|
||||
if (password.length < 16 && !namedArgs.short) {
|
||||
console.log(
|
||||
`\nWARNING: Your password is less than 16 characters (length: ${password.length}). Brute-force attacks are easy to `
|
||||
+ `try on public files, and you are most safe when using a long password.\n\n`
|
||||
+ `👉️ Here's a strong generated password you could use: `
|
||||
+ generateRandomString(21)
|
||||
+ "\n\nThe file was encrypted with your password. You can hide this warning by increasing your password length or"
|
||||
+ " adding the '--short' flag."
|
||||
)
|
||||
}
|
||||
|
||||
// get config file
|
||||
const isUsingconfigFile = namedArgs.config.toLowerCase() !== "false";
|
||||
const configPath = "./" + namedArgs.config;
|
||||
let config = {};
|
||||
if (isUsingconfigFile && fs.existsSync(configPath)) {
|
||||
config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
||||
}
|
||||
const config = getConfig(namedArgs.config);
|
||||
|
||||
// get the salt
|
||||
const salt = getSalt(namedArgs, config);
|
||||
|
||||
// validate the salt
|
||||
if (salt.length !== 32 || /[^a-f0-9]/.test(salt)) {
|
||||
exitWithError(
|
||||
"the salt should be a 32 character long hexadecimal string (only [0-9a-f] characters allowed)"
|
||||
+ "\nDetected salt: " + salt
|
||||
);
|
||||
}
|
||||
|
||||
// write salt to config file
|
||||
if (isUsingconfigFile && config.salt !== salt) {
|
||||
config.salt = salt;
|
||||
fs.writeFileSync(configPath, JSON.stringify(config, null, 4));
|
||||
}
|
||||
// get the salt & password
|
||||
const salt = getValidatedSalt(namedArgs, config);
|
||||
const password = await getValidatedPassword(namedArgs.password, namedArgs.short);
|
||||
|
||||
// display the share link with the hashed password if the --share flag is set
|
||||
if (isOptionSetByUser("share", yargs)) {
|
||||
|
@ -78,9 +41,26 @@ async function runStatiCrypt() {
|
|||
const hashedPassword = await cryptoEngine.hashPassphrase(password, salt);
|
||||
|
||||
console.log(url + "#staticrypt_pwd=" + hashedPassword);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// validate the number of arguments
|
||||
const positionalArguments = namedArgs._;
|
||||
if (positionalArguments.length === 0) {
|
||||
yargs.showHelp();
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// write salt to config file
|
||||
const isUsingconfigFile = namedArgs.config.toLowerCase() !== "false";
|
||||
const configPath = "./" + namedArgs.config;
|
||||
if (isUsingconfigFile && config.salt !== salt) {
|
||||
config.salt = salt;
|
||||
fs.writeFileSync(configPath, JSON.stringify(config, null, 4));
|
||||
}
|
||||
|
||||
// get the file content
|
||||
const inputFilepath = positionalArguments[0].toString();
|
||||
const contents = getFileContent(inputFilepath);
|
||||
|
||||
// encrypt input
|
||||
|
@ -105,7 +85,7 @@ async function runStatiCrypt() {
|
|||
template_title: namedArgs.templateTitle,
|
||||
};
|
||||
|
||||
const outputFilepath = namedArgs.output.replace(/\/+$/, '') + "/" + inputFilepath;
|
||||
const outputFilepath = namedArgs.directory.replace(/\/+$/, '') + "/" + inputFilepath;
|
||||
|
||||
genFile(data, outputFilepath, namedArgs.template);
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue