kopia lustrzana https://github.com/robinmoisson/staticrypt
better instructions
rodzic
ae0e273cf1
commit
0cdb80a419
20
README.md
20
README.md
|
@ -61,7 +61,7 @@ find . -type f -name "*.html" -not -name "*_encrypted.html" -exec staticrypt {}
|
|||
|
||||
The password argument is optional if `STATICRYPT_PASSWORD` is set in the environment or `.env` file.
|
||||
|
||||
Usage: staticrypt <filename> [<passphrase>] [options]
|
||||
Usage: staticrypt <filename> [<password>] [options]
|
||||
|
||||
Options:
|
||||
--help Show help [boolean]
|
||||
|
@ -73,24 +73,23 @@ The password argument is optional if `STATICRYPT_PASSWORD` is set in the environ
|
|||
-e, --embed Whether or not to embed crypto-js in the page
|
||||
(or use an external CDN).
|
||||
[boolean] [default: true]
|
||||
-f, --file-template Path to custom HTML template with passphrase
|
||||
-f, --file-template Path to custom HTML template with password
|
||||
prompt.
|
||||
[string] [default: "/lib/password_template.html"]
|
||||
[string] [default: "/code/staticrypt/lib/password_template.html"]
|
||||
-i, --instructions Special instructions to display to the user.
|
||||
[string] [default: ""]
|
||||
--label-error Error message to display on entering wrong
|
||||
passphrase. [string] [default: "Bad password!"]
|
||||
password. [string] [default: "Bad password!"]
|
||||
--noremember Set this flag to remove the "Remember me"
|
||||
checkbox. [boolean] [default: false]
|
||||
-o, --output File name/path for the generated encrypted file.
|
||||
[string] [default: null]
|
||||
--passphrase-placeholder Placeholder to use for the passphrase input.
|
||||
--passphrase-placeholder Placeholder to use for the password input.
|
||||
[string] [default: "Password"]
|
||||
-r, --remember Expiration in days of the "Remember me" checkbox
|
||||
that will save the (salted + hashed) passphrase
|
||||
in localStorage when entered by the user.
|
||||
Default: "0", no expiration.
|
||||
[number] [default: 0]
|
||||
that will save the (salted + hashed) password in
|
||||
localStorage when entered by the user. Default:
|
||||
"0", no expiration. [number] [default: 0]
|
||||
--remember-label Label to use for the "Remember me" checkbox.
|
||||
[string] [default: "Remember me"]
|
||||
-s, --salt Set the salt manually. It should be set if you
|
||||
|
@ -104,7 +103,10 @@ The password argument is optional if `STATICRYPT_PASSWORD` is set in the environ
|
|||
value to append "?staticrypt_pwd=<hashed_pwd>",
|
||||
or leave empty to display the hash to append.
|
||||
[string]
|
||||
--short Hide the "short password" warning.
|
||||
[boolean] [default: false]
|
||||
-t, --title Title for the output HTML page.
|
||||
[string] [default: "Protected Page"]
|
||||
|
||||
|
||||
## HOW STATICRYPT WORKS
|
||||
|
|
11
cli/index.js
11
cli/index.js
|
@ -47,10 +47,11 @@ const inputFilepath = positionalArguments[0].toString(),
|
|||
if (password.length < 16 && !namedArgs.short) {
|
||||
console.log(
|
||||
`WARNING: Your password is less than 16 characters (length: ${password.length}). Brute-force attacks are easy to `
|
||||
+ `try on public files, and you are most safe when using a long password. You can hide this warning by increasing `
|
||||
+ `the length or adding the '--short' flag.\n`
|
||||
+ `Here's a strong generated password you could use: `
|
||||
+ `try on public files, and you are most safe when using a long password.\n\n`
|
||||
+ `👉️ Here's a strong generated password you could use: `
|
||||
+ generateRandomString(21)
|
||||
+ "\n\nThe file was encrypted with your password. You can hide this warning by increasing your password length or"
|
||||
+ " adding the '--short' flag."
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -97,9 +98,9 @@ const isLegacy = isCustomPasswordTemplateLegacy(namedArgs.f);
|
|||
if (isLegacy) {
|
||||
console.log(
|
||||
"#################################\n\n" +
|
||||
"[StatiCrypt] SECURITY WARNING: You are using an old version of the password template, which has been found to " +
|
||||
"SECURITY WARNING [StatiCrypt]: You are using an old version of the password template, which has been found to " +
|
||||
"be less secure. Please update your custom password_template logic to match version 2.2.0 or higher." +
|
||||
"\nYou can find the template here: https://github.com/robinmoisson/staticrypt/blob/main/lib/password_template.html" +
|
||||
"\nYou can find instructions here: https://github.com/robinmoisson/staticrypt/issues/161" +
|
||||
"\n\n#################################"
|
||||
);
|
||||
}
|
||||
|
|
38
lib/codec.js
38
lib/codec.js
|
@ -12,23 +12,23 @@ function init(cryptoEngine) {
|
|||
|
||||
/**
|
||||
* Top-level function for encoding a message.
|
||||
* Includes passphrase hashing, encryption, and signing.
|
||||
* Includes password hashing, encryption, and signing.
|
||||
*
|
||||
* @param {string} msg
|
||||
* @param {string} passphrase
|
||||
* @param {string} password
|
||||
* @param {string} salt
|
||||
* @param {boolean} isLegacy - whether to use the legacy hashing algorithm (1k iterations) or not
|
||||
*
|
||||
* @returns {string} The encoded text
|
||||
*/
|
||||
function encode(msg, passphrase, salt, isLegacy = false) {
|
||||
function encode(msg, password, salt, isLegacy = false) {
|
||||
// TODO: remove in the next major version bump. This is to not break backwards compatibility with the old way of hashing
|
||||
const hashedPassphrase = isLegacy
|
||||
? cryptoEngine.hashLegacyRound(passphrase, salt)
|
||||
: cryptoEngine.hashPassphrase(passphrase, salt);
|
||||
? cryptoEngine.hashLegacyRound(password, salt)
|
||||
: cryptoEngine.hashPassphrase(password, salt);
|
||||
const encrypted = cryptoEngine.encrypt(msg, hashedPassphrase);
|
||||
// we use the hashed passphrase in the HMAC because this is effectively what will be used a passphrase (so we can store
|
||||
// it in localStorage safely, we don't use the clear text passphrase)
|
||||
// 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)
|
||||
const hmac = cryptoEngine.signMessage(hashedPassphrase, encrypted);
|
||||
|
||||
return hmac + encrypted;
|
||||
|
@ -41,11 +41,11 @@ function init(cryptoEngine) {
|
|||
*
|
||||
* @param {string} signedMsg
|
||||
* @param {string} hashedPassphrase
|
||||
* @param {boolean} shouldTryBackwardCompatible
|
||||
* @param {string} backwardCompatibleHashedPassword
|
||||
*
|
||||
* @returns {Object} {success: true, decoded: string} | {success: false, message: string}
|
||||
*/
|
||||
function decode(signedMsg, hashedPassphrase, shouldTryBackwardCompatible = true) {
|
||||
function decode(signedMsg, hashedPassphrase, backwardCompatibleHashedPassword = '') {
|
||||
const encryptedHMAC = signedMsg.substring(0, 64);
|
||||
const encryptedMsg = signedMsg.substring(64);
|
||||
const decryptedHMAC = cryptoEngine.signMessage(hashedPassphrase, encryptedMsg);
|
||||
|
@ -54,16 +54,32 @@ function init(cryptoEngine) {
|
|||
// TODO: remove in next major version bump. This is to not break backwards compatibility with the old 1k
|
||||
// iterations in PBKDF2 - if the key we try isn't working, it might be because it's a remember-me/autodecrypt
|
||||
// link key, generated with 1k iterations. Try again with the updated iteration count.
|
||||
if (shouldTryBackwardCompatible) {
|
||||
if (!backwardCompatibleHashedPassword) {
|
||||
return decode(
|
||||
signedMsg,
|
||||
cryptoEngine.hashSecondRound(hashedPassphrase, backwardCompatibleSalt),
|
||||
false
|
||||
hashedPassphrase
|
||||
);
|
||||
}
|
||||
|
||||
return { success: false, message: "Signature mismatch" };
|
||||
}
|
||||
|
||||
// TODO: remove in next major version bump. If we're trying to double hash for backward compatibility reasons,
|
||||
// and the attempt is successful, we check if we should update the stored password in localStorage. This avoids
|
||||
// having to compute the upgrade each time.
|
||||
if (backwardCompatibleHashedPassword) {
|
||||
if (window && window.localStorage) {
|
||||
const storedPassword = window.localStorage.getItem('staticrypt_passphrase');
|
||||
|
||||
// check the stored password is actually the backward compatible one, so we don't save the new one and trigger
|
||||
// the "remember-me" by mistake, leaking the password
|
||||
if (storedPassword === backwardCompatibleHashedPassword) {
|
||||
window.localStorage.setItem('staticrypt_passphrase', hashedPassphrase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
decoded: cryptoEngine.decrypt(encryptedMsg, hashedPassphrase),
|
||||
|
|
|
@ -96,27 +96,6 @@
|
|||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
.staticrypt-footer {
|
||||
position: fixed;
|
||||
height: 20px;
|
||||
font-size: 16px;
|
||||
padding: 2px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.staticrypt-footer p {
|
||||
margin: 2px;
|
||||
text-align: center;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.staticrypt-footer a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
label.staticrypt-remember {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -202,10 +181,6 @@
|
|||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<footer class="staticrypt-footer">
|
||||
<p class="pull-right">Created with <a href="https://robinmoisson.github.io/staticrypt">StatiCrypt</a></p>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue