[HN Gopher] Password protect a static HTML page ___________________________________________________________________ Password protect a static HTML page Author : mooreds Score : 246 points Date : 2023-02-18 17:44 UTC (5 hours ago) (HTM) web link (github.com) (TXT) w3m dump (github.com) | Karellen wrote: | Or... http authentication. | edent wrote: | How do you use that on something like GitHub pages? | marginalia_nu wrote: | Turns out when you give up the work of hosting your up stuff, | you also give up some of the benefits from doing so. | forrestthewoods wrote: | Which is why a project that returns some of those benefits | is genuinely cool and useful. | johannes1234321 wrote: | And even can give benefits by storing it encrypted at | rest. | Dma54rhs wrote: | You can email or hand out physical copies on usb would be one | use case where server auth can't compete. | Karellen wrote: | Aren't existing encryption tools more flexible for sending | out copies via those methods? e.g. by making more cipher | suites available? Or by allowing you to encrypt with the | intended recipients' public keys, so you don't need to worry | about distributing the passphrase securely? And might allow | better integration with password managers, as the OS would | recognise the files as being encrypted? | layer8 wrote: | Supposedly browsers are more ubiquitous on the recipient | side than whatever other tools you might use. | Karellen wrote: | I was thinking of editing my comment to add "Or be able | to support filetypes other than HTML", but I suppose in | our glorious "everything is the browser" future, | filetypes other than HTML are as anachronistic as 8" | floppy disks. | | Sigh. | layer8 wrote: | FWIW, you can use data URLs to include any type of file | in your HTML, and with <a download='filename' | href='data:...'> browsers will allow you to save the | file. | ipaddr wrote: | Use apache to serve your page and htpasswd to provide basic | authentication. Easy 1994 answer | mik1998 wrote: | Also NGINX auth basic option. I use it on my personal website. | | https://docs.nginx.com/nginx/admin-guide/security-controls/c... | Gordonjcp wrote: | I thought that too, but this appears like it works to password | protect an html file that's *not* being served off a server. | This ought to work with a file on disk too. | userbinator wrote: | The more general solution is to use a password-protected | archive. | fabiensanglard wrote: | A more lightweight solution would be to hash the password and | have a copy of that file at this url. | | windows.location = hash(password); | hosteur wrote: | Wow I like that. So simple and elegant. Could be combined with | a username to produce unique urls per user. | pyrolistical wrote: | A miss configured http server that allows directory listing | would compromise everything. | | Also now all intermediate things that have access to the | hashed url would suddenly have access to a secure piece of | information. | | Don't be clever with security | cozzyd wrote: | You can always put an index.html to prevent that mistake. | pyrolistical wrote: | Their solution intends for the static file to be copied offline | pdq wrote: | Client side decryption has the benefit that no machine or | router in the middle can view or cache the decrypted page | without the password. | tptacek wrote: | You mean, unless they tamper with the Javascript to capture | the password (or the derived key). | dividuum wrote: | I designed a similar tool with that threat model in mind: | the resulting HTML/JS is as minimal as possible so it's | possible to inspect before entering the password. Of course | assumes safe browser and client machine.. | https://github.com/dividuum/html-vault | madduci wrote: | A more lightweight solution would be to let the Webserver | (nginx, https, whatever) password-protect the site. | | No JavaScript required a d highly efficient | fragmede wrote: | Requiring some sort of VM or container to run this webserver | on? Is it possible that's way more onerous than a static html | file which can be emailed around? Are you sure nginx is even | going to be around in, say, 15 years? (think password | protected PDF but in html and allowing for JavaScript.) | [deleted] | victorbjorklund wrote: | Wow. This is really cool. I wonder if it would be possible to | kind of build a site with personal pages etc for different user | each encrypted by their own password | | Like domain.com/user1 and domain.com/user2 each are encrypted but | with their own passwords. So user 1 can only visit his own page | and not other users. | | (I know there would be much easier to just do a traditional | webapp but as a concept it is super cool). | efrecon wrote: | I am using it in exactly that context and it is good enough for | the level of security I need to achieve. I understand this can | be brute forced, but this is a risk I am willing to take given | the level of "secrecy" of the content. | eduction wrote: | Hey look it's a "static" HTML file that decrypts itself using AES | 256 CBC. Sure, that sounds static and simple and good for the | web. What could go wrong. | | Some obvious limitations: | | -requires users to re-authenticate for every protected file on | your site | | -assets loaded by the page not password protected | | -uses a single password globally shared by everyone who wants to | read the doc | | -archiving the page itself is useless unless you also archive the | password, which must be done out of band | | -this doesn't compose or integrate with the web: none of the | common tools you would use to download, spider, archive, spindle, | mutilate web pages know how to deal with this | | It's certainly one solution. The http basic auth built into every | popular webserver is another, with none of the above limitations. | But I guess that would require spending 5 minutes learning and | implementing some server config, and why do that when you can | further ruin the web by shoving yet more user hostile complexity | into client side JavaScript. | | Sorry to sound bitter I just feel this is a really bad idea if | you think about it for any length of time. | dakiol wrote: | > The http basic auth built into every popular webserver is | another, with none of the above limitations. | | The obvious advantage of OP's approach is that one doesn't need | to control the server that serves the HTML (e.g., static site | served via GitHub pages would be enough) | superkuh wrote: | [flagged] | tptacek wrote: | If that's wrong, so is the name of every "static site | generator". Also: please don't make the same point in two | separate top-level comments. | superkuh wrote: | A static site generator can be used to create an .html file | that's dependent on the user to execute a javscript web | application to show the content. That makes that generated | page dynamic. It doesn't change the nature of the static site | generator. | [deleted] | tantalor wrote: | The js is static too | minusf wrote: | funnily enough in certain circles "static pages" rather mean | "static on server side" but "dynamic on client side". | danShumway wrote: | Hah, this is another thing I've been thinking about recently :) | It's cool to see tools like this popping up. | | An approach I've played around with, but never sat down to | actually build, was to use service workers to be able to encrypt | large sites -- the entire site would be encrypted locally from | the command line using libsodium's `crypto_secretbox_easy`[0], | and all of the data would be concatenated into a series of padded | files to try and somewhat hide the number of files/size of the | site. That key would be merged with a lookup table that would | also be encrypted with a separate key, that would be stuck in the | url hash. Then once the site was decrypted (ie, the secretbox key | was sent to the service worker from the url) the service worker | would intercept any requests the the front-end made and decrypt | the original map that would tell it which file chunks to fetch, | and then it would decrypt them on the fly and cache them for the | duration of the session. Whenever you updated the site, the files | would be re-encrypted with another key, but the "user facing" key | in the URL would stay the same. | | The linked project (and other projects people have linked) are a | lot more portable, but I was thinking less about being able to | have a single file that I carried around and more about being | able to put up a full website where I could have something | approximating user accounts (ie, possibly having multiple lookup | tables that could be decrypted separately per-user), and where I | could build full-featured projects that could fetch their own | resources. | | But, I haven't ever gotten around to actually building it, I only | ever built some tests to make sure that it would technically | work, and I got nervous about rolling my own solution even though | I was just going through the libsodium APIs. | | ---- | | [0]: I've seen a couple of people recommend using Web Crypto | instead, which I've avoided because I thought libsodium ported to | the browser was harder to shoot myself in the foot with; is that | a bad instinct? | CM30 wrote: | Oh neat, this is a neat concept. Always wanted a secure way to | password protect a page without server side coding, and this is | definitely the closest we've gotten in years. | | Not sure I'd trust it myself, but it definitely seems like a good | option for those with limited hosting options (like GitHub pages | or Neocities) and a need to secure some content. | snake_doc wrote: | Similar to portable-secret? https://github.com/mprimi/portable- | secret | realPubkey wrote: | Should have used the WebCrypto API instead of the crypto-js npm | package. https://developer.mozilla.org/en- | US/docs/Web/API/Web_Crypto_... | fifafu wrote: | WebCrypto only works in secure contexts (https), which is a | significant limitation for some use cases. But I agree it | should be an option. | iamben wrote: | I spent some time Googling this about 6 months ago. Lots of | tutorials on Crypto-js, not so many (and almost zero "here's a | super simple implementation") for WebCrypto API. I can | understand if this is a hobby project why you'd lean into one | rather than the other, I probably would have done the same. | cgb223 wrote: | Sounds like a golden opportunity for someone with a developer | blog to make useful content | trusz wrote: | Not going to pretend that I know what the most of the stuff | mean, or if it is even safe enough, but I've followed the MDN | articles and put together this TypeScript snippet [1]. Maybe | somebody could comment on it? | | Also sorry for the long link. Is there any accepted way to | post a shorted URL? | | Edit: added a corrected version [2] | | [1]: https://www.typescriptlang.org/play?#code/DYUwLgBAbiDGYH | sBOE... | | [2]: https://www.typescriptlang.org/play?#code/FAiGGcE8DsGMAI | BmBX... | tptacek wrote: | If you call "encrypt" more than once in that code, you'll | leak the authentication key. Every invocation of GCM | encryption needs a unique nonce. Cryptography nerds will | chastise you for using a random nonce (there theoretically | isn't enough room in the GCM nonce space to safely encrypt | large numbers of message with random nonces), but the | alternative (using a counter) is even more hazardous. This | problem motivates a lot of people to use other AEADs like | XChapoly, which has an extended nonce space that safely | admits random nonces. Isn't cryptography fun? | ThePhysicist wrote: | It's still considered safe to call AES-GCM with a single | key and a randomly generated nonce 2^32 times [1], most | practical systems don't come anywhere near this limit. | And there's AES-GCM-SIV that solves nonce reuse (mostly), | though it's not available in the Web Cryptography API at | the moment. | | 1: https://csrc.nist.gov/csrc/media/Projects/crypto- | publication... | tptacek wrote: | I don't personally care, and probably wouldn't even | sev:info a random GCM nonce in an assessment, but I would | also choose extended-nonce Chapoly in preference to GCM | in part because of this issue. | majou wrote: | From what I shallowly researched; GCM's nonce seems | limited to 12 bytes by convention only. That nonce reuse | is so fatal seems absurd to me. | | Would "salting" the key safely tackle the problem? | | Put explicitly; send <- nonce || salt || | ciphertext recv -> decrypt(ciphertext, nonce, | pbkdf(pass) || salt) | | [edit: apply salt outside of the kdf] | tptacek wrote: | As I remember it, the balance of the bytes in the AES | block are used for the counter. At any rate, the | convention is essentially universal. | majou wrote: | Sounds above my (current) head. | | Here I thought GCM was some modern foolproof/footgunless | design. | tptacek wrote: | It is sort of infamously footgunny. | trusz wrote: | Oh yes! Thank you for the feedback. I've added a new | version where the `iv` and the `salt` is random. Maybe a | followup question: Because you need both the `iv` and | `salt` to decrypt the message is it ok in an E2E scenario | to send all three: `iv`, `salt` and the encrypted | message? | tptacek wrote: | I didn't look to see what "salt" means in your design, | but the idiom for using GCM in message encryption is to | send ciphertexts that take the form `nonce || | ciphertext`, and to decrypt by reading the nonce off the | front of the message. | dividuum wrote: | Mine does: https://github.com/dividuum/html-vault/ | paulpauper wrote: | What is the major difference? Isn't crypto-js still secure? | Xeoncross wrote: | One is a Javascript package, the other is a browser library | following a spec that is implemented by all the major browser | companies. | | Web Crypto is faster and has many more devs working in the | different implementations between all the companies and | doesn't require any includes. | lucideer wrote: | It might be. Whereas the native lib should be. | | Just levels of trust. I'd happily use the former if the | latter didn't exist. | irrational wrote: | Why use a library (thus incurring the need for the user to | download more JS) instead of using what is already in their | browser? | tptacek wrote: | I don't know what "secure" means. Is their implementation of | OFB correct? Probably. But using OFB mode is itself a | problem. From what I can see, crypto-js implements no | authenticated modes, and exposes all sorts of crufty old | things nobody should be using. The parent comment suggesting | WebCrypto is correct in this case. Avoid crypto-js. | [deleted] | bitexploder wrote: | The use case for a document like this is a little different from | .htaccess. This is something you can share, email, host, etc and | have some security in transit and at rest. Yes, .htaccess | password protects on the web server, but that is one specific use | case and requires a lot of machinery and specific environment. | JavaScript is everywhere. And this is a static HTML document in | the sense that there is no server side rendering. | ipaddr wrote: | Why not use a password protected word document if those are | your use-cases? | creata wrote: | You definitely could. But I think there are more computers | with web browsers than there are computers that can read | encrypted Microsoft Word documents. | [deleted] | adamcharnock wrote: | I saw a super simple example of this back in the 90s when I was | first leaning web development (was in Web Development for Dummies | or some such). | | The page prompted the user for the password, and then used the | password to generate the URL for the hidden page and redirected | the user there. Of course this wasn't over HTTPS, and you got a | 404 if you entered the wrong password, but it was still a neat | hobbyist trick for the era. I think the author even wagered that | readers couldn't defeat it. | aflag wrote: | That was very popular back then. Besides the 404, it has the | side effect that if that URL leaked, then your password system | broke. With this implementation leaking the page is not a big | deal (assuming you're not using it to store state secrets or | anything like that) | VincentEvans wrote: | Can someone explain a bit more how "remember me" works? If | symmetric encryption requires a "key" to decrypt - one might | expect that you will need to store that key to auto-decrypt. But | here it claims that the key is stored salted and hashed. But to | auto-decrypt - you need to reverse that salt and hash because you | need that key back. How would that work? | worldsavior wrote: | The title is a bit misleading. The title implies ONLY HTML when | it uses some JS. I guess it's not possible (in anyway I know) | without some JS, but still. | VoidWhisperer wrote: | The downside to this method is that since the resulting | cryptographic hash and salt have to be in the resulting file, so | there is nothing stopping someone from pulling the hash/salt out | and bruteforcing it locally (as opposed to being able to | ratelimit login attempts on a server) if they are so inclined and | have the required resources.. which may not be that much in the | way of resources as the tool uses 1000 iterations of PBKDF2[1]. | This is magnitudes lower than what OWASP recommends[2]. | | I wouldn't personally put anything you want secure behind this. | | [1]: | https://github.com/robinmoisson/staticrypt/blob/5dac008ba644... | [2]: | https://cheatsheetseries.owasp.org/cheatsheets/Password_Stor... | 411111111111111 wrote: | The linked readme agrees with that | https://github.com/robinmoisson/staticrypt#is-it-secure | [deleted] | dakiol wrote: | Is it a downside if the password is a 100 characters-long | string? | [deleted] | tialaramex wrote: | Right but all that's happening here is stretching. So the | difference only matters in the middle. Regardless of the | strategy bad guys will guess "1234" or "sesame" (too easy) and | they won't guess a random 128-bit key I just generated with my | hexadecimal dice (impossible). This weakness only means it's | easier than expected to guess your password is "suckitelon" or | "GoCowboys1978" or whatever | | We put a lot of effort into teaching people to do better | stretching, but it feels like the result was they put even | _more_ passwords on things, rather than using the breathing | room to get off passwords. If your project for 2023 is "Use a | fancier password hash" instead of "Get rid of passwords" you | are Doing It Wrong(tm). | | If you wanted to do something like this seriously, consider | hmac-secret extension to FIDO, which means Security Keys (so | the things you'd use to log in to say Google or Facebook) can | present an arbitrary always-identical secret value which would | be more than adequate to secure such a thing unlike a human | memorable password. Today hmac-secret is mostly used to | authenticate to an off-line laptop PC or similar. | ipaddr wrote: | Your 128 key is difficult for users to enter manually. | d-z-m wrote: | Last I heard WebAuthn didn't have access to hmac-secret or | prf outside of a Chrome canary. Has this changed recently? | maxlaumeister wrote: | I'm going to plug my project PageCrypt here too, which predates | StatiCrypt, has a web UI that's good for one-off page encryption, | and _does_ use the WebCrypto API. | | https://github.com/MaxLaumeister/pagecrypt | | https://www.maxlaumeister.com/pagecrypt/ | charles_f wrote: | Shameless plug, I did something similar in a markdown processor | (which processes any folder with some markdown into an html | website). You can either protect some of the pages, or the entire | thing | | https://github.com/cfe84/plaf | Retr0id wrote: | For anyone else wondering what the KDF is, it appears to be | PBKDF2 with 1000 iterations: | | https://github.com/robinmoisson/staticrypt/blob/5dac008ba644... | benatkin wrote: | Here's one w/ 100_000. Perhaps it's missing a couple zeroes. | | https://github.com/yjs/y-webrtc/blob/master/src/crypto.js#L2... | superkuh wrote: | If you have to run javascript it is not a static page anymore. | I've seen a lot of this particularly weird overloading of "static | HTML" lately. Static HTML, or static webpage, is meant to | describe the experience from the person who is trying to look at | the page. It does not describe the experience of the dev. | | Using a dynamic script or application to generate a static html | page that requires no JS execution is a static page. | | Using a static HTML page and then hiding it behind javascript | execution is explicitly not a static HTML page. | | Use .htaccess. And if you can't, reconsider the choices you made | that restrict your abilities so significantly. | cubefox wrote: | I would call any server side or client side code which alters | the HTML non-static. A static HTML page is just an HTML file | which is stored on the server and displayed as-is in the | browser. | superkuh wrote: | Exactly. I don't know where the confusion is, but I'm saying | that it doesn't matter how the page is generated. It is sent | to the website visitor as just HTML. When the user views it | it is all there, just html. No changes. | | For example, I have a perl script that generates a set of | .html files every night to show new additions to my library. | They are static .html files on disk and never modified before | the user views them. Just because a perl script (not | connected to the web server in any way) made it does not | "taint" the HTML so it is not static. The program, or the | person, that wrote the HTML does not matter. All that matters | is that it's just static unchanging HTML. | drowsspa wrote: | Everyone is allowed to give their own meaning to words, but | you can't expect to just change a widely agreed meaning to | match it. "Static" means it is just a set of files. Not | that the page is stationary. Do you think that a blink tag | in a HTML page makes it non-static? A hover effect? An | :after pseudoelement in CSS? | | If your perl script is saving the HTML to the disk, then | yeah, your website is static. If it's generating HTML on | the fly, it's dynamic. That's the widely agreed upon | meaning, and that's it. | scarface74 wrote: | That's not a generally accepted as the definition of a static | page. | | https://docs.aws.amazon.com/AmazonS3/latest/userguide/Websit. | .. | | > You can use Amazon S3 to host a static website. On a static | website, individual webpages include static content. They | might also contain client-side scripts. | | By contrast, a dynamic website relies on server-side | processing, including server-side scripts, such as PHP, JSP, | or ASP.NET. Amazon S3 does not support server-side scripting, | but AWS has other resources for hosting dynamic websites. To | learn more about website hosting on AWS, see Web Hosting. | mtlynch wrote: | > _If you have to run javascript it is not a static page | anymore. I 've seen a lot of this particularly weird | overloading of "static HTML" lately. Static HTML, or static | webpage, is meant to describe the experience from the person | who is trying to look at the page. It does not describe the | experience of the dev._ | | I don't think this has been the common meaning of "static page" | for at least 10 years. | | From Wikipedia [0]: | | > _A static web page (sometimes called a flat page or a | stationary page) is a web page that is delivered to the user 's | web browser exactly as stored_ | | Static refers to the fact the files are served without any | application-level processing on the server side beyond simple | file serving. A page can depend on CSS/JS/WASM and still be a | static page. | | [0] https://en.wikipedia.org/wiki/Static_web_page | RobotToaster wrote: | OP said static _HTML_ page though, that very much means | something only using static as opposed to dynamic HTML. | | https://en.wikipedia.org/wiki/Dynamic_HTML | | "DHTML allows scripting languages to change variables in a | web page's definition language, which in turn affects the | look and function of otherwise "static" HTML page content | after the page has been fully loaded and during the viewing | process. Thus the dynamic characteristic of DHTML is the way | it functions while a page is viewed, not in its ability to | generate a unique page with each page load. | | By contrast, a dynamic web page is a broader concept, | covering any web page generated differently for each user, | load occurrence, or specific variable values. This includes | pages created by client-side scripting and ones created by | server-side scripting (such as PHP, Python, JSP or ASP.NET) | where the web server generates content before sending it to | the client." | superkuh wrote: | >A static web page (sometimes called a flat page or a | stationary page) is a web page that is delivered to the | user's web browser exactly as stored" | | Right. "exactly as stored" It doesn't matter who or what | wrote the HTML. I could do it by hand or maybe use a WYSIWYG | editor to make it or maybe it's generated by a script. The | point is that there's an html file sitting on disk and the | server delivers it without modification and it's viewable in | the browser as it. It's just the webserver sending the | contents of the file. | | Whereas this "Password protected a static HTML page" cannot | be viewed in the browser without a "web application", the | javascript, dynamically changing the file. It's pretty clear | cut. So it fails the test of the very link you posted: | | >in contrast to dynamic web pages which are generated by a | web application | [deleted] | Bytewave81 wrote: | It's really not "clear cut." By the definition which you | agree with, an HTML file containing JavaScript is served to | the client without modification, and is viewable in any | modern browser with a functioning JavaScript engine. The | "web application" in reference is a server-sided | application which controls and renders the content, as can | be assumed based on context from the rest of that page. | Namely: | | > Any personalization or interactivity has to run client- | side, which is restricting. | mtlynch wrote: | >>A static web page (sometimes called a flat page or a | stationary page) is a web page that is delivered to the | user's web browser exactly as stored" | | >Right. "exactly as stored" It doesn't matter who or what | wrote the HTML. I could do it by hand or maybe use a | WYSIWYG editor to make it or maybe it's generated by a | script. | | Yes, agree. | | >The point is that there's an html file sitting on disk and | the server delivers it without modification and it's | viewable in the browser as it. | | No, I don't think that's the widely understood | interpretation of "static web page." | | Even the definition you agree with just says the file is | _delivered_ as-is. It says nothing about how the browser | renders the page. | snowwrestler wrote: | The title says "static HTML page" not "static web page". | | JavaScript is not HTML. | RobotToaster wrote: | Neither is CSS, if you want to be pedantic. | matsemann wrote: | I think your definition of a static web page is different from | the common one? | | In my head, a static page is something that's served verbatim, | without some backend generating it or inserting things into a | template. | | Wikipedia seems to agree with that view: | https://en.wikipedia.org/wiki/Static_web_page | superkuh wrote: | That's exactly what I said. It doesn't matter if I wrote the | HTML by hand or I had a perl, or bash, or compiled c program | make it. It's just an HTML file. | [deleted] | meghan_rain wrote: | Lol no. If you HTML is generated, it's by definition not | static anymore. | | Otherwise, all of the React server side rendering is static | HTML. | superkuh wrote: | Oh, so when I make an .html file in Dreamweaver WYSIWYG | HTML editor and save the .html file to my websever ~/www/ | dir it is automatically not a static page anymore because | I used a program to generate it? This is a very wild and | weird interpretation of 'static site' that does not fit | with existing usage. | Kiro wrote: | You are the last person to have a say in that considering | your incorrect take that JS can't be static. You're | clearly misaligned with common usage of terms. | GeneralTspoon wrote: | No, because React is dynamically generating the HTML on | the fly. | | If you pre-compile the HTML using something like Jekyll, | so that the webserver is just serving HTML files without | any dynamic/on-the-fly processing at request time, then | it's considered static. | matsemann wrote: | React server side rendering: most likely dynamic | | React on the client side: static, as you still got the | same files served, how they dynamically alter the page | runtime doesn't count. | shawabawa3 wrote: | You're incorrect | | CSS and JavaScript and images are also static, it doesn't | have to be just HTML | | If you have a perl or bash or c backend generating html in | response to http requests it's not static | superkuh wrote: | You're assuming this is a backend. It is not. Do you | consider generating an HTML file in a WYSIWYG editor | like, say, "Dreamweaver" that outputs an .html no longer | static because it was made by a program? That's absurd. | vore wrote: | You can put client-side JavaScript fine in "just an HTML | file"? | [deleted] | mytailorisrich wrote: | It can be html, css, javascript, whatever. | | 'Static' means it's only made of static files that can be | served by just a vanilla Web server (i.e. just by serving | static files). | swatcoder wrote: | HTML includes the content of style and script elements | (among many others) and the results of whatever they do. | | The combination of _all_ of these direct a browser in how | to render a page. | | Traditionally, a static site or static page is one whose | data can be delivered to the client directly as stored, | with no _server-side_ alterations or generation. | | This is/was a meaningful distinction because a server that | can stream stored data is fundamentally much simpler than | one that executes programs. Such a server can run in | different contexts, be optimized in different ways, and | satisfies constraints that allow further optimizations | downstream. | creatable wrote: | This is nonsense semantics. Words and phrases change meaning | over time. | scarface74 wrote: | It didn't even "change meaning" | | As far back as I remember (and I played with JavaScript when | it was first introduced in beta for Netscape), a "static web | page server" always meant that there was no backend server | generating pages on the fly. | Karellen wrote: | I think "static" and "dynamic" can reasonably be used to | describe both server-side and client-side behaviour, and I | don't think that the dual meaning is particularly new. | | Yes, "Dynamic HTML" vs "Static HTML" to refer to JS-dependent | and JS-free pages respectively has been around since the dawn | of javascript, but my copy of the 1996 O'Reilly _CGI | Programming on the World Wide Web_ by Gundavaram contains | sentences like | | "Virtual, or dynamic, document creation is at the heart of CGI" | (p.4) | | "A common use for [server redirection] is to return a generic | document that contains static information. [...] Suppose you | have an HTML file ( _thanks.html_ ) like the one below, that | you want to display after the user fills out one of your forms: | [...] You could use the programs discussed earlier to return | static documents, but [...] it is much quicker and simpler to | [redirect with a "Location" header]." (pp.44-45) | | ...without mentioning javascript anywhere. | Timon3 wrote: | You're interpreting the title as "a static HTML page with | password protection", but the way I understood it is | "statically hostable version of a static HTML page with | password protection", which seems to be exactly what this | implements. I'm probably biased because I would have frequently | had use for this, and all the paid offerings mention "private | hosting of static pages", but I feel you're a bit uncharitable | with your interpretation. | | If you want to just have a free small private static page which | is easily updated by public CI offerings this is a great | solution, and the title transports this clearly. | [deleted] | pierrec wrote: | That is not correct. As long as the javascript is run on the | client-side, it's a static page. Static simply means the files | on the server are sent directly to the client. The client can | then do whatever they want with the files. | | The expression "dynamic" was trending a decade or two ago to | vaguely refer to javascript+HTML5. It was never the opposite of | "static" in this domain. | dymk wrote: | Title is still accurate, the tool is for password protecting a | static HTML page. The page starts out as a static HTML page. | Then this tool generates something that has password protected | it. | voytec wrote: | > If you have to run javascript it is not a static page anymore | | I understand static pages as files sent to a browser without | having to be generated server-side. | rwalle wrote: | Right. This concept has existed for decades, and people | should figure out what it actually means before complaining. | [deleted] | anurag wrote: | Pagecrypt does the same thing, but with the Web Crypto API. More | (including a sample repo) at https://render.com/blog/static-site- | auth-pagecrypt. | sowbug wrote: | Similar here: https://github.com/sowbug/quaid | | It works with a GPG-encrypted file. I figured that was safer | than developing my own encryption format. As it is, any | vulnerability in the decryption process is equivalent to a | vulnerability in GPG. | [deleted] | Yenrabbit wrote: | Does anyone know of a way to do something like this but with | OAuth? E.g. log in with GitHub to view these docs. | denysvitali wrote: | I'd say it's not possible in pure HTML + JS (as in, encryption/ | access control performed entirely there). | | The solution (with a server) is: | https://oauth2-proxy.github.io/oauth2-proxy/ | pier25 wrote: | Anyone remembers .htaccess files from Apache? Good times. | johannes1234321 wrote: | Those would be quite nice, if web browsers were good HTTP | clients. | | The user experience with basic auth is not so good. The dialogs | give little way to customize and providing information for | user. No support for logout or any form of password changes. | marginalia_nu wrote: | Isn't that sort of a feature? Customizable HTTP auth dialogs | are a security liability, as they blur the line between | content and browser. | johannes1234321 wrote: | Yes and no. There is some part of it which helps to | identify where you are connecting to. Meanwhile those | dialogs aren't modal anymore, which allows access to https | certificate info, but it is still complicated to provide | trust for average users. | tqkxzugoaupvwqr wrote: | Logout is possible: The server has to send http status 401 if | I recall correctly. The browser treats this as logout. | johannes1234321 wrote: | This requires some server side handling. The web browser | could have a logout button so I can end my session. | Probably that should be combined with a configured target | page for the user. | | And well, my experience there is about 20 years old, but | back then sending 401 wasn't enough. You had to send a | different auth request, which then would pop up a new | password dialog first. Indoubt 401 is enough today as well, | as the browser can't distinguish whether a specific | resource is restricted or whether the whole session should | be invalidated. | eduction wrote: | Take one shot if you thought this was going to be about .htaccess | and a second if you're confused why it wasn't. | ab8 wrote: | This solution has no street cred | Xeoncross wrote: | I'm not a cryptographer, but I'm pretty sure that CBC | (https://github.com/robinmoisson/staticrypt/blob/main/lib/cry...) | should be replaced with GCM (https://developer.mozilla.org/en- | US/docs/Web/API/SubtleCrypt...) since this is not a stream. | | https://security.stackexchange.com/questions/184305/why-woul... | | (also, use the built-in WebCrypto API instead of the crypto-js | package) | dragontamer wrote: | CBC is far easier to implement than GCM mode. | | I bet that most programmers cannot implement a Galois Field in | Javascript. Meanwhile, CBC is just "encrypt then xor". | tptacek wrote: | Nobody implements GCM themselves; they get it from a library. | CBC, implemented the way you're describing, is almost always | insecure. | dragontamer wrote: | And the library they use doesn't have GCM mode. | | So now what? | | https://cryptojs.gitbook.io/docs/ | | Because CBC mode is easier to implement, you'll find it in | far more libraries. And honestly, if your underlying block- | cipher is secure (that's the hard part: where your side- | channels all exist), then CBC mode is really the easy part | and can be safely implemented yourself. It really is that | simple. | | ----------------- | | CBC doesn't have authentication. So add on an HMAC. Done. | It takes up a few more bytes but that's not a big deal | these days. | tptacek wrote: | So use WebCrypto, instead of the cabinet of curiosities | that is crypto-js. (Or, better yet, don't do stuff like | this at all, because a browser window is simply an awful | setting for serious cryptography). | fifafu wrote: | WebCrypto only works in secure contexts which is a | significant limitation (https origins only) | tptacek wrote: | Your next best bet might be sjcl. | d-z-m wrote: | If you're talking about sending these files around via | email/messenger, most browsers treat localhost as a | secure context, so this doesn't seem like _that_ | significant of a limitation. | | If you are serving out an encrypted HTML page insecurely, | your users are already hosed, because someone on the path | could inject a script that sends the password to | evil[.]com when they type it in. | password11 wrote: | > _CBC is far easier to implement..._ | | Never implement your own cryptography. | | Edit: | | In fact an incorrect implementation _of CBC mode_ famously | caused a vulnerability in Microsoft 's ASP.NET in 2010 | (https://learn.microsoft.com/en-us/security- | updates/securityb...). The margin for error is small and even | subtle mistakes or incorrect design can cripple security. | Even Microsoft got it wrong once (although they handled | remediation very well). | dragontamer wrote: | Or... you can have a more nuanced viewpoint and note that | CBC is really, really, really easy to implement, and | _really_ doesn't fall into that category of discussion. | | The reason you don't implement your own block ciphers is | because side-channel attacks are damn near impossible for | normal programmers to understand. Especially timing | attacks. | | But block-modes of operation? Some of them are really easy. | I've ever heard of a bad implementation of CBC causing a | security bug. | | ------- | | I'd say you shouldn't implement your own GCM mode. GCM is | quite complex, and the Galois Field's authentication bits | could be side-channeled if you don't know what you're | doing. | | CBC? Where's the flaw? Its so stupid simple I don't think | that even a novice would make a critical error. | tptacek wrote: | You keep saying "the Galois Field" as if that was a | thing. It's GCM. The components of GCM are CTR mode and | the GMAC authentication code, which is based on GHASH. If | you're afraid of Galois fields, you don't get to use AES | at all! Nobody should be implementing _any_ of these | primitives themselves, very much including CBC, which, as | you saw downthread, left both you and the author of this | project with an insecure cryptosystem. | | Vulnerabilities in CBC systems were for a long time | during the 2000s _the most common crypto vulnerabilities | on the Internet_. There are more things that go wrong | with CBC mode than just forgetting to authenticate it! | dragontamer wrote: | > You keep saying "the Galois Field" as if that was a | thing | | You're kidding, right? You've never looked at how GCM- | mode works? The entire set of math is inside of the | GF(2^128) field. That's why its called a Galois Counter | Mode. | | I don't think anyone should be implementing their own GCM | mode. Its very subtle and potentially full of traps. CBC | on the other hand is pretty dumb and simple, and | surprisingly secure and robust | | > Vulnerabilities in CBC systems were for a long time | during the 2000s the most common crypto vulnerabilities | on the Internet. There are more things that go wrong with | CBC mode than just forgetting to authenticate it! | | If they're so common, you shouldn't have much of an issue | naming one such vulnerability. | tptacek wrote: | I think some of my comment went over your head. | [deleted] | password11 wrote: | > _Or... you can have a more nuanced viewpoint_ | | The nuanced viewpoint is never implement your own | cryptography. | | > _Its so stupid simple I don 't think that even a novice | would make a critical error._ | | Ask Microsoft about that one: | https://learn.microsoft.com/en-us/security- | updates/securityb... | dragontamer wrote: | That's a Padding Oracle vulnerability, not a CBC error. | password11 wrote: | Padding is an important part of CBC. | dragontamer wrote: | There is a huge difference. | | A padding oracle attack can attack any system that uses | CBC + padding, even when CBC is perfectly implemented. | | What I asked for earlier was a vulnerability due to an | improper implementation of CBC. | | ----- | | Furthermore, padding oracles are completely irrelevant to | data at rest, like as described in this topics use case. | So it really is a bit of a non sequitur too. | tptacek wrote: | No, to all of this. | [deleted] | tptacek wrote: | It's a CBC padding oracle, intrinsic to the operation of | CBC --- if you PKCS7-pad some other mode, you do not get | the same attack --- the single best-known cryptographic | vulnerability on the Internet, and the parent commenter | took the time to give you the most famous instance of it. | For the record: that's _also_ not the only CBC | vulnerability. | ThePhysicist wrote: | AES-GCM is part of the Web Cryptography API and supported in | all modern browsers, so no need to implement anything. | tptacek wrote: | I don't know what "being a stream" has to do with anything (you | should virtually always use "stream" modes of AES); the | meaningful distinction between CBC and GCM is that GCM | authenticates the ciphertext, so you can't tamper with it. | tialaramex wrote: | > so you can't tamper with it. | | ... if the API provided is correctly designed, and either the | language made it practical to design the API in a misuse- | resistant way /or/ the programmer was actually careful and | used it properly. | | We both know it's _way_ more likely the problem in your | actual system is "Oops, we use the bogus plaintext here | despite the validation error" than "Dastardly enemy | cryptographers have made a breakthrough in cryptanalysis to | attack our product". | tptacek wrote: | I'm not thinking very hard about it; there is just never a | reason to use unauthenticated encryption modes. When I | wrote that comment, I hadn't even looked to see if they'd | manually authenticated their ciphertext (spoiler alert: you | can guess). | ThePhysicist wrote: | SubtleCrypto (Web Cryptography API) will simply throw an | exception if the authentication fails for AES-GCM, so | there's no way to even get at the bogus plaintext. | [deleted] | 411111111111111 wrote: | The readme links to this issue wrt that decision | https://github.com/robinmoisson/staticrypt/issues/19 | | It seems that the hmac validation makes the GCM unnecessary in | their thread model | pluc wrote: | Leave it to full-stack devs to take care of cryptography | [deleted] | NKosmatos wrote: | I came here for the comments and sure enough I wasn't | disappointed :-) | jrexilius wrote: | This is a great utility and has a lot of meaningful use-cases. | Thanks for puting this out there! | avip3d wrote: | Wouldn't .htaccess solve this issue? | bertman wrote: | No, this is strictly client-side, ie. encryption and decryption | happen in the user's browser. | ebfe1 wrote: | Hah! I did a similar thing for a fun friday afternoon security | challenge with AES256 encryption on static website using the | answer to challenges as the key here if anyone wanna play with | it... :) | | https://challenge.surge.sh/ | | It should take you no less than 10 minutes ;) | userbinator wrote: | I'll echo the other sentiments here that I wouldn't consider this | "static HTML", and I was expecting something about .htaccess. | That said, this seems to be a strengthening of what used to be | somewhat common "protection", namely variations consisting of: | | - Password in plaintext in the source e.g. | "if(password=='hunter2') ..." | | - No correlation between password and page contents (either the | content is merely hidden and shown when the password check | succeeds, or lightly obfuscated/encrypted using key independent | of knowing the password) | | - Hiding content by using "display:none" or similar | DanielBMarkham wrote: | Gad! I have spent all morning trying to --- password protect a | static html page. How in the hell does HN have a story about the | exact topic I've been struggling with appear just a dozen or so | hours after I started working on it. Wow. | | I was _extremely_ happy to see this posted. | | However when I click the link I am taken to the library I had | initially tried and had to reject. Without getting into the | crypto side of things (which very well may resolve to "just make | it tough enough for most folks") I crashed and burned using this | tool once my page reached certain sizes. (I was cramming | everything I needed into one page and I had a big hunk of bytes | that I didn't want hanging out on the filesystem) | | As I understand it, this is a known issue in V8. V8 limits the | number of properties/collection members an object can have. | There's a flag you can use with node to get a little more | headspace, I believe it's something like "--max-old-space- | size=8192" but it's a V8 problem, not a node problem. The | staticrypt coders could also switch to a streaming cryptography | instead of block, but that's far too much to ask of the casual | user who only wants to lock up a page or two. | | This is a really cool tool, and I wished I could have used it. | Good luck to the team going forward. I've gotta find something | else as this doesn't work for me. | snowstormsun wrote: | Something similar has been posted before some time ago: | https://news.ycombinator.com/item?id=34083366 | doodlesdev wrote: | Which in turn has inspired the creation of PrivacyProtect | [0]. It allows to do basically the same thing as the other | applications, but in my opinion the interface is better, it | also allows you to directly select a file which I guess is | easier than copying the contents, it also means you can just | select an image file for instance or some other type of file | other than a web page. | | [0]: https://www.privacyprotect.dev/ | DanielBMarkham wrote: | Why is everybody forcing me to upload to the web the very | files I want to keep private to myself? If any code in the | universe should run locally, it's this kind of code. | | I don't get it. | | Great UI, though. But I still don't get it. | cuttysnark wrote: | That the frontend is hosted on someone else's server is a | convenience, but I see your point and agree. Technically | nothing is uploaded anywhere, nor does it call any APIs | to do the de/encryption. Instead, it uses the | cryptography mechanisms built into your browser. Local | file access and creation are via FileSystem api[0]. Said | differently, you could save the page to your desktop-- | ensure all the includes are to local files, and still run | it. In fact, thats's what I did with Portable Secret[1] | which others noted was previously posted here. I can | confirm this works and nothing "calls home". | | [0] https://developer.mozilla.org/en- | US/docs/Web/API/FileSystem [1] | https://mprimi.github.io/portable-secret ___________________________________________________________________ (page generated 2023-02-18 23:00 UTC)