5 ms·
If you're using node.js and you use these hashing methods, your entire server is going to pause for 0.5 seconds on a login because it runs on a single thread. G
by rcconf 11y ago
If you're using node.js and you use these hashing methods, your entire server is going to pause for 0.5 seconds on a login because it runs on a single thread. Goodbye to all of your server performance.
You can create a worker system, or use a child process to solve this problem, but most of these articles never mention it
- lukev 11y agoI think this says more about node.js than it does about the proper way to secure a password.
- StavrosK 11y agoIt definitely does, and I think that's the GP's point.
- ARussell 11y agoWasn't Node's big draw early on (aside from the fact that it's JavaScript) the fact that everything is supposed to be asynchronous? I'm actually surprised this is a problem.
- mobiuscog 11y agoasynchronous doesn't magically make CPU-intensive tasks faster.
- kornish 11y agoCorrect, but it sure does stop your entire single-threaded process from blocking to the detriment of all other requests.
- corobo 11y agoIt does mean other tasks (e.g. serving pages to visitors) can still be run at the same time as the CPU-intensive task though, like most languages do when it comes to hashing passwords and logging people in
- sotojuan 11y agoEverything is asynchronous but the linked article uses the synchronous versions of the functions for some reason... async versions exist and are recommended[1] [1] https://github.com/ncb000gt/node.bcrypt.js#async-recommended https://github.com/ncb000gt/node.bcrypt.js#async-recommended
- zwily 11y agoDo the async methods actually execute on a thread pool though? Or do they use enough async methods internally to periodically release the main thread enough to keep it responsive? From a quick glance at the source, the answer to the first is no.
- herbst 11y agoWouldnt this happen with pretty much anything that is not threaded by default? Clearly with PHP you give a fuck, but i assume its not different with Ruby, Python, Go, ASP or anything else. You just usually use them threaded.
- Joeri 11y agoPHP is usually deployed in a FastCGI multiprocess setup, so the server will keep handling requests on the other processes while the hashing process is blocked. I wonder whether threading really saves you, given that there are only so many cores in a system and password hashing is CPU heavy. Naively it seems a DoS would involve sending as many parallel requests as there are cores, which is not a lot and can easily be done from a single machine.
- sarciszewski 11y agoThe blog post that HN is reading is served by PHP-FPM + nginx, without any extra special features to handle the load of an unexpected "oh hey we made it to the front page of HN". It's also hosted on a relatively cheap VPS.
- seanp2k2 11y agoConsidering the other article from HN today about Stack Overflow being able to handle their top-100 global Alexa rank traffic with one physical web front end, I'm impressed but not that impressed. PHP has been popular for a long time and lots of smart people have figured out how to make it pretty quick. For things like blog posts, I'm sad that Movable Type fell out of favor. The pattern of using dynamic server pages to edit blog posts and generate static files for your viewers just makes so much sense to me. Then again, these days we can host our single-page JS front-ends on S3 + CloudFront and hook them up to API gateway and Lambda / Beanstalk talking to RDS and "not have any servers" :)
- herbst 11y agoI know thats what i ment with usually you give a fuck, i dont know any way you could run PHP single threaded on a server (i mean there sure is). But its something common you learn when you programm in the other languages i mentioned. I dont think it could get a real issue in a real environment, except someone really wants to fuck with you. But the some fail2ban on to fast requests should fix this easily as the hashes dont actually take that long.
- EGreg 11y agoIt says both. The hashing is computationally expensive and Node runs in a single process (if we ignore workers). They could have made an implementation that yields and resumes after several ms. or you can spawn a worker and send it jobs.
- abjorn 11y agoThe particular module being used in the article has async versions of those methods. He uses the synchronous versions in the example presumably for clarity/brevity.
- phillipburch 11y agoOr you could just use the async versions.... https://www.npmjs.com/package/bcrypt-nodejs https://www.npmjs.com/package/bcrypt-nodejs
- zwily 11y agoDoes that library do the calculations in a thread pool, or is it just async on the main thread? If the latter (which seems mostly likely), then it won't matter.
- phpnode 11y agoIt does it on the main thread, pseudo-async, so I agree with you, you should not use this library. Look for a native module instead.
- warfangle 11y agoIt looks like that one is pure JS, using native node crypt functionality for randomness. The one recommended in the article[0] actually includes a blowfish C++ binding, with both synchronous and asynchronous methods for comparing and hashing. That binding uses NAN[1] to queue AsyncWorkers. NAN uses libuv[2] behind the scenes to launch a thread[3]. 0. https://www.npmjs.com/package/bcrypt https://www.npmjs.com/package/bcrypt 1. https://github.com/nodejs/nan https://github.com/nodejs/nan 2. https://github.com/libuv/libuv https://github.com/libuv/libuv 3. https://blog.scottfrees.com/building-an-asynchronous-c-addon-for-node-js-using-nan#toc_7 https://blog.scottfrees.com/building-an-asynchronous-c-addon...
- dfischer 11y agoHave any examples of how to properly handle it with node? Isn't it just the typical callback pattern?
- warfangle 11y agoIncorrect; the first hashing method recommended uses a native CPP binding which launches a thread to execute both hashing and comparing. Unfortunately, the example used for the bcrypt node module is the async form of hashing. That library exports both sync and async forms of hash/compare.
- neals 11y agoI find that using the original bcrypt node module is hard to build consistently, I often have trouble getting it built on various systems. I switched to bcryptJS which is a drop-in JS implementation. Anybody here that knows if any of these is a valid replacement? https://nodejs.org/api/crypto.html https://nodejs.org/api/crypto.html
- lazyjones 11y ago> You can create a worker system, or use a child process to solve this problem, but most of these articles never mention it Or you can do the bcrypt() inside your (PostgreSQL) database and add an extra layer of security by not directly exposing the hash (or even the whole password table) to the web server process (i.e. write a password check SQL function and allow only calling it, no direct table/column access).
- NickNameNick 11y agoCongratulations, now there are plaintext passwords in your server logs... I did exactly what you are suggesting on a project some time ago - deferred to the database to do the password hashing and comparison to the stored hash. Unfortunately, the server query logs contained the query parameters. So did some of the database logs when running at elevated log levels. We quickly decided that was unacceptable, and moved the hashing process into the web server.
- swang 11y agoI don't see how moving to the web server would prevent that if you were logging passed req body or query parameters since they would be posted in plaintext (hopefully) over a https connection.
- theIV 11y agoI'm not sure but I'm assuming this has more to do with Postgres' WAL than it does filtering logs. I've never used this side of Postgres though, so just a guess.
- minitech 11y ago“query parameters” here are the parameters passed to PostgreSQL. That is, "SELECT * FROM users WHERE password_hash = get_hash('P4ssw0rd')" is being logged, not "?password=P4ssw0rd".
- NickNameNick 11y ago