Skip to content

Commit 228af74

Browse files
committed
use URL fragment for logout/auto-decrypt (closes #156)
1 parent cc37c5c commit 228af74

File tree

8 files changed

+89
-27
lines changed

8 files changed

+89
-27
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ staticrypt test.html --engine webcrypto
4242
**Encrypt a file and get a shareable link containing the hashed password** - you can include your file URL or leave blank:
4343

4444
```bash
45-
# you can also pass '--share' without specifying the URL to get the `?staticrypt_pwd=...`
45+
# you can also pass '--share' without specifying the URL to get the `#staticrypt_pwd=...`
4646
staticrypt test.html MY_LONG_PASSWORD --share https://example.com/test_encrypted.html --engine webcrypto
47-
# => https://example.com/test_encrypted.html?staticrypt_pwd=5bfbf1343c7257cd7be23ecd74bb37fa2c76d041042654f358b6255baeab898f
47+
# => https://example.com/test_encrypted.html#staticrypt_pwd=5bfbf1343c7257cd7be23ecd74bb37fa2c76d041042654f358b6255baeab898f
4848
```
4949

5050
**Encrypt all html files in a directory** and replace them with encrypted versions (`{}` will be replaced with each file name by the `find` command - if you wanted to move the encrypted files to an `encrypted/` directory, you could use `-o encrypted/{}`):
@@ -106,7 +106,7 @@ The password argument is optional if `STATICRYPT_PASSWORD` is set in the environ
106106
you can use: "statycrypt -s". [string]
107107
--share Get a link containing your hashed password that
108108
will auto-decrypt the page. Pass your URL as a
109-
value to append "?staticrypt_pwd=<hashed_pwd>",
109+
value to append "#staticrypt_pwd=<hashed_pwd>",
110110
or leave empty to display the hash to append.
111111
[string]
112112
--short Hide the "short password" warning.
@@ -175,7 +175,7 @@ If no value is provided the stored password doesn't expire, you can also give it
175175

176176
#### "Logging out"
177177

178-
You can clear StatiCrypt values in localStorage (effectively "logging out") at any time by appending `staticrypt_logout` to the URL query parameters (`mysite.com?staticrypt_logout`).
178+
You can clear StatiCrypt values in localStorage (effectively "logging out") at any time by appending `staticrypt_logout` to the URL fragment (`mysite.com#staticrypt_logout`).
179179

180180
#### Encrypting multiple pages
181181

cli/helpers.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ function parseCommandLineArguments() {
297297
.option("share", {
298298
describe:
299299
'Get a link containing your hashed password that will auto-decrypt the page. Pass your URL as a value to append '
300-
+ '"?staticrypt_pwd=<hashed_pwd>", or leave empty to display the hash to append.',
300+
+ '"#staticrypt_pwd=<hashed_pwd>", or leave empty to display the hash to append.',
301301
type: "string",
302302
})
303303
.option("short", {

cli/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ async function runStatiCrypt() {
8888

8989
const hashedPassword = await cryptoEngine.hashPassphrase(password, salt);
9090

91-
console.log(url + "?staticrypt_pwd=" + hashedPassword);
91+
console.log(url + "#staticrypt_pwd=" + hashedPassword);
9292
}
9393

9494
// TODO: remove in the next major version bump. This is to allow a security update to some versions without breaking

example/example_encrypted.html

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,7 @@
564564
const decode = codec.init(cryptoEngine).decode;
565565

566566
// variables to be filled when generating the file
567-
const encryptedMsg = '1c9cbdfdb99a165b6459b329f37250ec99c30c53c5cca71d28e19314268896ec613dc0443a36e38dc5a983145dda064fc7716024e87c32ae5dbe03a888731e53e0869a0e739134d91fb343c0b11c759a2a9f9ac755544274af0fad8959919ad91e285405f9255b9ad8ce83f3f8e13e367c0b061b1bd84df78440a63196469743d34a887819d31111750f0de9d915e85020ca3b4cd209e5ad82678c572fc677642a8884fff4943b6366d4172d515519db96b6476f23066d36ae40b1b3bdd3c69a',
567+
const encryptedMsg = 'df7428ed075decd3c4ff9d8ab6d2bea4410854c863d705789fb22e14b7da7ee20e94c593047abb9ba34d6519eebc879d2097bb918c0af0d4e248959849fb9c6bbb93aba054806c8773d1e4b63ec317185ad5462a9919dda986716c67bb57a89a044de3e25707cded482657c4a0208e9916aaa9d839f090eaaeb95603e05db11fe4bc37c4d98b9170124ce1c7ca18fe39c2f179e23eee61ba7d79cb3145e8833936c62adeffce1f5e129745c89541faa8100bfde4733bfa9c0ecf04768b3d1889',
568568
salt = 'b93bbaf35459951c47721d1f3eaeb5b9',
569569
labelError = 'Bad password!',
570570
isRememberEnabled = true,
@@ -600,6 +600,31 @@
600600
localStorage.removeItem(rememberExpirationKey);
601601
}
602602

603+
/**
604+
* Clear storage if we are logging out
605+
*
606+
* @returns - whether we logged out
607+
*/
608+
function logoutIfNeeded() {
609+
const logoutKey = "staticrypt_logout";
610+
611+
// handle logout through query param
612+
const queryParams = new URLSearchParams(window.location.search);
613+
if (queryParams.has(logoutKey)) {
614+
clearLocalStorage();
615+
return true;
616+
}
617+
618+
// handle logout through URL fragment
619+
const hash = window.location.hash.substring(1);
620+
if (hash.includes(logoutKey)) {
621+
clearLocalStorage();
622+
return true;
623+
}
624+
625+
return false;
626+
}
627+
603628
/**
604629
* To be called on load: check if we want to try to decrypt and replace the HTML with the decrypted content, and
605630
* try to do it if needed.
@@ -614,11 +639,8 @@
614639
// show the remember me checkbox
615640
document.getElementById('staticrypt-remember-label').classList.remove('hidden');
616641

617-
// if we are login out, clear the storage and terminate
618-
const queryParams = new URLSearchParams(window.location.search);
619-
620-
if (queryParams.has("staticrypt_logout")) {
621-
clearLocalStorage();
642+
// if we are login out, terminate
643+
if (logoutIfNeeded()) {
622644
return false;
623645
}
624646

@@ -652,9 +674,18 @@
652674
return false;
653675
}
654676

655-
function decryptOnLoadFromQueryParam() {
677+
function decryptOnLoadFromUrl() {
678+
const passwordKey = "staticrypt_pwd";
679+
680+
// get the password from the query param
656681
const queryParams = new URLSearchParams(window.location.search);
657-
const hashedPassphrase = queryParams.get("staticrypt_pwd");
682+
const hashedPassphraseQuery = queryParams.get(passwordKey);
683+
684+
// get the password from the url fragment
685+
const hashRegexMatch = window.location.hash.substring(1).match(new RegExp(passwordKey + "=(.*)"));
686+
const hashedPassphraseFragment = hashRegexMatch ? hashRegexMatch[1] : null;
687+
688+
const hashedPassphrase = hashedPassphraseFragment || hashedPassphraseQuery;
658689

659690
if (hashedPassphrase) {
660691
return decryptAndReplaceHtml(hashedPassphrase);
@@ -665,7 +696,7 @@
665696

666697
// try to automatically decrypt on load if there is a saved password
667698
window.onload = async function () {
668-
let hasDecrypted = await decryptOnLoadFromQueryParam();
699+
let hasDecrypted = await decryptOnLoadFromUrl();
669700

670701
if (!hasDecrypted) {
671702
hasDecrypted = await decryptOnLoadFromRememberMe();

index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ <h4>
112112
<div class="form-group">
113113
<label class="no-style">
114114
<input type="checkbox" id="remember" checked>
115-
Add "Remember me" checkbox (append <code>?staticrypt_logout</code> to your URL to logout)
115+
Add "Remember me" checkbox (append <code>#staticrypt_logout</code> to your URL to logout)
116116
<small>
117117
<abbr class="text-muted"
118118
title="The password will be stored in clear text in the browser's localStorage upon entry by the user. See &quot;More options&quot; to set the expiration (default: none)">
@@ -616,7 +616,7 @@ <h2>Encrypted HTML</h2>
616616

617617
/**
618618
* Register something happened - this uses a simple Supabase function to implement a counter, and allows use to drop
619-
* google analytics. We don't store the IP or any personal information.
619+
* google analytics.
620620
*
621621
* @param action
622622
*/

lib/password_template.html

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,31 @@
231231
localStorage.removeItem(rememberExpirationKey);
232232
}
233233

234+
/**
235+
* Clear storage if we are logging out
236+
*
237+
* @returns {boolean} - whether we logged out
238+
*/
239+
function logoutIfNeeded() {
240+
const logoutKey = "staticrypt_logout";
241+
242+
// handle logout through query param
243+
const queryParams = new URLSearchParams(window.location.search);
244+
if (queryParams.has(logoutKey)) {
245+
clearLocalStorage();
246+
return true;
247+
}
248+
249+
// handle logout through URL fragment
250+
const hash = window.location.hash.substring(1);
251+
if (hash.includes(logoutKey)) {
252+
clearLocalStorage();
253+
return true;
254+
}
255+
256+
return false;
257+
}
258+
234259
/**
235260
* To be called on load: check if we want to try to decrypt and replace the HTML with the decrypted content, and
236261
* try to do it if needed.
@@ -245,11 +270,8 @@
245270
// show the remember me checkbox
246271
document.getElementById('staticrypt-remember-label').classList.remove('hidden');
247272

248-
// if we are login out, clear the storage and terminate
249-
const queryParams = new URLSearchParams(window.location.search);
250-
251-
if (queryParams.has("staticrypt_logout")) {
252-
clearLocalStorage();
273+
// if we are login out, terminate
274+
if (logoutIfNeeded()) {
253275
return false;
254276
}
255277

@@ -283,9 +305,18 @@
283305
return false;
284306
}
285307

286-
function decryptOnLoadFromQueryParam() {
308+
function decryptOnLoadFromUrl() {
309+
const passwordKey = "staticrypt_pwd";
310+
311+
// get the password from the query param
287312
const queryParams = new URLSearchParams(window.location.search);
288-
const hashedPassphrase = queryParams.get("staticrypt_pwd");
313+
const hashedPassphraseQuery = queryParams.get(passwordKey);
314+
315+
// get the password from the url fragment
316+
const hashRegexMatch = window.location.hash.substring(1).match(new RegExp(passwordKey + "=(.*)"));
317+
const hashedPassphraseFragment = hashRegexMatch ? hashRegexMatch[1] : null;
318+
319+
const hashedPassphrase = hashedPassphraseFragment || hashedPassphraseQuery;
289320

290321
if (hashedPassphrase) {
291322
return decryptAndReplaceHtml(hashedPassphrase);
@@ -296,7 +327,7 @@
296327

297328
// try to automatically decrypt on load if there is a saved password
298329
window.onload = async function () {
299-
let hasDecrypted = await decryptOnLoadFromQueryParam();
330+
let hasDecrypted = await decryptOnLoadFromUrl();
300331

301332
if (!hasDecrypted) {
302333
hasDecrypted = await decryptOnLoadFromRememberMe();

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "staticrypt",
3-
"version": "2.5.0",
3+
"version": "2.6.0",
44
"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).",
55
"main": "index.js",
66
"files": [

scripts/index_template.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ <h4>
112112
<div class="form-group">
113113
<label class="no-style">
114114
<input type="checkbox" id="remember" checked>
115-
Add "Remember me" checkbox (append <code>?staticrypt_logout</code> to your URL to logout)
115+
Add "Remember me" checkbox (append <code>#staticrypt_logout</code> to your URL to logout)
116116
<small>
117117
<abbr class="text-muted"
118118
title="The password will be stored in clear text in the browser's localStorage upon entry by the user. See &quot;More options&quot; to set the expiration (default: none)">

0 commit comments

Comments
 (0)