rename passphrase into password

pull/177/head
robinmoisson 2023-04-19 09:57:12 +02:00
rodzic 4696a24324
commit 5ef120be53
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 9419716500078583
9 zmienionych plików z 260 dodań i 260 usunięć

Wyświetl plik

@ -15,7 +15,7 @@ require('dotenv').config();
const cryptoEngine = require("../lib/cryptoEngine.js"); const cryptoEngine = require("../lib/cryptoEngine.js");
const codec = require("../lib/codec.js"); const codec = require("../lib/codec.js");
const { generateRandomSalt } = cryptoEngine; const { generateRandomSalt } = cryptoEngine;
const { encodeWithHashedPassphrase } = codec.init(cryptoEngine); const { encodeWithHashedPassword } = codec.init(cryptoEngine);
const { parseCommandLineArguments, buildStaticryptJS, isOptionSetByUser, genFile, getFileContent, const { parseCommandLineArguments, buildStaticryptJS, isOptionSetByUser, genFile, getFileContent,
getValidatedSalt, getValidatedSalt,
getValidatedPassword, getConfig, writeConfig getValidatedPassword, getConfig, writeConfig
@ -69,7 +69,7 @@ async function runStatiCrypt() {
if (hasShareFlag) { if (hasShareFlag) {
const url = namedArgs.share || ""; const url = namedArgs.share || "";
const hashedPassword = await cryptoEngine.hashPassphrase(password, salt); const hashedPassword = await cryptoEngine.hashPassword(password, salt);
console.log(url + "#staticrypt_pwd=" + hashedPassword); console.log(url + "#staticrypt_pwd=" + hashedPassword);
process.exit(0); process.exit(0);
@ -96,7 +96,7 @@ async function runStatiCrypt() {
template_color_secondary: namedArgs.templateColorSecondary, template_color_secondary: namedArgs.templateColorSecondary,
}; };
const hashedPassword = await cryptoEngine.hashPassphrase(password, salt); const hashedPassword = await cryptoEngine.hashPassword(password, salt);
for (const positionalArgument of positionalArguments) { for (const positionalArgument of positionalArguments) {
const inputFilepath = positionalArgument.toString(); const inputFilepath = positionalArgument.toString();
@ -105,7 +105,7 @@ async function runStatiCrypt() {
const contents = getFileContent(inputFilepath); const contents = getFileContent(inputFilepath);
// encrypt input // encrypt input
const encryptedMsg = await encodeWithHashedPassphrase(contents, hashedPassword); const encryptedMsg = await encodeWithHashedPassword(contents, hashedPassword);
const staticryptConfig = { const staticryptConfig = {
encryptedMsg, encryptedMsg,

Wyświetl plik

@ -251,14 +251,14 @@ const UTF8Encoder = {
/** /**
* Salt and encrypt a msg with a password. * Salt and encrypt a msg with a password.
*/ */
async function encrypt(msg, hashedPassphrase) { async function encrypt(msg, hashedPassword) {
// Must be 16 bytes, unpredictable, and preferably cryptographically random. However, it need not be secret. // Must be 16 bytes, unpredictable, and preferably cryptographically random. However, it need not be secret.
// https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/encrypt#parameters // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/encrypt#parameters
const iv = crypto.getRandomValues(new Uint8Array(IV_BITS / 8)); const iv = crypto.getRandomValues(new Uint8Array(IV_BITS / 8));
const key = await subtle.importKey( const key = await subtle.importKey(
"raw", "raw",
HexEncoder.parse(hashedPassphrase), HexEncoder.parse(hashedPassword),
ENCRYPTION_ALGO, ENCRYPTION_ALGO,
false, false,
["encrypt"] ["encrypt"]
@ -282,17 +282,17 @@ exports.encrypt = encrypt;
* Decrypt a salted msg using a password. * Decrypt a salted msg using a password.
* *
* @param {string} encryptedMsg * @param {string} encryptedMsg
* @param {string} hashedPassphrase * @param {string} hashedPassword
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
async function decrypt(encryptedMsg, hashedPassphrase) { async function decrypt(encryptedMsg, hashedPassword) {
const ivLength = IV_BITS / HEX_BITS; const ivLength = IV_BITS / HEX_BITS;
const iv = HexEncoder.parse(encryptedMsg.substring(0, ivLength)); const iv = HexEncoder.parse(encryptedMsg.substring(0, ivLength));
const encrypted = encryptedMsg.substring(ivLength); const encrypted = encryptedMsg.substring(ivLength);
const key = await subtle.importKey( const key = await subtle.importKey(
"raw", "raw",
HexEncoder.parse(hashedPassphrase), HexEncoder.parse(hashedPassword),
ENCRYPTION_ALGO, ENCRYPTION_ALGO,
false, false,
["decrypt"] ["decrypt"]
@ -312,33 +312,33 @@ async function decrypt(encryptedMsg, hashedPassphrase) {
exports.decrypt = decrypt; exports.decrypt = decrypt;
/** /**
* Salt and hash the passphrase so it can be stored in localStorage without opening a password reuse vulnerability. * Salt and hash the password so it can be stored in localStorage without opening a password reuse vulnerability.
* *
* @param {string} passphrase * @param {string} password
* @param {string} salt * @param {string} salt
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
async function hashPassphrase(passphrase, salt) { async function hashPassword(password, salt) {
// we hash the passphrase in multiple steps, each adding more iterations. This is because we used to allow less // we hash the password in multiple steps, each adding more iterations. This is because we used to allow less
// iterations, so for backward compatibility reasons, we need to support going from that to more iterations. // iterations, so for backward compatibility reasons, we need to support going from that to more iterations.
let hashedPassphrase = await hashLegacyRound(passphrase, salt); let hashedPassword = await hashLegacyRound(password, salt);
hashedPassphrase = await hashSecondRound(hashedPassphrase, salt); hashedPassword = await hashSecondRound(hashedPassword, salt);
return hashThirdRound(hashedPassphrase, salt); return hashThirdRound(hashedPassword, salt);
} }
exports.hashPassphrase = hashPassphrase; exports.hashPassword = hashPassword;
/** /**
* This hashes the passphrase with 1k iterations. This is a low number, we need this function to support backwards * This hashes the password with 1k iterations. This is a low number, we need this function to support backwards
* compatibility. * compatibility.
* *
* @param {string} passphrase * @param {string} password
* @param {string} salt * @param {string} salt
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
function hashLegacyRound(passphrase, salt) { function hashLegacyRound(password, salt) {
return pbkdf2(passphrase, salt, 1000, "SHA-1"); return pbkdf2(password, salt, 1000, "SHA-1");
} }
exports.hashLegacyRound = hashLegacyRound; exports.hashLegacyRound = hashLegacyRound;
@ -346,12 +346,12 @@ exports.hashLegacyRound = hashLegacyRound;
* Add a second round of iterations. This is because we used to use 1k, so for backwards compatibility with * Add a second round of iterations. This is because we used to use 1k, so for backwards compatibility with
* remember-me/autodecrypt links, we need to support going from that to more iterations. * remember-me/autodecrypt links, we need to support going from that to more iterations.
* *
* @param hashedPassphrase * @param hashedPassword
* @param salt * @param salt
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
function hashSecondRound(hashedPassphrase, salt) { function hashSecondRound(hashedPassword, salt) {
return pbkdf2(hashedPassphrase, salt, 14000, "SHA-256"); return pbkdf2(hashedPassword, salt, 14000, "SHA-256");
} }
exports.hashSecondRound = hashSecondRound; exports.hashSecondRound = hashSecondRound;
@ -359,28 +359,28 @@ exports.hashSecondRound = hashSecondRound;
* Add a third round of iterations to bring total number to 600k. This is because we used to use 1k, then 15k, so for * Add a third round of iterations to bring total number to 600k. This is because we used to use 1k, then 15k, so for
* backwards compatibility with remember-me/autodecrypt links, we need to support going from that to more iterations. * backwards compatibility with remember-me/autodecrypt links, we need to support going from that to more iterations.
* *
* @param hashedPassphrase * @param hashedPassword
* @param salt * @param salt
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
function hashThirdRound(hashedPassphrase, salt) { function hashThirdRound(hashedPassword, salt) {
return pbkdf2(hashedPassphrase, salt, 585000, "SHA-256"); return pbkdf2(hashedPassword, salt, 585000, "SHA-256");
} }
exports.hashThirdRound = hashThirdRound; exports.hashThirdRound = hashThirdRound;
/** /**
* Salt and hash the passphrase so it can be stored in localStorage without opening a password reuse vulnerability. * Salt and hash the password so it can be stored in localStorage without opening a password reuse vulnerability.
* *
* @param {string} passphrase * @param {string} password
* @param {string} salt * @param {string} salt
* @param {int} iterations * @param {int} iterations
* @param {string} hashAlgorithm * @param {string} hashAlgorithm
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
async function pbkdf2(passphrase, salt, iterations, hashAlgorithm) { async function pbkdf2(password, salt, iterations, hashAlgorithm) {
const key = await subtle.importKey( const key = await subtle.importKey(
"raw", "raw",
UTF8Encoder.parse(passphrase), UTF8Encoder.parse(password),
"PBKDF2", "PBKDF2",
false, false,
["deriveBits"] ["deriveBits"]
@ -407,10 +407,10 @@ function generateRandomSalt() {
} }
exports.generateRandomSalt = generateRandomSalt; exports.generateRandomSalt = generateRandomSalt;
async function signMessage(hashedPassphrase, message) { async function signMessage(hashedPassword, message) {
const key = await subtle.importKey( const key = await subtle.importKey(
"raw", "raw",
HexEncoder.parse(hashedPassphrase), HexEncoder.parse(hashedPassword),
{ {
name: "HMAC", name: "HMAC",
hash: "SHA-256", hash: "SHA-256",
@ -486,13 +486,13 @@ function init(cryptoEngine) {
* @returns {string} The encoded text * @returns {string} The encoded text
*/ */
async function encode(msg, password, salt) { async function encode(msg, password, salt) {
const hashedPassphrase = await cryptoEngine.hashPassphrase(password, salt); const hashedPassword = await cryptoEngine.hashPassword(password, salt);
const encrypted = await cryptoEngine.encrypt(msg, hashedPassphrase); const encrypted = await cryptoEngine.encrypt(msg, hashedPassword);
// we use the hashed password in the HMAC because this is effectively what will be used a password (so we can store // we use the hashed password in the HMAC because this is effectively what will be used a password (so we can store
// it in localStorage safely, we don't use the clear text password) // it in localStorage safely, we don't use the clear text password)
const hmac = await cryptoEngine.signMessage(hashedPassphrase, encrypted); const hmac = await cryptoEngine.signMessage(hashedPassword, encrypted);
return hmac + encrypted; return hmac + encrypted;
} }
@ -503,58 +503,58 @@ function init(cryptoEngine) {
* we don't need to hash the password multiple times. * we don't need to hash the password multiple times.
* *
* @param {string} msg * @param {string} msg
* @param {string} hashedPassphrase * @param {string} hashedPassword
* *
* @returns {string} The encoded text * @returns {string} The encoded text
*/ */
async function encodeWithHashedPassphrase(msg, hashedPassphrase) { async function encodeWithHashedPassword(msg, hashedPassword) {
const encrypted = await cryptoEngine.encrypt(msg, hashedPassphrase); const encrypted = await cryptoEngine.encrypt(msg, hashedPassword);
// we use the hashed password in the HMAC because this is effectively what will be used a password (so we can store // we use the hashed password in the HMAC because this is effectively what will be used a password (so we can store
// it in localStorage safely, we don't use the clear text password) // it in localStorage safely, we don't use the clear text password)
const hmac = await cryptoEngine.signMessage(hashedPassphrase, encrypted); const hmac = await cryptoEngine.signMessage(hashedPassword, encrypted);
return hmac + encrypted; return hmac + encrypted;
} }
exports.encodeWithHashedPassphrase = encodeWithHashedPassphrase; exports.encodeWithHashedPassword = encodeWithHashedPassword;
/** /**
* Top-level function for decoding a message. * Top-level function for decoding a message.
* Includes signature check and decryption. * Includes signature check and decryption.
* *
* @param {string} signedMsg * @param {string} signedMsg
* @param {string} hashedPassphrase * @param {string} hashedPassword
* @param {string} salt * @param {string} salt
* @param {int} backwardCompatibleAttempt * @param {int} backwardCompatibleAttempt
* @param {string} originalPassphrase * @param {string} originalPassword
* *
* @returns {Object} {success: true, decoded: string} | {success: false, message: string} * @returns {Object} {success: true, decoded: string} | {success: false, message: string}
*/ */
async function decode( async function decode(
signedMsg, signedMsg,
hashedPassphrase, hashedPassword,
salt, salt,
backwardCompatibleAttempt = 0, backwardCompatibleAttempt = 0,
originalPassphrase = '' originalPassword = ''
) { ) {
const encryptedHMAC = signedMsg.substring(0, 64); const encryptedHMAC = signedMsg.substring(0, 64);
const encryptedMsg = signedMsg.substring(64); const encryptedMsg = signedMsg.substring(64);
const decryptedHMAC = await cryptoEngine.signMessage(hashedPassphrase, encryptedMsg); const decryptedHMAC = await cryptoEngine.signMessage(hashedPassword, encryptedMsg);
if (decryptedHMAC !== encryptedHMAC) { if (decryptedHMAC !== encryptedHMAC) {
// we have been raising the number of iterations in the hashing algorithm multiple times, so to support the old // we have been raising the number of iterations in the hashing algorithm multiple times, so to support the old
// remember-me/autodecrypt links we need to try bringing the old hashes up to speed. // remember-me/autodecrypt links we need to try bringing the old hashes up to speed.
originalPassphrase = originalPassphrase || hashedPassphrase; originalPassword = originalPassword || hashedPassword;
if (backwardCompatibleAttempt === 0) { if (backwardCompatibleAttempt === 0) {
const updatedHashedPassphrase = await cryptoEngine.hashThirdRound(originalPassphrase, salt); const updatedHashedPassword = await cryptoEngine.hashThirdRound(originalPassword, salt);
return decode(signedMsg, updatedHashedPassphrase, salt, backwardCompatibleAttempt + 1, originalPassphrase); return decode(signedMsg, updatedHashedPassword, salt, backwardCompatibleAttempt + 1, originalPassword);
} }
if (backwardCompatibleAttempt === 1) { if (backwardCompatibleAttempt === 1) {
let updatedHashedPassphrase = await cryptoEngine.hashSecondRound(originalPassphrase, salt); let updatedHashedPassword = await cryptoEngine.hashSecondRound(originalPassword, salt);
updatedHashedPassphrase = await cryptoEngine.hashThirdRound(updatedHashedPassphrase, salt); updatedHashedPassword = await cryptoEngine.hashThirdRound(updatedHashedPassword, salt);
return decode(signedMsg, updatedHashedPassphrase, salt, backwardCompatibleAttempt + 1, originalPassphrase); return decode(signedMsg, updatedHashedPassword, salt, backwardCompatibleAttempt + 1, originalPassword);
} }
return { success: false, message: "Signature mismatch" }; return { success: false, message: "Signature mismatch" };
@ -562,7 +562,7 @@ function init(cryptoEngine) {
return { return {
success: true, success: true,
decoded: await cryptoEngine.decrypt(encryptedMsg, hashedPassphrase), decoded: await cryptoEngine.decrypt(encryptedMsg, hashedPassword),
}; };
} }
exports.decode = decode; exports.decode = decode;
@ -599,14 +599,14 @@ function init(staticryptConfig, templateConfig) {
/** /**
* Decrypt our encrypted page, replace the whole HTML. * Decrypt our encrypted page, replace the whole HTML.
* *
* @param {string} hashedPassphrase * @param {string} hashedPassword
* @returns {Promise<boolean>} * @returns {Promise<boolean>}
*/ */
async function decryptAndReplaceHtml(hashedPassphrase) { async function decryptAndReplaceHtml(hashedPassword) {
const { encryptedMsg, salt } = staticryptConfig; const { encryptedMsg, salt } = staticryptConfig;
const { replaceHtmlCallback } = templateConfig; const { replaceHtmlCallback } = templateConfig;
const result = await decode(encryptedMsg, hashedPassphrase, salt); const result = await decode(encryptedMsg, hashedPassword, salt);
if (!result.success) { if (!result.success) {
return false; return false;
} }
@ -637,7 +637,7 @@ function init(staticryptConfig, templateConfig) {
const { rememberExpirationKey, rememberPassphraseKey } = templateConfig; const { rememberExpirationKey, rememberPassphraseKey } = templateConfig;
// decrypt and replace the whole page // decrypt and replace the whole page
const hashedPassword = await cryptoEngine.hashPassphrase(password, salt); const hashedPassword = await cryptoEngine.hashPassword(password, salt);
const isDecryptionSuccessful = await decryptAndReplaceHtml(hashedPassword); const isDecryptionSuccessful = await decryptAndReplaceHtml(hashedPassword);
@ -744,11 +744,11 @@ function init(staticryptConfig, templateConfig) {
} }
} }
const hashedPassphrase = localStorage.getItem(rememberPassphraseKey); const hashedPassword = localStorage.getItem(rememberPassphraseKey);
if (hashedPassphrase) { if (hashedPassword) {
// try to decrypt // try to decrypt
const isDecryptionSuccessful = await decryptAndReplaceHtml(hashedPassphrase); const isDecryptionSuccessful = await decryptAndReplaceHtml(hashedPassword);
// if the decryption is unsuccessful the password might be wrong - silently clear the saved data and let // if the decryption is unsuccessful the password might be wrong - silently clear the saved data and let
// the user fill the password form again // the user fill the password form again
@ -768,16 +768,16 @@ function init(staticryptConfig, templateConfig) {
// get the password from the query param // get the password from the query param
const queryParams = new URLSearchParams(window.location.search); const queryParams = new URLSearchParams(window.location.search);
const hashedPassphraseQuery = queryParams.get(passwordKey); const hashedPasswordQuery = queryParams.get(passwordKey);
// get the password from the url fragment // get the password from the url fragment
const hashRegexMatch = window.location.hash.substring(1).match(new RegExp(passwordKey + "=(.*)")); const hashRegexMatch = window.location.hash.substring(1).match(new RegExp(passwordKey + "=(.*)"));
const hashedPassphraseFragment = hashRegexMatch ? hashRegexMatch[1] : null; const hashedPasswordFragment = hashRegexMatch ? hashRegexMatch[1] : null;
const hashedPassphrase = hashedPassphraseFragment || hashedPassphraseQuery; const hashedPassword = hashedPasswordFragment || hashedPasswordQuery;
if (hashedPassphrase) { if (hashedPassword) {
return decryptAndReplaceHtml(hashedPassphrase); return decryptAndReplaceHtml(hashedPassword);
} }
return false; return false;
@ -790,7 +790,7 @@ exports.init = init;
})()) })())
const templateError = 'Bad password!', const templateError = 'Bad password!',
isRememberEnabled = true, isRememberEnabled = true,
staticryptConfig = {"encryptedMsg":"8ad22b42e255e1467bbd5369c84ae7420583384946876422f9450a5ab7fb3eaf33f5b73b1980988ef451c513871bb24582fabe01c8a5d0bde2a0580d564bf9c232cffc7fca5169005c024de005a25f479c172a65f6554405874082906b4a3be1ca7c0118728b25cd3ae915277e19f574c4f794affeffb2a1c3e923ea12fd83f5005a1c1b9606d36448082bd0f8ef70f8cc99f5205075e702b2f2b795c9150e20f2de2c6c86631c2d59ebbe2543c8ec13e450b21bbefdc2f2cb219190a0510538","isRememberEnabled":true,"rememberDurationInDays":0,"salt":"b93bbaf35459951c47721d1f3eaeb5b9"}; staticryptConfig = {"encryptedMsg":"eaad887f76cba7e862577a8d69c79acfa062d4a1af097faf1fa2d5c56ca2383ea696b3a2f62c6507bebe2f6497d84bcbf7f989136c9ea7f6a95191c1da90a92c330615d9643f382beb9bc3eecaef67a1e2243913e3bd7165820eef4518ac95287e12c1af22bcdaf6190167da3215800ca6809cf5b011847b4618f36e53b40b39d77d174b52a5c8ffaf47f9309478f0d3739f29d606ebe5a2a2334bf6c0f06ed53cdf7f4d703a4a97a41e47b34c50ac4103b7c4a8f0ba92f31010fe097f57bf1c","isRememberEnabled":true,"rememberDurationInDays":0,"salt":"b93bbaf35459951c47721d1f3eaeb5b9"};
// you can edit these values to customize some of the behavior of StatiCrypt // you can edit these values to customize some of the behavior of StatiCrypt
const templateConfig = { const templateConfig = {
@ -826,10 +826,10 @@ exports.init = init;
document.getElementById('staticrypt-form').addEventListener('submit', async function (e) { document.getElementById('staticrypt-form').addEventListener('submit', async function (e) {
e.preventDefault(); e.preventDefault();
const passphrase = document.getElementById('staticrypt-password').value, const password = document.getElementById('staticrypt-password').value,
isRememberChecked = document.getElementById('staticrypt-remember').checked; isRememberChecked = document.getElementById('staticrypt-remember').checked;
const { isSuccessful } = await staticrypt.handleDecryptionOfPage(passphrase, isRememberChecked); const { isSuccessful } = await staticrypt.handleDecryptionOfPage(password, isRememberChecked);
if (!isSuccessful) { if (!isSuccessful) {
alert(templateError); alert(templateError);

Wyświetl plik

@ -96,8 +96,8 @@
<div class="col-xs-12"> <div class="col-xs-12">
<form id="encrypt_form"> <form id="encrypt_form">
<div class="form-group"> <div class="form-group">
<label for="passphrase">Password</label> <label for="password">Password</label>
<input type="password" class="form-control" id="passphrase" <input type="password" class="form-control" id="password"
placeholder="Password (choose a long one!)"> placeholder="Password (choose a long one!)">
</div> </div>
@ -137,9 +137,9 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="template_placeholder">Passphrase input placeholder</label> <label for="template_placeholder">Password input placeholder</label>
<input type="text" class="form-control" id="template_placeholder" <input type="text" class="form-control" id="template_placeholder"
placeholder="Default: 'Passphrase'"> placeholder="Default: 'Password'">
</div> </div>
<div class="form-group"> <div class="form-group">
@ -155,7 +155,7 @@
step="any" step="any"
placeholder="Default: 0 (no expiration)"> placeholder="Default: 0 (no expiration)">
<small class="form-text text-muted"> <small class="form-text text-muted">
After this many days, the user will have to enter the passphrase again. Leave empty or set After this many days, the user will have to enter the password again. Leave empty or set
to 0 for no expiration. to 0 for no expiration.
</small> </small>
</div> </div>
@ -166,7 +166,7 @@
</div> </div>
</div> </div>
<button class="btn btn-primary pull-right" type="submit">Generate passphrase protected HTML</button> <button class="btn btn-primary pull-right" type="submit">Generate password protected HTML</button>
</form> </form>
</div> </div>
</div> </div>
@ -254,14 +254,14 @@ const UTF8Encoder = {
/** /**
* Salt and encrypt a msg with a password. * Salt and encrypt a msg with a password.
*/ */
async function encrypt(msg, hashedPassphrase) { async function encrypt(msg, hashedPassword) {
// Must be 16 bytes, unpredictable, and preferably cryptographically random. However, it need not be secret. // Must be 16 bytes, unpredictable, and preferably cryptographically random. However, it need not be secret.
// https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/encrypt#parameters // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/encrypt#parameters
const iv = crypto.getRandomValues(new Uint8Array(IV_BITS / 8)); const iv = crypto.getRandomValues(new Uint8Array(IV_BITS / 8));
const key = await subtle.importKey( const key = await subtle.importKey(
"raw", "raw",
HexEncoder.parse(hashedPassphrase), HexEncoder.parse(hashedPassword),
ENCRYPTION_ALGO, ENCRYPTION_ALGO,
false, false,
["encrypt"] ["encrypt"]
@ -285,17 +285,17 @@ exports.encrypt = encrypt;
* Decrypt a salted msg using a password. * Decrypt a salted msg using a password.
* *
* @param {string} encryptedMsg * @param {string} encryptedMsg
* @param {string} hashedPassphrase * @param {string} hashedPassword
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
async function decrypt(encryptedMsg, hashedPassphrase) { async function decrypt(encryptedMsg, hashedPassword) {
const ivLength = IV_BITS / HEX_BITS; const ivLength = IV_BITS / HEX_BITS;
const iv = HexEncoder.parse(encryptedMsg.substring(0, ivLength)); const iv = HexEncoder.parse(encryptedMsg.substring(0, ivLength));
const encrypted = encryptedMsg.substring(ivLength); const encrypted = encryptedMsg.substring(ivLength);
const key = await subtle.importKey( const key = await subtle.importKey(
"raw", "raw",
HexEncoder.parse(hashedPassphrase), HexEncoder.parse(hashedPassword),
ENCRYPTION_ALGO, ENCRYPTION_ALGO,
false, false,
["decrypt"] ["decrypt"]
@ -315,33 +315,33 @@ async function decrypt(encryptedMsg, hashedPassphrase) {
exports.decrypt = decrypt; exports.decrypt = decrypt;
/** /**
* Salt and hash the passphrase so it can be stored in localStorage without opening a password reuse vulnerability. * Salt and hash the password so it can be stored in localStorage without opening a password reuse vulnerability.
* *
* @param {string} passphrase * @param {string} password
* @param {string} salt * @param {string} salt
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
async function hashPassphrase(passphrase, salt) { async function hashPassword(password, salt) {
// we hash the passphrase in multiple steps, each adding more iterations. This is because we used to allow less // we hash the password in multiple steps, each adding more iterations. This is because we used to allow less
// iterations, so for backward compatibility reasons, we need to support going from that to more iterations. // iterations, so for backward compatibility reasons, we need to support going from that to more iterations.
let hashedPassphrase = await hashLegacyRound(passphrase, salt); let hashedPassword = await hashLegacyRound(password, salt);
hashedPassphrase = await hashSecondRound(hashedPassphrase, salt); hashedPassword = await hashSecondRound(hashedPassword, salt);
return hashThirdRound(hashedPassphrase, salt); return hashThirdRound(hashedPassword, salt);
} }
exports.hashPassphrase = hashPassphrase; exports.hashPassword = hashPassword;
/** /**
* This hashes the passphrase with 1k iterations. This is a low number, we need this function to support backwards * This hashes the password with 1k iterations. This is a low number, we need this function to support backwards
* compatibility. * compatibility.
* *
* @param {string} passphrase * @param {string} password
* @param {string} salt * @param {string} salt
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
function hashLegacyRound(passphrase, salt) { function hashLegacyRound(password, salt) {
return pbkdf2(passphrase, salt, 1000, "SHA-1"); return pbkdf2(password, salt, 1000, "SHA-1");
} }
exports.hashLegacyRound = hashLegacyRound; exports.hashLegacyRound = hashLegacyRound;
@ -349,12 +349,12 @@ exports.hashLegacyRound = hashLegacyRound;
* Add a second round of iterations. This is because we used to use 1k, so for backwards compatibility with * Add a second round of iterations. This is because we used to use 1k, so for backwards compatibility with
* remember-me/autodecrypt links, we need to support going from that to more iterations. * remember-me/autodecrypt links, we need to support going from that to more iterations.
* *
* @param hashedPassphrase * @param hashedPassword
* @param salt * @param salt
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
function hashSecondRound(hashedPassphrase, salt) { function hashSecondRound(hashedPassword, salt) {
return pbkdf2(hashedPassphrase, salt, 14000, "SHA-256"); return pbkdf2(hashedPassword, salt, 14000, "SHA-256");
} }
exports.hashSecondRound = hashSecondRound; exports.hashSecondRound = hashSecondRound;
@ -362,28 +362,28 @@ exports.hashSecondRound = hashSecondRound;
* Add a third round of iterations to bring total number to 600k. This is because we used to use 1k, then 15k, so for * Add a third round of iterations to bring total number to 600k. This is because we used to use 1k, then 15k, so for
* backwards compatibility with remember-me/autodecrypt links, we need to support going from that to more iterations. * backwards compatibility with remember-me/autodecrypt links, we need to support going from that to more iterations.
* *
* @param hashedPassphrase * @param hashedPassword
* @param salt * @param salt
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
function hashThirdRound(hashedPassphrase, salt) { function hashThirdRound(hashedPassword, salt) {
return pbkdf2(hashedPassphrase, salt, 585000, "SHA-256"); return pbkdf2(hashedPassword, salt, 585000, "SHA-256");
} }
exports.hashThirdRound = hashThirdRound; exports.hashThirdRound = hashThirdRound;
/** /**
* Salt and hash the passphrase so it can be stored in localStorage without opening a password reuse vulnerability. * Salt and hash the password so it can be stored in localStorage without opening a password reuse vulnerability.
* *
* @param {string} passphrase * @param {string} password
* @param {string} salt * @param {string} salt
* @param {int} iterations * @param {int} iterations
* @param {string} hashAlgorithm * @param {string} hashAlgorithm
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
async function pbkdf2(passphrase, salt, iterations, hashAlgorithm) { async function pbkdf2(password, salt, iterations, hashAlgorithm) {
const key = await subtle.importKey( const key = await subtle.importKey(
"raw", "raw",
UTF8Encoder.parse(passphrase), UTF8Encoder.parse(password),
"PBKDF2", "PBKDF2",
false, false,
["deriveBits"] ["deriveBits"]
@ -410,10 +410,10 @@ function generateRandomSalt() {
} }
exports.generateRandomSalt = generateRandomSalt; exports.generateRandomSalt = generateRandomSalt;
async function signMessage(hashedPassphrase, message) { async function signMessage(hashedPassword, message) {
const key = await subtle.importKey( const key = await subtle.importKey(
"raw", "raw",
HexEncoder.parse(hashedPassphrase), HexEncoder.parse(hashedPassword),
{ {
name: "HMAC", name: "HMAC",
hash: "SHA-256", hash: "SHA-256",
@ -492,13 +492,13 @@ function init(cryptoEngine) {
* @returns {string} The encoded text * @returns {string} The encoded text
*/ */
async function encode(msg, password, salt) { async function encode(msg, password, salt) {
const hashedPassphrase = await cryptoEngine.hashPassphrase(password, salt); const hashedPassword = await cryptoEngine.hashPassword(password, salt);
const encrypted = await cryptoEngine.encrypt(msg, hashedPassphrase); const encrypted = await cryptoEngine.encrypt(msg, hashedPassword);
// we use the hashed password in the HMAC because this is effectively what will be used a password (so we can store // we use the hashed password in the HMAC because this is effectively what will be used a password (so we can store
// it in localStorage safely, we don't use the clear text password) // it in localStorage safely, we don't use the clear text password)
const hmac = await cryptoEngine.signMessage(hashedPassphrase, encrypted); const hmac = await cryptoEngine.signMessage(hashedPassword, encrypted);
return hmac + encrypted; return hmac + encrypted;
} }
@ -509,58 +509,58 @@ function init(cryptoEngine) {
* we don't need to hash the password multiple times. * we don't need to hash the password multiple times.
* *
* @param {string} msg * @param {string} msg
* @param {string} hashedPassphrase * @param {string} hashedPassword
* *
* @returns {string} The encoded text * @returns {string} The encoded text
*/ */
async function encodeWithHashedPassphrase(msg, hashedPassphrase) { async function encodeWithHashedPassword(msg, hashedPassword) {
const encrypted = await cryptoEngine.encrypt(msg, hashedPassphrase); const encrypted = await cryptoEngine.encrypt(msg, hashedPassword);
// we use the hashed password in the HMAC because this is effectively what will be used a password (so we can store // we use the hashed password in the HMAC because this is effectively what will be used a password (so we can store
// it in localStorage safely, we don't use the clear text password) // it in localStorage safely, we don't use the clear text password)
const hmac = await cryptoEngine.signMessage(hashedPassphrase, encrypted); const hmac = await cryptoEngine.signMessage(hashedPassword, encrypted);
return hmac + encrypted; return hmac + encrypted;
} }
exports.encodeWithHashedPassphrase = encodeWithHashedPassphrase; exports.encodeWithHashedPassword = encodeWithHashedPassword;
/** /**
* Top-level function for decoding a message. * Top-level function for decoding a message.
* Includes signature check and decryption. * Includes signature check and decryption.
* *
* @param {string} signedMsg * @param {string} signedMsg
* @param {string} hashedPassphrase * @param {string} hashedPassword
* @param {string} salt * @param {string} salt
* @param {int} backwardCompatibleAttempt * @param {int} backwardCompatibleAttempt
* @param {string} originalPassphrase * @param {string} originalPassword
* *
* @returns {Object} {success: true, decoded: string} | {success: false, message: string} * @returns {Object} {success: true, decoded: string} | {success: false, message: string}
*/ */
async function decode( async function decode(
signedMsg, signedMsg,
hashedPassphrase, hashedPassword,
salt, salt,
backwardCompatibleAttempt = 0, backwardCompatibleAttempt = 0,
originalPassphrase = '' originalPassword = ''
) { ) {
const encryptedHMAC = signedMsg.substring(0, 64); const encryptedHMAC = signedMsg.substring(0, 64);
const encryptedMsg = signedMsg.substring(64); const encryptedMsg = signedMsg.substring(64);
const decryptedHMAC = await cryptoEngine.signMessage(hashedPassphrase, encryptedMsg); const decryptedHMAC = await cryptoEngine.signMessage(hashedPassword, encryptedMsg);
if (decryptedHMAC !== encryptedHMAC) { if (decryptedHMAC !== encryptedHMAC) {
// we have been raising the number of iterations in the hashing algorithm multiple times, so to support the old // we have been raising the number of iterations in the hashing algorithm multiple times, so to support the old
// remember-me/autodecrypt links we need to try bringing the old hashes up to speed. // remember-me/autodecrypt links we need to try bringing the old hashes up to speed.
originalPassphrase = originalPassphrase || hashedPassphrase; originalPassword = originalPassword || hashedPassword;
if (backwardCompatibleAttempt === 0) { if (backwardCompatibleAttempt === 0) {
const updatedHashedPassphrase = await cryptoEngine.hashThirdRound(originalPassphrase, salt); const updatedHashedPassword = await cryptoEngine.hashThirdRound(originalPassword, salt);
return decode(signedMsg, updatedHashedPassphrase, salt, backwardCompatibleAttempt + 1, originalPassphrase); return decode(signedMsg, updatedHashedPassword, salt, backwardCompatibleAttempt + 1, originalPassword);
} }
if (backwardCompatibleAttempt === 1) { if (backwardCompatibleAttempt === 1) {
let updatedHashedPassphrase = await cryptoEngine.hashSecondRound(originalPassphrase, salt); let updatedHashedPassword = await cryptoEngine.hashSecondRound(originalPassword, salt);
updatedHashedPassphrase = await cryptoEngine.hashThirdRound(updatedHashedPassphrase, salt); updatedHashedPassword = await cryptoEngine.hashThirdRound(updatedHashedPassword, salt);
return decode(signedMsg, updatedHashedPassphrase, salt, backwardCompatibleAttempt + 1, originalPassphrase); return decode(signedMsg, updatedHashedPassword, salt, backwardCompatibleAttempt + 1, originalPassword);
} }
return { success: false, message: "Signature mismatch" }; return { success: false, message: "Signature mismatch" };
@ -568,7 +568,7 @@ function init(cryptoEngine) {
return { return {
success: true, success: true,
decoded: await cryptoEngine.decrypt(encryptedMsg, hashedPassphrase), decoded: await cryptoEngine.decrypt(encryptedMsg, hashedPassword),
}; };
} }
exports.decode = decode; exports.decode = decode;
@ -686,14 +686,14 @@ const UTF8Encoder = {
/** /**
* Salt and encrypt a msg with a password. * Salt and encrypt a msg with a password.
*/ */
async function encrypt(msg, hashedPassphrase) { async function encrypt(msg, hashedPassword) {
// Must be 16 bytes, unpredictable, and preferably cryptographically random. However, it need not be secret. // Must be 16 bytes, unpredictable, and preferably cryptographically random. However, it need not be secret.
// https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/encrypt#parameters // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/encrypt#parameters
const iv = crypto.getRandomValues(new Uint8Array(IV_BITS / 8)); const iv = crypto.getRandomValues(new Uint8Array(IV_BITS / 8));
const key = await subtle.importKey( const key = await subtle.importKey(
"raw", "raw",
HexEncoder.parse(hashedPassphrase), HexEncoder.parse(hashedPassword),
ENCRYPTION_ALGO, ENCRYPTION_ALGO,
false, false,
["encrypt"] ["encrypt"]
@ -717,17 +717,17 @@ exports.encrypt = encrypt;
* Decrypt a salted msg using a password. * Decrypt a salted msg using a password.
* *
* @param {string} encryptedMsg * @param {string} encryptedMsg
* @param {string} hashedPassphrase * @param {string} hashedPassword
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
async function decrypt(encryptedMsg, hashedPassphrase) { async function decrypt(encryptedMsg, hashedPassword) {
const ivLength = IV_BITS / HEX_BITS; const ivLength = IV_BITS / HEX_BITS;
const iv = HexEncoder.parse(encryptedMsg.substring(0, ivLength)); const iv = HexEncoder.parse(encryptedMsg.substring(0, ivLength));
const encrypted = encryptedMsg.substring(ivLength); const encrypted = encryptedMsg.substring(ivLength);
const key = await subtle.importKey( const key = await subtle.importKey(
"raw", "raw",
HexEncoder.parse(hashedPassphrase), HexEncoder.parse(hashedPassword),
ENCRYPTION_ALGO, ENCRYPTION_ALGO,
false, false,
["decrypt"] ["decrypt"]
@ -747,33 +747,33 @@ async function decrypt(encryptedMsg, hashedPassphrase) {
exports.decrypt = decrypt; exports.decrypt = decrypt;
/** /**
* Salt and hash the passphrase so it can be stored in localStorage without opening a password reuse vulnerability. * Salt and hash the password so it can be stored in localStorage without opening a password reuse vulnerability.
* *
* @param {string} passphrase * @param {string} password
* @param {string} salt * @param {string} salt
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
async function hashPassphrase(passphrase, salt) { async function hashPassword(password, salt) {
// we hash the passphrase in multiple steps, each adding more iterations. This is because we used to allow less // we hash the password in multiple steps, each adding more iterations. This is because we used to allow less
// iterations, so for backward compatibility reasons, we need to support going from that to more iterations. // iterations, so for backward compatibility reasons, we need to support going from that to more iterations.
let hashedPassphrase = await hashLegacyRound(passphrase, salt); let hashedPassword = await hashLegacyRound(password, salt);
hashedPassphrase = await hashSecondRound(hashedPassphrase, salt); hashedPassword = await hashSecondRound(hashedPassword, salt);
return hashThirdRound(hashedPassphrase, salt); return hashThirdRound(hashedPassword, salt);
} }
exports.hashPassphrase = hashPassphrase; exports.hashPassword = hashPassword;
/** /**
* This hashes the passphrase with 1k iterations. This is a low number, we need this function to support backwards * This hashes the password with 1k iterations. This is a low number, we need this function to support backwards
* compatibility. * compatibility.
* *
* @param {string} passphrase * @param {string} password
* @param {string} salt * @param {string} salt
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
function hashLegacyRound(passphrase, salt) { function hashLegacyRound(password, salt) {
return pbkdf2(passphrase, salt, 1000, "SHA-1"); return pbkdf2(password, salt, 1000, "SHA-1");
} }
exports.hashLegacyRound = hashLegacyRound; exports.hashLegacyRound = hashLegacyRound;
@ -781,12 +781,12 @@ exports.hashLegacyRound = hashLegacyRound;
* Add a second round of iterations. This is because we used to use 1k, so for backwards compatibility with * Add a second round of iterations. This is because we used to use 1k, so for backwards compatibility with
* remember-me/autodecrypt links, we need to support going from that to more iterations. * remember-me/autodecrypt links, we need to support going from that to more iterations.
* *
* @param hashedPassphrase * @param hashedPassword
* @param salt * @param salt
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
function hashSecondRound(hashedPassphrase, salt) { function hashSecondRound(hashedPassword, salt) {
return pbkdf2(hashedPassphrase, salt, 14000, "SHA-256"); return pbkdf2(hashedPassword, salt, 14000, "SHA-256");
} }
exports.hashSecondRound = hashSecondRound; exports.hashSecondRound = hashSecondRound;
@ -794,28 +794,28 @@ exports.hashSecondRound = hashSecondRound;
* Add a third round of iterations to bring total number to 600k. This is because we used to use 1k, then 15k, so for * Add a third round of iterations to bring total number to 600k. This is because we used to use 1k, then 15k, so for
* backwards compatibility with remember-me/autodecrypt links, we need to support going from that to more iterations. * backwards compatibility with remember-me/autodecrypt links, we need to support going from that to more iterations.
* *
* @param hashedPassphrase * @param hashedPassword
* @param salt * @param salt
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
function hashThirdRound(hashedPassphrase, salt) { function hashThirdRound(hashedPassword, salt) {
return pbkdf2(hashedPassphrase, salt, 585000, "SHA-256"); return pbkdf2(hashedPassword, salt, 585000, "SHA-256");
} }
exports.hashThirdRound = hashThirdRound; exports.hashThirdRound = hashThirdRound;
/** /**
* Salt and hash the passphrase so it can be stored in localStorage without opening a password reuse vulnerability. * Salt and hash the password so it can be stored in localStorage without opening a password reuse vulnerability.
* *
* @param {string} passphrase * @param {string} password
* @param {string} salt * @param {string} salt
* @param {int} iterations * @param {int} iterations
* @param {string} hashAlgorithm * @param {string} hashAlgorithm
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
async function pbkdf2(passphrase, salt, iterations, hashAlgorithm) { async function pbkdf2(password, salt, iterations, hashAlgorithm) {
const key = await subtle.importKey( const key = await subtle.importKey(
"raw", "raw",
UTF8Encoder.parse(passphrase), UTF8Encoder.parse(password),
"PBKDF2", "PBKDF2",
false, false,
["deriveBits"] ["deriveBits"]
@ -842,10 +842,10 @@ function generateRandomSalt() {
} }
exports.generateRandomSalt = generateRandomSalt; exports.generateRandomSalt = generateRandomSalt;
async function signMessage(hashedPassphrase, message) { async function signMessage(hashedPassword, message) {
const key = await subtle.importKey( const key = await subtle.importKey(
"raw", "raw",
HexEncoder.parse(hashedPassphrase), HexEncoder.parse(hashedPassword),
{ {
name: "HMAC", name: "HMAC",
hash: "SHA-256", hash: "SHA-256",
@ -921,13 +921,13 @@ function init(cryptoEngine) {
* @returns {string} The encoded text * @returns {string} The encoded text
*/ */
async function encode(msg, password, salt) { async function encode(msg, password, salt) {
const hashedPassphrase = await cryptoEngine.hashPassphrase(password, salt); const hashedPassword = await cryptoEngine.hashPassword(password, salt);
const encrypted = await cryptoEngine.encrypt(msg, hashedPassphrase); const encrypted = await cryptoEngine.encrypt(msg, hashedPassword);
// we use the hashed password in the HMAC because this is effectively what will be used a password (so we can store // we use the hashed password in the HMAC because this is effectively what will be used a password (so we can store
// it in localStorage safely, we don't use the clear text password) // it in localStorage safely, we don't use the clear text password)
const hmac = await cryptoEngine.signMessage(hashedPassphrase, encrypted); const hmac = await cryptoEngine.signMessage(hashedPassword, encrypted);
return hmac + encrypted; return hmac + encrypted;
} }
@ -938,58 +938,58 @@ function init(cryptoEngine) {
* we don't need to hash the password multiple times. * we don't need to hash the password multiple times.
* *
* @param {string} msg * @param {string} msg
* @param {string} hashedPassphrase * @param {string} hashedPassword
* *
* @returns {string} The encoded text * @returns {string} The encoded text
*/ */
async function encodeWithHashedPassphrase(msg, hashedPassphrase) { async function encodeWithHashedPassword(msg, hashedPassword) {
const encrypted = await cryptoEngine.encrypt(msg, hashedPassphrase); const encrypted = await cryptoEngine.encrypt(msg, hashedPassword);
// we use the hashed password in the HMAC because this is effectively what will be used a password (so we can store // we use the hashed password in the HMAC because this is effectively what will be used a password (so we can store
// it in localStorage safely, we don't use the clear text password) // it in localStorage safely, we don't use the clear text password)
const hmac = await cryptoEngine.signMessage(hashedPassphrase, encrypted); const hmac = await cryptoEngine.signMessage(hashedPassword, encrypted);
return hmac + encrypted; return hmac + encrypted;
} }
exports.encodeWithHashedPassphrase = encodeWithHashedPassphrase; exports.encodeWithHashedPassword = encodeWithHashedPassword;
/** /**
* Top-level function for decoding a message. * Top-level function for decoding a message.
* Includes signature check and decryption. * Includes signature check and decryption.
* *
* @param {string} signedMsg * @param {string} signedMsg
* @param {string} hashedPassphrase * @param {string} hashedPassword
* @param {string} salt * @param {string} salt
* @param {int} backwardCompatibleAttempt * @param {int} backwardCompatibleAttempt
* @param {string} originalPassphrase * @param {string} originalPassword
* *
* @returns {Object} {success: true, decoded: string} | {success: false, message: string} * @returns {Object} {success: true, decoded: string} | {success: false, message: string}
*/ */
async function decode( async function decode(
signedMsg, signedMsg,
hashedPassphrase, hashedPassword,
salt, salt,
backwardCompatibleAttempt = 0, backwardCompatibleAttempt = 0,
originalPassphrase = '' originalPassword = ''
) { ) {
const encryptedHMAC = signedMsg.substring(0, 64); const encryptedHMAC = signedMsg.substring(0, 64);
const encryptedMsg = signedMsg.substring(64); const encryptedMsg = signedMsg.substring(64);
const decryptedHMAC = await cryptoEngine.signMessage(hashedPassphrase, encryptedMsg); const decryptedHMAC = await cryptoEngine.signMessage(hashedPassword, encryptedMsg);
if (decryptedHMAC !== encryptedHMAC) { if (decryptedHMAC !== encryptedHMAC) {
// we have been raising the number of iterations in the hashing algorithm multiple times, so to support the old // we have been raising the number of iterations in the hashing algorithm multiple times, so to support the old
// remember-me/autodecrypt links we need to try bringing the old hashes up to speed. // remember-me/autodecrypt links we need to try bringing the old hashes up to speed.
originalPassphrase = originalPassphrase || hashedPassphrase; originalPassword = originalPassword || hashedPassword;
if (backwardCompatibleAttempt === 0) { if (backwardCompatibleAttempt === 0) {
const updatedHashedPassphrase = await cryptoEngine.hashThirdRound(originalPassphrase, salt); const updatedHashedPassword = await cryptoEngine.hashThirdRound(originalPassword, salt);
return decode(signedMsg, updatedHashedPassphrase, salt, backwardCompatibleAttempt + 1, originalPassphrase); return decode(signedMsg, updatedHashedPassword, salt, backwardCompatibleAttempt + 1, originalPassword);
} }
if (backwardCompatibleAttempt === 1) { if (backwardCompatibleAttempt === 1) {
let updatedHashedPassphrase = await cryptoEngine.hashSecondRound(originalPassphrase, salt); let updatedHashedPassword = await cryptoEngine.hashSecondRound(originalPassword, salt);
updatedHashedPassphrase = await cryptoEngine.hashThirdRound(updatedHashedPassphrase, salt); updatedHashedPassword = await cryptoEngine.hashThirdRound(updatedHashedPassword, salt);
return decode(signedMsg, updatedHashedPassphrase, salt, backwardCompatibleAttempt + 1, originalPassphrase); return decode(signedMsg, updatedHashedPassword, salt, backwardCompatibleAttempt + 1, originalPassword);
} }
return { success: false, message: "Signature mismatch" }; return { success: false, message: "Signature mismatch" };
@ -997,7 +997,7 @@ function init(cryptoEngine) {
return { return {
success: true, success: true,
decoded: await cryptoEngine.decrypt(encryptedMsg, hashedPassphrase), decoded: await cryptoEngine.decrypt(encryptedMsg, hashedPassword),
}; };
} }
exports.decode = decode; exports.decode = decode;
@ -1034,14 +1034,14 @@ function init(staticryptConfig, templateConfig) {
/** /**
* Decrypt our encrypted page, replace the whole HTML. * Decrypt our encrypted page, replace the whole HTML.
* *
* @param {string} hashedPassphrase * @param {string} hashedPassword
* @returns {Promise<boolean>} * @returns {Promise<boolean>}
*/ */
async function decryptAndReplaceHtml(hashedPassphrase) { async function decryptAndReplaceHtml(hashedPassword) {
const { encryptedMsg, salt } = staticryptConfig; const { encryptedMsg, salt } = staticryptConfig;
const { replaceHtmlCallback } = templateConfig; const { replaceHtmlCallback } = templateConfig;
const result = await decode(encryptedMsg, hashedPassphrase, salt); const result = await decode(encryptedMsg, hashedPassword, salt);
if (!result.success) { if (!result.success) {
return false; return false;
} }
@ -1072,7 +1072,7 @@ function init(staticryptConfig, templateConfig) {
const { rememberExpirationKey, rememberPassphraseKey } = templateConfig; const { rememberExpirationKey, rememberPassphraseKey } = templateConfig;
// decrypt and replace the whole page // decrypt and replace the whole page
const hashedPassword = await cryptoEngine.hashPassphrase(password, salt); const hashedPassword = await cryptoEngine.hashPassword(password, salt);
const isDecryptionSuccessful = await decryptAndReplaceHtml(hashedPassword); const isDecryptionSuccessful = await decryptAndReplaceHtml(hashedPassword);
@ -1179,11 +1179,11 @@ function init(staticryptConfig, templateConfig) {
} }
} }
const hashedPassphrase = localStorage.getItem(rememberPassphraseKey); const hashedPassword = localStorage.getItem(rememberPassphraseKey);
if (hashedPassphrase) { if (hashedPassword) {
// try to decrypt // try to decrypt
const isDecryptionSuccessful = await decryptAndReplaceHtml(hashedPassphrase); const isDecryptionSuccessful = await decryptAndReplaceHtml(hashedPassword);
// if the decryption is unsuccessful the password might be wrong - silently clear the saved data and let // if the decryption is unsuccessful the password might be wrong - silently clear the saved data and let
// the user fill the password form again // the user fill the password form again
@ -1203,16 +1203,16 @@ function init(staticryptConfig, templateConfig) {
// get the password from the query param // get the password from the query param
const queryParams = new URLSearchParams(window.location.search); const queryParams = new URLSearchParams(window.location.search);
const hashedPassphraseQuery = queryParams.get(passwordKey); const hashedPasswordQuery = queryParams.get(passwordKey);
// get the password from the url fragment // get the password from the url fragment
const hashRegexMatch = window.location.hash.substring(1).match(new RegExp(passwordKey + "=(.*)")); const hashRegexMatch = window.location.hash.substring(1).match(new RegExp(passwordKey + "=(.*)"));
const hashedPassphraseFragment = hashRegexMatch ? hashRegexMatch[1] : null; const hashedPasswordFragment = hashRegexMatch ? hashRegexMatch[1] : null;
const hashedPassphrase = hashedPassphraseFragment || hashedPassphraseQuery; const hashedPassword = hashedPasswordFragment || hashedPasswordQuery;
if (hashedPassphrase) { if (hashedPassword) {
return decryptAndReplaceHtml(hashedPassphrase); return decryptAndReplaceHtml(hashedPassword);
} }
return false; return false;
@ -1300,10 +1300,10 @@ exports.init = init;
CKEDITOR.instances['template_instructions'].updateElement(); CKEDITOR.instances['template_instructions'].updateElement();
const unencrypted = document.getElementById('unencrypted_html').value, const unencrypted = document.getElementById('unencrypted_html').value,
passphrase = document.getElementById('passphrase').value; password = document.getElementById('password').value;
const salt = cryptoEngine.generateRandomSalt(); const salt = cryptoEngine.generateRandomSalt();
const encryptedMsg = await encode(unencrypted, passphrase, salt); const encryptedMsg = await encode(unencrypted, password, salt);
const templateButton = document.getElementById('template_button').value, const templateButton = document.getElementById('template_button').value,
templateInstructions = document.getElementById('template_instructions').value, templateInstructions = document.getElementById('template_instructions').value,
@ -1324,7 +1324,7 @@ exports.init = init;
js_staticrypt: getScriptAsString('staticrypt'), js_staticrypt: getScriptAsString('staticrypt'),
template_button: templateButton ? templateButton : 'DECRYPT', template_button: templateButton ? templateButton : 'DECRYPT',
template_instructions: templateInstructions || '', template_instructions: templateInstructions || '',
template_placeholder: templatePlaceholder || 'Passphrase', template_placeholder: templatePlaceholder || 'Password',
template_remember: templateRemember || 'Remember me', template_remember: templateRemember || 'Remember me',
template_title: templateTitle || 'Protected Page', template_title: templateTitle || 'Protected Page',
}; };

Wyświetl plik

@ -17,13 +17,13 @@ function init(cryptoEngine) {
* @returns {string} The encoded text * @returns {string} The encoded text
*/ */
async function encode(msg, password, salt) { async function encode(msg, password, salt) {
const hashedPassphrase = await cryptoEngine.hashPassphrase(password, salt); const hashedPassword = await cryptoEngine.hashPassword(password, salt);
const encrypted = await cryptoEngine.encrypt(msg, hashedPassphrase); const encrypted = await cryptoEngine.encrypt(msg, hashedPassword);
// we use the hashed password in the HMAC because this is effectively what will be used a password (so we can store // we use the hashed password in the HMAC because this is effectively what will be used a password (so we can store
// it in localStorage safely, we don't use the clear text password) // it in localStorage safely, we don't use the clear text password)
const hmac = await cryptoEngine.signMessage(hashedPassphrase, encrypted); const hmac = await cryptoEngine.signMessage(hashedPassword, encrypted);
return hmac + encrypted; return hmac + encrypted;
} }
@ -34,58 +34,58 @@ function init(cryptoEngine) {
* we don't need to hash the password multiple times. * we don't need to hash the password multiple times.
* *
* @param {string} msg * @param {string} msg
* @param {string} hashedPassphrase * @param {string} hashedPassword
* *
* @returns {string} The encoded text * @returns {string} The encoded text
*/ */
async function encodeWithHashedPassphrase(msg, hashedPassphrase) { async function encodeWithHashedPassword(msg, hashedPassword) {
const encrypted = await cryptoEngine.encrypt(msg, hashedPassphrase); const encrypted = await cryptoEngine.encrypt(msg, hashedPassword);
// we use the hashed password in the HMAC because this is effectively what will be used a password (so we can store // we use the hashed password in the HMAC because this is effectively what will be used a password (so we can store
// it in localStorage safely, we don't use the clear text password) // it in localStorage safely, we don't use the clear text password)
const hmac = await cryptoEngine.signMessage(hashedPassphrase, encrypted); const hmac = await cryptoEngine.signMessage(hashedPassword, encrypted);
return hmac + encrypted; return hmac + encrypted;
} }
exports.encodeWithHashedPassphrase = encodeWithHashedPassphrase; exports.encodeWithHashedPassword = encodeWithHashedPassword;
/** /**
* Top-level function for decoding a message. * Top-level function for decoding a message.
* Includes signature check and decryption. * Includes signature check and decryption.
* *
* @param {string} signedMsg * @param {string} signedMsg
* @param {string} hashedPassphrase * @param {string} hashedPassword
* @param {string} salt * @param {string} salt
* @param {int} backwardCompatibleAttempt * @param {int} backwardCompatibleAttempt
* @param {string} originalPassphrase * @param {string} originalPassword
* *
* @returns {Object} {success: true, decoded: string} | {success: false, message: string} * @returns {Object} {success: true, decoded: string} | {success: false, message: string}
*/ */
async function decode( async function decode(
signedMsg, signedMsg,
hashedPassphrase, hashedPassword,
salt, salt,
backwardCompatibleAttempt = 0, backwardCompatibleAttempt = 0,
originalPassphrase = '' originalPassword = ''
) { ) {
const encryptedHMAC = signedMsg.substring(0, 64); const encryptedHMAC = signedMsg.substring(0, 64);
const encryptedMsg = signedMsg.substring(64); const encryptedMsg = signedMsg.substring(64);
const decryptedHMAC = await cryptoEngine.signMessage(hashedPassphrase, encryptedMsg); const decryptedHMAC = await cryptoEngine.signMessage(hashedPassword, encryptedMsg);
if (decryptedHMAC !== encryptedHMAC) { if (decryptedHMAC !== encryptedHMAC) {
// we have been raising the number of iterations in the hashing algorithm multiple times, so to support the old // we have been raising the number of iterations in the hashing algorithm multiple times, so to support the old
// remember-me/autodecrypt links we need to try bringing the old hashes up to speed. // remember-me/autodecrypt links we need to try bringing the old hashes up to speed.
originalPassphrase = originalPassphrase || hashedPassphrase; originalPassword = originalPassword || hashedPassword;
if (backwardCompatibleAttempt === 0) { if (backwardCompatibleAttempt === 0) {
const updatedHashedPassphrase = await cryptoEngine.hashThirdRound(originalPassphrase, salt); const updatedHashedPassword = await cryptoEngine.hashThirdRound(originalPassword, salt);
return decode(signedMsg, updatedHashedPassphrase, salt, backwardCompatibleAttempt + 1, originalPassphrase); return decode(signedMsg, updatedHashedPassword, salt, backwardCompatibleAttempt + 1, originalPassword);
} }
if (backwardCompatibleAttempt === 1) { if (backwardCompatibleAttempt === 1) {
let updatedHashedPassphrase = await cryptoEngine.hashSecondRound(originalPassphrase, salt); let updatedHashedPassword = await cryptoEngine.hashSecondRound(originalPassword, salt);
updatedHashedPassphrase = await cryptoEngine.hashThirdRound(updatedHashedPassphrase, salt); updatedHashedPassword = await cryptoEngine.hashThirdRound(updatedHashedPassword, salt);
return decode(signedMsg, updatedHashedPassphrase, salt, backwardCompatibleAttempt + 1, originalPassphrase); return decode(signedMsg, updatedHashedPassword, salt, backwardCompatibleAttempt + 1, originalPassword);
} }
return { success: false, message: "Signature mismatch" }; return { success: false, message: "Signature mismatch" };
@ -93,7 +93,7 @@ function init(cryptoEngine) {
return { return {
success: true, success: true,
decoded: await cryptoEngine.decrypt(encryptedMsg, hashedPassphrase), decoded: await cryptoEngine.decrypt(encryptedMsg, hashedPassword),
}; };
} }
exports.decode = decode; exports.decode = decode;

Wyświetl plik

@ -64,14 +64,14 @@ const UTF8Encoder = {
/** /**
* Salt and encrypt a msg with a password. * Salt and encrypt a msg with a password.
*/ */
async function encrypt(msg, hashedPassphrase) { async function encrypt(msg, hashedPassword) {
// Must be 16 bytes, unpredictable, and preferably cryptographically random. However, it need not be secret. // Must be 16 bytes, unpredictable, and preferably cryptographically random. However, it need not be secret.
// https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/encrypt#parameters // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/encrypt#parameters
const iv = crypto.getRandomValues(new Uint8Array(IV_BITS / 8)); const iv = crypto.getRandomValues(new Uint8Array(IV_BITS / 8));
const key = await subtle.importKey( const key = await subtle.importKey(
"raw", "raw",
HexEncoder.parse(hashedPassphrase), HexEncoder.parse(hashedPassword),
ENCRYPTION_ALGO, ENCRYPTION_ALGO,
false, false,
["encrypt"] ["encrypt"]
@ -95,17 +95,17 @@ exports.encrypt = encrypt;
* Decrypt a salted msg using a password. * Decrypt a salted msg using a password.
* *
* @param {string} encryptedMsg * @param {string} encryptedMsg
* @param {string} hashedPassphrase * @param {string} hashedPassword
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
async function decrypt(encryptedMsg, hashedPassphrase) { async function decrypt(encryptedMsg, hashedPassword) {
const ivLength = IV_BITS / HEX_BITS; const ivLength = IV_BITS / HEX_BITS;
const iv = HexEncoder.parse(encryptedMsg.substring(0, ivLength)); const iv = HexEncoder.parse(encryptedMsg.substring(0, ivLength));
const encrypted = encryptedMsg.substring(ivLength); const encrypted = encryptedMsg.substring(ivLength);
const key = await subtle.importKey( const key = await subtle.importKey(
"raw", "raw",
HexEncoder.parse(hashedPassphrase), HexEncoder.parse(hashedPassword),
ENCRYPTION_ALGO, ENCRYPTION_ALGO,
false, false,
["decrypt"] ["decrypt"]
@ -125,33 +125,33 @@ async function decrypt(encryptedMsg, hashedPassphrase) {
exports.decrypt = decrypt; exports.decrypt = decrypt;
/** /**
* Salt and hash the passphrase so it can be stored in localStorage without opening a password reuse vulnerability. * Salt and hash the password so it can be stored in localStorage without opening a password reuse vulnerability.
* *
* @param {string} passphrase * @param {string} password
* @param {string} salt * @param {string} salt
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
async function hashPassphrase(passphrase, salt) { async function hashPassword(password, salt) {
// we hash the passphrase in multiple steps, each adding more iterations. This is because we used to allow less // we hash the password in multiple steps, each adding more iterations. This is because we used to allow less
// iterations, so for backward compatibility reasons, we need to support going from that to more iterations. // iterations, so for backward compatibility reasons, we need to support going from that to more iterations.
let hashedPassphrase = await hashLegacyRound(passphrase, salt); let hashedPassword = await hashLegacyRound(password, salt);
hashedPassphrase = await hashSecondRound(hashedPassphrase, salt); hashedPassword = await hashSecondRound(hashedPassword, salt);
return hashThirdRound(hashedPassphrase, salt); return hashThirdRound(hashedPassword, salt);
} }
exports.hashPassphrase = hashPassphrase; exports.hashPassword = hashPassword;
/** /**
* This hashes the passphrase with 1k iterations. This is a low number, we need this function to support backwards * This hashes the password with 1k iterations. This is a low number, we need this function to support backwards
* compatibility. * compatibility.
* *
* @param {string} passphrase * @param {string} password
* @param {string} salt * @param {string} salt
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
function hashLegacyRound(passphrase, salt) { function hashLegacyRound(password, salt) {
return pbkdf2(passphrase, salt, 1000, "SHA-1"); return pbkdf2(password, salt, 1000, "SHA-1");
} }
exports.hashLegacyRound = hashLegacyRound; exports.hashLegacyRound = hashLegacyRound;
@ -159,12 +159,12 @@ exports.hashLegacyRound = hashLegacyRound;
* Add a second round of iterations. This is because we used to use 1k, so for backwards compatibility with * Add a second round of iterations. This is because we used to use 1k, so for backwards compatibility with
* remember-me/autodecrypt links, we need to support going from that to more iterations. * remember-me/autodecrypt links, we need to support going from that to more iterations.
* *
* @param hashedPassphrase * @param hashedPassword
* @param salt * @param salt
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
function hashSecondRound(hashedPassphrase, salt) { function hashSecondRound(hashedPassword, salt) {
return pbkdf2(hashedPassphrase, salt, 14000, "SHA-256"); return pbkdf2(hashedPassword, salt, 14000, "SHA-256");
} }
exports.hashSecondRound = hashSecondRound; exports.hashSecondRound = hashSecondRound;
@ -172,28 +172,28 @@ exports.hashSecondRound = hashSecondRound;
* Add a third round of iterations to bring total number to 600k. This is because we used to use 1k, then 15k, so for * Add a third round of iterations to bring total number to 600k. This is because we used to use 1k, then 15k, so for
* backwards compatibility with remember-me/autodecrypt links, we need to support going from that to more iterations. * backwards compatibility with remember-me/autodecrypt links, we need to support going from that to more iterations.
* *
* @param hashedPassphrase * @param hashedPassword
* @param salt * @param salt
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
function hashThirdRound(hashedPassphrase, salt) { function hashThirdRound(hashedPassword, salt) {
return pbkdf2(hashedPassphrase, salt, 585000, "SHA-256"); return pbkdf2(hashedPassword, salt, 585000, "SHA-256");
} }
exports.hashThirdRound = hashThirdRound; exports.hashThirdRound = hashThirdRound;
/** /**
* Salt and hash the passphrase so it can be stored in localStorage without opening a password reuse vulnerability. * Salt and hash the password so it can be stored in localStorage without opening a password reuse vulnerability.
* *
* @param {string} passphrase * @param {string} password
* @param {string} salt * @param {string} salt
* @param {int} iterations * @param {int} iterations
* @param {string} hashAlgorithm * @param {string} hashAlgorithm
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
async function pbkdf2(passphrase, salt, iterations, hashAlgorithm) { async function pbkdf2(password, salt, iterations, hashAlgorithm) {
const key = await subtle.importKey( const key = await subtle.importKey(
"raw", "raw",
UTF8Encoder.parse(passphrase), UTF8Encoder.parse(password),
"PBKDF2", "PBKDF2",
false, false,
["deriveBits"] ["deriveBits"]
@ -220,10 +220,10 @@ function generateRandomSalt() {
} }
exports.generateRandomSalt = generateRandomSalt; exports.generateRandomSalt = generateRandomSalt;
async function signMessage(hashedPassphrase, message) { async function signMessage(hashedPassword, message) {
const key = await subtle.importKey( const key = await subtle.importKey(
"raw", "raw",
HexEncoder.parse(hashedPassphrase), HexEncoder.parse(hashedPassword),
{ {
name: "HMAC", name: "HMAC",
hash: "SHA-256", hash: "SHA-256",

Wyświetl plik

@ -221,10 +221,10 @@
document.getElementById('staticrypt-form').addEventListener('submit', async function (e) { document.getElementById('staticrypt-form').addEventListener('submit', async function (e) {
e.preventDefault(); e.preventDefault();
const passphrase = document.getElementById('staticrypt-password').value, const password = document.getElementById('staticrypt-password').value,
isRememberChecked = document.getElementById('staticrypt-remember').checked; isRememberChecked = document.getElementById('staticrypt-remember').checked;
const { isSuccessful } = await staticrypt.handleDecryptionOfPage(passphrase, isRememberChecked); const { isSuccessful } = await staticrypt.handleDecryptionOfPage(password, isRememberChecked);
if (!isSuccessful) { if (!isSuccessful) {
alert(templateError); alert(templateError);

Wyświetl plik

@ -26,14 +26,14 @@ function init(staticryptConfig, templateConfig) {
/** /**
* Decrypt our encrypted page, replace the whole HTML. * Decrypt our encrypted page, replace the whole HTML.
* *
* @param {string} hashedPassphrase * @param {string} hashedPassword
* @returns {Promise<boolean>} * @returns {Promise<boolean>}
*/ */
async function decryptAndReplaceHtml(hashedPassphrase) { async function decryptAndReplaceHtml(hashedPassword) {
const { encryptedMsg, salt } = staticryptConfig; const { encryptedMsg, salt } = staticryptConfig;
const { replaceHtmlCallback } = templateConfig; const { replaceHtmlCallback } = templateConfig;
const result = await decode(encryptedMsg, hashedPassphrase, salt); const result = await decode(encryptedMsg, hashedPassword, salt);
if (!result.success) { if (!result.success) {
return false; return false;
} }
@ -64,7 +64,7 @@ function init(staticryptConfig, templateConfig) {
const { rememberExpirationKey, rememberPassphraseKey } = templateConfig; const { rememberExpirationKey, rememberPassphraseKey } = templateConfig;
// decrypt and replace the whole page // decrypt and replace the whole page
const hashedPassword = await cryptoEngine.hashPassphrase(password, salt); const hashedPassword = await cryptoEngine.hashPassword(password, salt);
const isDecryptionSuccessful = await decryptAndReplaceHtml(hashedPassword); const isDecryptionSuccessful = await decryptAndReplaceHtml(hashedPassword);
@ -171,11 +171,11 @@ function init(staticryptConfig, templateConfig) {
} }
} }
const hashedPassphrase = localStorage.getItem(rememberPassphraseKey); const hashedPassword = localStorage.getItem(rememberPassphraseKey);
if (hashedPassphrase) { if (hashedPassword) {
// try to decrypt // try to decrypt
const isDecryptionSuccessful = await decryptAndReplaceHtml(hashedPassphrase); const isDecryptionSuccessful = await decryptAndReplaceHtml(hashedPassword);
// if the decryption is unsuccessful the password might be wrong - silently clear the saved data and let // if the decryption is unsuccessful the password might be wrong - silently clear the saved data and let
// the user fill the password form again // the user fill the password form again
@ -195,16 +195,16 @@ function init(staticryptConfig, templateConfig) {
// get the password from the query param // get the password from the query param
const queryParams = new URLSearchParams(window.location.search); const queryParams = new URLSearchParams(window.location.search);
const hashedPassphraseQuery = queryParams.get(passwordKey); const hashedPasswordQuery = queryParams.get(passwordKey);
// get the password from the url fragment // get the password from the url fragment
const hashRegexMatch = window.location.hash.substring(1).match(new RegExp(passwordKey + "=(.*)")); const hashRegexMatch = window.location.hash.substring(1).match(new RegExp(passwordKey + "=(.*)"));
const hashedPassphraseFragment = hashRegexMatch ? hashRegexMatch[1] : null; const hashedPasswordFragment = hashRegexMatch ? hashRegexMatch[1] : null;
const hashedPassphrase = hashedPassphraseFragment || hashedPassphraseQuery; const hashedPassword = hashedPasswordFragment || hashedPasswordQuery;
if (hashedPassphrase) { if (hashedPassword) {
return decryptAndReplaceHtml(hashedPassphrase); return decryptAndReplaceHtml(hashedPassword);
} }
return false; return false;

Wyświetl plik

@ -1,7 +1,7 @@
{ {
"name": "staticrypt", "name": "staticrypt",
"version": "3.2.0", "version": "3.2.0",
"description": "Based on the [crypto-js](https://github.com/brix/crypto-js) library, StatiCrypt uses AES-256 to encrypt your input with your passphrase and put it in a HTML file with a password prompt that can decrypted in-browser (client side).", "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", "main": "index.js",
"files": [ "files": [
"/cli", "/cli",

Wyświetl plik

@ -96,8 +96,8 @@
<div class="col-xs-12"> <div class="col-xs-12">
<form id="encrypt_form"> <form id="encrypt_form">
<div class="form-group"> <div class="form-group">
<label for="passphrase">Password</label> <label for="password">Password</label>
<input type="password" class="form-control" id="passphrase" <input type="password" class="form-control" id="password"
placeholder="Password (choose a long one!)"> placeholder="Password (choose a long one!)">
</div> </div>
@ -137,9 +137,9 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="template_placeholder">Passphrase input placeholder</label> <label for="template_placeholder">Password input placeholder</label>
<input type="text" class="form-control" id="template_placeholder" <input type="text" class="form-control" id="template_placeholder"
placeholder="Default: 'Passphrase'"> placeholder="Default: 'Password'">
</div> </div>
<div class="form-group"> <div class="form-group">
@ -155,7 +155,7 @@
step="any" step="any"
placeholder="Default: 0 (no expiration)"> placeholder="Default: 0 (no expiration)">
<small class="form-text text-muted"> <small class="form-text text-muted">
After this many days, the user will have to enter the passphrase again. Leave empty or set After this many days, the user will have to enter the password again. Leave empty or set
to 0 for no expiration. to 0 for no expiration.
</small> </small>
</div> </div>
@ -166,7 +166,7 @@
</div> </div>
</div> </div>
<button class="btn btn-primary pull-right" type="submit">Generate passphrase protected HTML</button> <button class="btn btn-primary pull-right" type="submit">Generate password protected HTML</button>
</form> </form>
</div> </div>
</div> </div>
@ -277,10 +277,10 @@ Your encrypted string</pre>
CKEDITOR.instances['template_instructions'].updateElement(); CKEDITOR.instances['template_instructions'].updateElement();
const unencrypted = document.getElementById('unencrypted_html').value, const unencrypted = document.getElementById('unencrypted_html').value,
passphrase = document.getElementById('passphrase').value; password = document.getElementById('password').value;
const salt = cryptoEngine.generateRandomSalt(); const salt = cryptoEngine.generateRandomSalt();
const encryptedMsg = await encode(unencrypted, passphrase, salt); const encryptedMsg = await encode(unencrypted, password, salt);
const templateButton = document.getElementById('template_button').value, const templateButton = document.getElementById('template_button').value,
templateInstructions = document.getElementById('template_instructions').value, templateInstructions = document.getElementById('template_instructions').value,
@ -301,7 +301,7 @@ Your encrypted string</pre>
js_staticrypt: getScriptAsString('staticrypt'), js_staticrypt: getScriptAsString('staticrypt'),
template_button: templateButton ? templateButton : 'DECRYPT', template_button: templateButton ? templateButton : 'DECRYPT',
template_instructions: templateInstructions || '', template_instructions: templateInstructions || '',
template_placeholder: templatePlaceholder || 'Passphrase', template_placeholder: templatePlaceholder || 'Password',
template_remember: templateRemember || 'Remember me', template_remember: templateRemember || 'Remember me',
template_title: templateTitle || 'Protected Page', template_title: templateTitle || 'Protected Page',
}; };