Porównaj commity

...

4 Commity

Autor SHA1 Wiadomość Data
robinmoisson 8cf1ab5cd6
use salt from encrypted file when decrypting 2023-04-23 10:44:39 +02:00
robinmoisson e3cc2acda2
readme: clarify examples, add reco for multiple users 2023-04-23 10:33:18 +02:00
robinmoisson a256971e22
add funding 2023-04-23 10:15:10 +02:00
robinmoisson 5d99ce92ba
add support for decrypting in the CLI (closes #112) 2023-04-23 00:21:30 +02:00
9 zmienionych plików z 272 dodań i 95 usunięć

1
.gitignore vendored
Wyświetl plik

@ -5,3 +5,4 @@ node_modules
.env
encrypted/
!example/encrypted/
decrypted/

Wyświetl plik

@ -20,19 +20,20 @@ Staticrypt is available through npm as a CLI, install with
npm install staticrypt
```
You can then run it with `npx staticrypt ...`. You can also install globally with `npm install -g staticrypt` and then just call `staticrypt ...`.
You can then run it with `npx staticrypt ...`. You can also install globally with `npm install -g staticrypt` and then just call `staticrypt ...` from anywhere.
### Examples
> These examples will create a `.staticrypt.json` file in the current directory, see the FAQ as to why. You can prevent it by setting the `--config` flag to "false".
> These examples will create a `.staticrypt.json` file in the current directory, see [the FAQ](#why-does-staticrypt-create-a-config-file) as to why. You can prevent it by setting the `--config` flag to "false".
**Encrypt a file:** encrypt `test.html` and create a `encrypted/test.html` file (use `-d my_directory` to change the output directory):
```bash
staticrypt test.html -p MY_LONG_PASSWORD
# or do not include the password if you want to be prompted for it:
# this will prompt you for the password, which won't stay in your terminal command history
staticrypt test.html
# you can also pass the password as an argument
staticrypt test.html -p <long-password>
```
**Encrypt a file with the password in an environment variable:** set your long password in the `STATICRYPT_PASSWORD` environment variable ([`.env` files](https://www.npmjs.com/package/dotenv#usage) are supported):
@ -42,34 +43,47 @@ staticrypt test.html
staticrypt test.html
```
**Encrypt multiple files at once** and put them in a `encrypted/` directory:
**Encrypt multiple files at once** and put them in an `encrypted/` directory:
```bash
# this will encrypt test_A.html, test_B.html and all files in the test/ directory
staticrypt test_A.html test_B.html test/* -p MY_LONG_PASSWORD
# => encrypted files are in encrypted/test_A.html, encrypted/test_B.html, encrypted/test/...
# this will encrypt test_A.html and test_B.html
staticrypt test_A.html test_B.html
# => encrypted files are in encrypted/test_A.html and encrypted/test_B.html
# you can also use the -r flag to recursively encrypt all files in a directory
staticrypt dir_to_encrypt -p MY_LONG_PASSWORD -r
staticrypt dir_to_encrypt -r
# => encrypted files are in encrypted/dir_to_encrypt/...
# if you don't want to include the directory name in the output path, you can use dir_to_encrypt/* instead. `-r` will
# include potential subdirectories as well
staticrypt dir_to_encrypt/* -r
# => encrypted files are in encrypted/...
```
**Encrypt a file and get a shareable link containing the hashed password** - you can include your file URL or leave blank:
```bash
# you can also pass '--share' without specifying the URL to get the `#staticrypt_pwd=...`
staticrypt test.html -p MY_LONG_PASSWORD --share https://example.com/encrypted.html
staticrypt test.html --share https://example.com/encrypted.html
# => https://example.com/encrypted.html#staticrypt_pwd=5bfbf1343c7257cd7be23ecd74bb37fa2c76d041042654f358b6255baeab898f
```
**Decrypt files you encrypted earlier** with StatiCrypt straight from the CLI by including the `--decrypt` flag, so you can keep only the encrypted files. The `-r|--recursive` flag and output `-d|--directory` option work the same way as when encrypting (default name for the output directory is `decrypted`):
```bash
staticrypt encrypted/test.html --decrypt
# => decrypted file is in decrypted/test.html
```
**Pin the salt to use staticrypt in your CI in a build step** - if you want want the "Remember-me" or share features to work accross multiple pages or multiple successive deployment, the salt needs to stay the same ([see why](https://github.com/robinmoisson/staticrypt#why-does-staticrypt-create-a-config-file)). If you run StatiCrypt in a CI step, you can pin the salt in two ways:
```bash
# either commit the .staticrypt.json config file - you can generate a random salt and
# config file on your local machine:
# config file on your local machine with:
staticrypt --salt
# or hardcode the salt in the CI script command:
staticrypt test.html -p MY_LONG_PASSWORD --salt 12345678901234567890123456789012
# or hardcode the salt in the encryption command in the CI script:
staticrypt test.html --salt 12345678901234567890123456789012
```
### CLI Reference
@ -83,9 +97,12 @@ The password argument is optional if `STATICRYPT_PASSWORD` is set in the environ
--version Show version number [boolean]
-c, --config Path to the config file. Set to "false" to
disable.[string] [default: ".staticrypt.json"]
-d, --directory Name of the directory where the encrypted
files will be saved.
[string] [default: "encrypted/"]
-d, --directory Name of the directory where the generated
files will be saved. If the '--decrypt' flag
is set, default will be 'decrypted'.
[string] [default: "encrypted"]
--decrypt Include this flag to decrypt files instead of
encrypt. [boolean] [default: false]
-p, --password The password to encrypt your file with. Leave
empty to be prompted for it. If
STATICRYPT_PASSWORD is set in the env, we'll
@ -157,6 +174,21 @@ Yes! Just copy `lib/password_template.html`, modify it to suit your style and po
Be careful to not break the encrypting javascript part, the variables replaced by StatiCrypt are in this format: `/*[|variable|]*/0`. Don't leave out the `0` at the end, this weird syntax is to avoid conflict with other templating engines while still being read as valid JS to parsers so we can use auto-formatting on the template files.
### Can I support multiple users with different passwords?
At the moment you can only use one passsword per page (though there is a reflection on supporting decryption with multiple different passwords in [#158](https://github.com/robinmoisson/staticrypt/issues/158)). If you want to support multiple users so you can invalidate passwords individualy, the current recommended way is the following:
- Make a script that will encrypt your files with different passwords and different output folders
```
staticrypt test.html -p <john-password> -d john
...
```
- send each user the link to their folder with their password: `https://example.com/john/test.html`
In a way, the username input becomes the folder in the `https://example.com/<username>` URL, and the password input is the HTML form. You can then invalidate a single password by changing it in your script and running it again.
### Why doesn't StatiCrypt work in HTTP?
From version 3.x StatiCrypt only uses the browser WebCrypto API, which makes it more secure but is only available in HTTPS or on localhost. If you need to use it in HTTP, you can use version 2.x which offers the CryptoJS engine as an option, and will work everywhere.

Wyświetl plik

@ -1,4 +1,4 @@
const path = require("path");
const pathModule = require("path");
const fs = require("fs");
const readline = require("readline");
@ -6,7 +6,9 @@ const { generateRandomSalt, generateRandomString } = require("../lib/cryptoEngin
const { renderTemplate } = require("../lib/formater.js");
const Yargs = require("yargs");
const PASSWORD_TEMPLATE_DEFAULT_PATH = path.join(__dirname, "..", "lib", "password_template.html");
const PASSWORD_TEMPLATE_DEFAULT_PATH = pathModule.join(__dirname, "..", "lib", "password_template.html");
const OUTPUT_DIRECTORY_DEFAULT_PATH = "encrypted";
exports.OUTPUT_DIRECTORY_DEFAULT_PATH = OUTPUT_DIRECTORY_DEFAULT_PATH;
/**
* @param {string} message
@ -71,16 +73,19 @@ function prompt(question) {
});
}
async function getValidatedPassword(passwordArgument, isShortAllowed) {
const password = await getPassword(passwordArgument);
/**
* @param {string} password
* @param {boolean} isShortAllowed
* @returns {Promise<void>}
*/
async function validatePassword(password, isShortAllowed) {
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: " +
" and it's easy to try brute-forcing on public files, so we recommend using a longer one. Here's a generated one: " +
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] "
"\nDo you want to still want to use the shorter password? [y/N] "
);
if (!shouldUseShort.match(/^\s*(y|yes)\s*$/i)) {
@ -88,10 +93,8 @@ async function getValidatedPassword(passwordArgument, isShortAllowed) {
process.exit(0);
}
}
return password;
}
exports.getValidatedPassword = getValidatedPassword;
exports.validatePassword = validatePassword;
/**
* Get the config from the config file.
@ -137,6 +140,7 @@ async function getPassword(passwordArgument) {
// prompt the user for their password
return prompt("Enter your long, unusual password: ");
}
exports.getPassword = getPassword;
/**
* @param {string} filepath
@ -200,8 +204,8 @@ function getSalt(namedArgs, config) {
* @param {string} modulePath - path from staticrypt root directory
*/
function convertCommonJSToBrowserJS(modulePath) {
const rootDirectory = path.join(__dirname, "..");
const resolvedPath = path.join(rootDirectory, ...modulePath.split("/")) + ".js";
const rootDirectory = pathModule.join(__dirname, "..");
const resolvedPath = pathModule.join(rootDirectory, ...modulePath.split("/")) + ".js";
if (!fs.existsSync(resolvedPath)) {
exitWithError(`could not find module to convert at path "${resolvedPath}"`);
@ -262,20 +266,29 @@ function genFile(data, outputFilePath, templateFilePath) {
const renderedTemplate = renderTemplate(templateContents, data);
writeFile(outputFilePath, renderedTemplate);
}
exports.genFile = genFile;
/**
* @param {string} filePath
* @param {string} contents
*/
function writeFile(filePath, contents) {
// create output directory if it does not exist
const dirname = path.dirname(outputFilePath);
const dirname = pathModule.dirname(filePath);
if (!fs.existsSync(dirname)) {
fs.mkdirSync(dirname, { recursive: true });
}
try {
fs.writeFileSync(outputFilePath, renderedTemplate);
fs.writeFileSync(filePath, contents);
} catch (e) {
console.error(e);
exitWithError("could not generate output file");
exitWithError(`could not write file at path "${filePath}"`);
}
}
exports.genFile = genFile;
exports.writeFile = writeFile;
/**
* @param {string} templatePathParameter
@ -287,6 +300,28 @@ function isCustomPasswordTemplateDefault(templatePathParameter) {
}
exports.isCustomPasswordTemplateDefault = isCustomPasswordTemplateDefault;
/**
* @param {string} path
* @param {string} rootDirectory
* @param {(fullPath: string, rootDirectoryFromArgument: string) => void} callback
*/
function recursivelyApplyCallbackToFiles(callback, path, rootDirectory = "") {
const fullPath = pathModule.resolve(path);
const fullRootDirectory = rootDirectory || pathModule.dirname(fullPath);
if (fs.statSync(fullPath).isDirectory()) {
fs.readdirSync(fullPath).forEach((filePath) => {
const fullFilePath = `${fullPath}/${filePath}`;
recursivelyApplyCallbackToFiles(callback, fullFilePath, fullRootDirectory);
});
return;
}
callback(fullPath, fullRootDirectory);
}
exports.recursivelyApplyCallbackToFiles = recursivelyApplyCallbackToFiles;
function parseCommandLineArguments() {
return (
Yargs.usage("Usage: staticrypt <filename> [<filename> ...] [options]")
@ -299,8 +334,15 @@ function parseCommandLineArguments() {
.option("d", {
alias: "directory",
type: "string",
describe: "Name of the directory where the encrypted files will be saved.",
default: "encrypted/",
describe:
"Name of the directory where the generated files will be saved. If the '--decrypt' flag is " +
"set, default will be 'decrypted'.",
default: OUTPUT_DIRECTORY_DEFAULT_PATH,
})
.option("decrypt", {
type: "boolean",
describe: "Include this flag to decrypt files instead of encrypt.",
default: false,
})
.option("p", {
alias: "password",

Wyświetl plik

@ -12,22 +12,28 @@ if (nodeVersion[0] < 16) {
// parse .env file into process.env
require("dotenv").config();
const pathModule = require("path");
const fs = require("fs");
const cryptoEngine = require("../lib/cryptoEngine.js");
const codec = require("../lib/codec.js");
const { generateRandomSalt } = cryptoEngine;
const { encodeWithHashedPassword } = codec.init(cryptoEngine);
const { decode, encodeWithHashedPassword } = codec.init(cryptoEngine);
const {
parseCommandLineArguments,
OUTPUT_DIRECTORY_DEFAULT_PATH,
buildStaticryptJS,
isOptionSetByUser,
exitWithError,
genFile,
getFileContent,
getValidatedSalt,
getValidatedPassword,
getConfig,
getFileContent,
getPassword,
getValidatedSalt,
isOptionSetByUser,
parseCommandLineArguments,
recursivelyApplyCallbackToFiles,
validatePassword,
writeConfig,
writeFile,
} = require("./helpers.js");
// parse arguments
@ -67,23 +73,49 @@ async function runStatiCrypt() {
writeConfig(configPath, config);
}
process.exit(0);
return;
}
// get the salt & password
const salt = getValidatedSalt(namedArgs, config);
const password = await getValidatedPassword(namedArgs.password, namedArgs.short);
const password = await getPassword(namedArgs.password);
const hashedPassword = await cryptoEngine.hashPassword(password, salt);
// display the share link with the hashed password if the --share flag is set
if (hasShareFlag) {
await validatePassword(password, namedArgs.short);
const url = namedArgs.share || "";
const hashedPassword = await cryptoEngine.hashPassword(password, salt);
console.log(url + "#staticrypt_pwd=" + hashedPassword);
process.exit(0);
return;
}
// only process a directory if the --recursive flag is set
const directoriesInArguments = positionalArguments.filter((path) => fs.statSync(path).isDirectory());
if (directoriesInArguments.length > 0 && !namedArgs.recursive) {
exitWithError(
`'${directoriesInArguments[0].toString()}' is a directory. Use the -r|--recursive flag to process directories.`
);
}
// if asking for decryption, decrypt all the files
if (namedArgs.decrypt) {
const isOutputDirectoryDefault =
namedArgs.directory === OUTPUT_DIRECTORY_DEFAULT_PATH && !isOptionSetByUser("d", yargs);
const outputDirectory = isOutputDirectoryDefault ? "decrypted" : namedArgs.directory;
positionalArguments.forEach((path) => {
recursivelyApplyCallbackToFiles((fullPath, fullRootDirectory) => {
decodeAndGenerateFile(fullPath, fullRootDirectory, hashedPassword, outputDirectory);
}, path);
});
return;
}
await validatePassword(password, namedArgs.short);
// write salt to config file
if (config.salt !== salt) {
config.salt = salt;
@ -105,35 +137,56 @@ async function runStatiCrypt() {
template_color_secondary: namedArgs.templateColorSecondary,
};
const hashedPassword = await cryptoEngine.hashPassword(password, salt);
positionalArguments.forEach((path) =>
encodeAndGenerateFile(path.toString(), hashedPassword, salt, baseTemplateData, isRememberEnabled, namedArgs)
);
// encode all the files
positionalArguments.forEach((path) => {
recursivelyApplyCallbackToFiles((fullPath, fullRootDirectory) => {
encodeAndGenerateFile(
fullPath,
fullRootDirectory,
hashedPassword,
salt,
baseTemplateData,
isRememberEnabled,
namedArgs
);
}, path);
});
}
async function encodeAndGenerateFile(path, hashedPassword, salt, baseTemplateData, isRememberEnabled, namedArgs) {
// if the path is a directory, get into it and process all files
if (fs.statSync(path).isDirectory()) {
if (!namedArgs.recursive) {
console.log(
"ERROR: The path '" +
path +
"' is a directory. Use the -r|--recursive flag to process all files in the directory."
);
async function decodeAndGenerateFile(path, rootDirectoryFromArguments, hashedPassword, outputDirectory) {
// get the file content
const encryptedFileContent = getFileContent(path);
// just return instead of exiting the process, that way all other files can be processed
return;
}
// extract the cipher text from the encrypted file
const cipherTextMatch = encryptedFileContent.match(/"staticryptEncryptedMsgUniqueVariableName":\s*"([^"]+)"/);
const saltMatch = encryptedFileContent.match(/"staticryptSaltUniqueVariableName":\s*"([^"]+)"/);
fs.readdirSync(path).forEach((filePath) => {
const fullPath = `${path}/${filePath}`;
encodeAndGenerateFile(fullPath, hashedPassword, salt, baseTemplateData, isRememberEnabled, namedArgs);
});
return;
if (!cipherTextMatch || !saltMatch) {
return console.log(`ERROR: could not extract cipher text or salt from ${path}`);
}
// decrypt input
const { success, decoded } = await decode(cipherTextMatch[1], hashedPassword, saltMatch[1]);
if (!success) {
return console.log(`ERROR: could not decrypt ${path}`);
}
const relativePath = pathModule.relative(rootDirectoryFromArguments, path);
const outputFilepath = outputDirectory + "/" + relativePath;
writeFile(outputFilepath, decoded);
}
async function encodeAndGenerateFile(
path,
rootDirectoryFromArguments,
hashedPassword,
salt,
baseTemplateData,
isRememberEnabled,
namedArgs
) {
// get the file content
const contents = getFileContent(path);
@ -141,17 +194,19 @@ async function encodeAndGenerateFile(path, hashedPassword, salt, baseTemplateDat
const encryptedMsg = await encodeWithHashedPassword(contents, hashedPassword);
const staticryptConfig = {
encryptedMsg,
staticryptEncryptedMsgUniqueVariableName: encryptedMsg,
isRememberEnabled,
rememberDurationInDays: namedArgs.remember,
salt,
staticryptSaltUniqueVariableName: salt,
};
const templateData = {
...baseTemplateData,
staticrypt_config: staticryptConfig,
};
const outputFilepath = namedArgs.directory.replace(/\/+$/, "") + "/" + path;
// remove the base path so that the actual output path is relative to the base path
const relativePath = pathModule.relative(rootDirectoryFromArguments, path);
const outputFilepath = namedArgs.directory + "/" + relativePath;
genFile(templateData, outputFilepath, namedArgs.template);
}

Wyświetl plik

@ -553,10 +553,10 @@ const decode = codec.init(cryptoEngine).decode;
* Initialize the staticrypt module, that exposes functions callbable by the password_template.
*
* @param {{
* encryptedMsg: string,
* staticryptEncryptedMsgUniqueVariableName: string,
* isRememberEnabled: boolean,
* rememberDurationInDays: number,
* salt: string,
* staticryptSaltUniqueVariableName: string,
* }} staticryptConfig - object of data that is stored on the password_template at encryption time.
*
* @param {{
@ -576,10 +576,14 @@ function init(staticryptConfig, templateConfig) {
* @returns {Promise<boolean>}
*/
async function decryptAndReplaceHtml(hashedPassword) {
const { encryptedMsg, salt } = staticryptConfig;
const { staticryptEncryptedMsgUniqueVariableName, staticryptSaltUniqueVariableName } = staticryptConfig;
const { replaceHtmlCallback } = templateConfig;
const result = await decode(encryptedMsg, hashedPassword, salt);
const result = await decode(
staticryptEncryptedMsgUniqueVariableName,
hashedPassword,
staticryptSaltUniqueVariableName
);
if (!result.success) {
return false;
}
@ -606,11 +610,11 @@ function init(staticryptConfig, templateConfig) {
* expose more information in the future we can do it without breaking the password_template
*/
async function handleDecryptionOfPage(password, isRememberChecked) {
const { isRememberEnabled, rememberDurationInDays, salt } = staticryptConfig;
const { isRememberEnabled, rememberDurationInDays, staticryptSaltUniqueVariableName } = staticryptConfig;
const { rememberExpirationKey, rememberPassphraseKey } = templateConfig;
// decrypt and replace the whole page
const hashedPassword = await cryptoEngine.hashPassword(password, salt);
const hashedPassword = await cryptoEngine.hashPassword(password, staticryptSaltUniqueVariableName);
const isDecryptionSuccessful = await decryptAndReplaceHtml(hashedPassword);
@ -764,7 +768,7 @@ exports.init = init;
})());
const templateError = "Bad password!",
isRememberEnabled = true,
staticryptConfig = {"encryptedMsg":"bf0f821fe4fdab54ffde29fd6d812fdf7dd423a0e4e36369c41864d369b71aa6a826caf47e563ba5e4bdfc2b55ea323c5d9fabc6ece3e99cdacc30afd560ec57b6bdda0beef1b2b220e934f214202134e8eb284a5a58f94418c970ca2172622b9286eb5931fff69e345d737c00832ecfbb77057a4e814dd633ab1ef294514d28ef7cb047bb541000b12b8f4c15851fa8ca1e6cd0cbee64c67b4467a46e2bc154896bb4deed9987e222f0c280c8d766ea16769515f9d337592e6807dfa07534ef","isRememberEnabled":true,"rememberDurationInDays":0,"salt":"b93bbaf35459951c47721d1f3eaeb5b9"};
staticryptConfig = {"staticryptEncryptedMsgUniqueVariableName":"85cf880a1573985224adbac66ceeba6c026484ad101ffabc6bc0d874a1e4eb75ddee7d265055e80d8e87369a694f873ff044933e1b5d33c46a636e2fdc4f2d108f0dd36252aba4c2e0f71a8e9ed2027839a6ea46a3e3a5f8e0d205046966c3bd1eac8b78e5ba3a5d9015eea2e0d83629d19c47e0b2311966aa7d3ac2fb8b592276484fea27cd90e5e85e65c11abd483a3d938b738efb02d290e94c9d249844f157667be667ed018f0d0e7702f141ef713c8cc2b472e25922d70cb75955a4182b","isRememberEnabled":true,"rememberDurationInDays":0,"staticryptSaltUniqueVariableName":"b93bbaf35459951c47721d1f3eaeb5b9"};
// you can edit these values to customize some of the behavior of StatiCrypt
const templateConfig = {

Wyświetl plik

@ -1044,10 +1044,10 @@ const decode = codec.init(cryptoEngine).decode;
* Initialize the staticrypt module, that exposes functions callbable by the password_template.
*
* @param {{
* encryptedMsg: string,
* staticryptEncryptedMsgUniqueVariableName: string,
* isRememberEnabled: boolean,
* rememberDurationInDays: number,
* salt: string,
* staticryptSaltUniqueVariableName: string,
* }} staticryptConfig - object of data that is stored on the password_template at encryption time.
*
* @param {{
@ -1067,10 +1067,14 @@ function init(staticryptConfig, templateConfig) {
* @returns {Promise<boolean>}
*/
async function decryptAndReplaceHtml(hashedPassword) {
const { encryptedMsg, salt } = staticryptConfig;
const { staticryptEncryptedMsgUniqueVariableName, staticryptSaltUniqueVariableName } = staticryptConfig;
const { replaceHtmlCallback } = templateConfig;
const result = await decode(encryptedMsg, hashedPassword, salt);
const result = await decode(
staticryptEncryptedMsgUniqueVariableName,
hashedPassword,
staticryptSaltUniqueVariableName
);
if (!result.success) {
return false;
}
@ -1097,11 +1101,11 @@ function init(staticryptConfig, templateConfig) {
* expose more information in the future we can do it without breaking the password_template
*/
async function handleDecryptionOfPage(password, isRememberChecked) {
const { isRememberEnabled, rememberDurationInDays, salt } = staticryptConfig;
const { isRememberEnabled, rememberDurationInDays, staticryptSaltUniqueVariableName } = staticryptConfig;
const { rememberExpirationKey, rememberPassphraseKey } = templateConfig;
// decrypt and replace the whole page
const hashedPassword = await cryptoEngine.hashPassword(password, salt);
const hashedPassword = await cryptoEngine.hashPassword(password, staticryptSaltUniqueVariableName);
const isDecryptionSuccessful = await decryptAndReplaceHtml(hashedPassword);

Wyświetl plik

@ -6,10 +6,10 @@ const decode = codec.init(cryptoEngine).decode;
* Initialize the staticrypt module, that exposes functions callbable by the password_template.
*
* @param {{
* encryptedMsg: string,
* staticryptEncryptedMsgUniqueVariableName: string,
* isRememberEnabled: boolean,
* rememberDurationInDays: number,
* salt: string,
* staticryptSaltUniqueVariableName: string,
* }} staticryptConfig - object of data that is stored on the password_template at encryption time.
*
* @param {{
@ -29,10 +29,14 @@ function init(staticryptConfig, templateConfig) {
* @returns {Promise<boolean>}
*/
async function decryptAndReplaceHtml(hashedPassword) {
const { encryptedMsg, salt } = staticryptConfig;
const { staticryptEncryptedMsgUniqueVariableName, staticryptSaltUniqueVariableName } = staticryptConfig;
const { replaceHtmlCallback } = templateConfig;
const result = await decode(encryptedMsg, hashedPassword, salt);
const result = await decode(
staticryptEncryptedMsgUniqueVariableName,
hashedPassword,
staticryptSaltUniqueVariableName
);
if (!result.success) {
return false;
}
@ -59,11 +63,11 @@ function init(staticryptConfig, templateConfig) {
* expose more information in the future we can do it without breaking the password_template
*/
async function handleDecryptionOfPage(password, isRememberChecked) {
const { isRememberEnabled, rememberDurationInDays, salt } = staticryptConfig;
const { isRememberEnabled, rememberDurationInDays, staticryptSaltUniqueVariableName } = staticryptConfig;
const { rememberExpirationKey, rememberPassphraseKey } = templateConfig;
// decrypt and replace the whole page
const hashedPassword = await cryptoEngine.hashPassword(password, salt);
const hashedPassword = await cryptoEngine.hashPassword(password, staticryptSaltUniqueVariableName);
const isDecryptionSuccessful = await decryptAndReplaceHtml(hashedPassword);

32
package-lock.json wygenerowano
Wyświetl plik

@ -1,12 +1,12 @@
{
"name": "staticrypt",
"version": "3.2.0",
"version": "3.3.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "staticrypt",
"version": "3.2.0",
"version": "3.3.0",
"license": "MIT",
"dependencies": {
"dotenv": "^16.0.3",
@ -15,8 +15,15 @@
"bin": {
"staticrypt": "cli/index.js"
},
"devDependencies": {
"prettier": "^2.8.7"
},
"engines": {
"node": ">=16.0.0"
},
"funding": {
"type": "github",
"url": "https://github.com/robinmoisson/staticrypt?sponsor=1"
}
},
"node_modules/ansi-regex": {
@ -104,6 +111,21 @@
"node": ">=8"
}
},
"node_modules/prettier": {
"version": "2.8.7",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.7.tgz",
"integrity": "sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==",
"dev": true,
"bin": {
"prettier": "bin-prettier.js"
},
"engines": {
"node": ">=10.13.0"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
@ -248,6 +270,12 @@
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
},
"prettier": {
"version": "2.8.7",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.7.tgz",
"integrity": "sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==",
"dev": true
},
"require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",

Wyświetl plik

@ -1,6 +1,6 @@
{
"name": "staticrypt",
"version": "3.2.0",
"version": "3.3.0",
"description": "Based on the [crypto-js](https://github.com/brix/crypto-js) library, StatiCrypt uses AES-256 to encrypt your input with your long password and put it in a HTML file with a password prompt that can decrypted in-browser (client side).",
"main": "index.js",
"files": [
@ -17,6 +17,10 @@
"engines": {
"node": ">=16.0.0"
},
"funding": {
"type": "github",
"url": "https://github.com/robinmoisson/staticrypt?sponsor=1"
},
"author": "Robin Moisson (https://github.com/robinmoisson)",
"contributors": [
"Aaron Coplan (https://github.com/AaronCoplan)",
@ -43,5 +47,8 @@
"bugs": {
"url": "https://github.com/robinmoisson/staticrypt/issues"
},
"homepage": "https://github.com/robinmoisson/staticrypt"
"homepage": "https://github.com/robinmoisson/staticrypt",
"devDependencies": {
"prettier": "^2.8.7"
}
}