[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)