At work, we want to upgrade our node app authentification a little by using a unique salt per user.
We are already using passport and passport-local with our hand-written password validation, storing password hash in DB and salting with a common salt.
I want to upgrade it correctly. One of the first rule of security I know is not doing it oneself : https://crackstation.net/hashing-security.htm
However, I'm having trouble finding a decent, trustable npm module to handle that. Searching npm with "salt" or "auth" yielded those modules :
https://github.com/florianheinemann/password-hash-and-salt
https://github.com/davidbanham/hashPass
Their documentation is unclear and they have less than 10 stars on GitHub.
Can someone point me to a good module for hashing/salting/checking my passwords ?
Bcrypt (npm)
Choose bcrypt module for generating hash with salt. Also note that it will make slow ur node app. Single encrypt decrypt operation takes around 100ms
[edit] Explanation : How To Safely Store A Password
Related
I have an offline application that encrypts local file (using aes-356-gcm) and it uses scrypt for password hashing (both from the node.js crypto library). Because the application is offline I can't prevent the user from being locked out after x attempts like a web app.
My question: Is it more secure to use a really long salt that is shared between all instances of the application, or would it be better to ask the user to remember a 6-8 byte salt that is not stored anywhere?
My initial thought would be that the 4-8+ byte salt that is not stored in a config file would be more secure because it would act almost as a second password. On the other hand, a 32bit salt is quite short (but would it even be considered a salt in this case?).
My current implementation uses a default hash for if the user just doesn't want to worry about remembering another pass phrase. Then, they can either specify their own salt or have a random one generated based on the number of bytes they want the length to be. The salt is not stored anywhere in any type of config file or anything along those lines.
The other idea I had was to generate a longer salt and prepend it to each encrypted file. Would this be overkill?
I also want to say: This is not an application that will be used in production. I am simply a student who's trying to learn on a personal app. I've already received all the "you shouldn't be implementing this if you don't know anything about encryption" comments. I understand your concern so let me just put it to rest now.
I am having a dillema now ..
I am building an application on VueJS and NodeJS .. and during the authentication, I need to verify whether the password and username match (obviously).
The problem is, I don't want to send the plaintext password from FE (VueJS) to the BE (NodeJS) but already encrypted with bcrypt
The problem is, there is no way for me to check if the given hash matches the stored one in the database. so this leaves me with sending the plain text password - but from my paranoid security perspective, it's not ok ...
How do you guys solve this?
It is standard practice to send "plaintext" passwords over HTTPS. The passwords are ultimately not plaintext, since the client-server communication is encrypted as per TLS.
Encrypting the password before sending it in HTTPS doesn't accomplish much: if the attacker got their hands on the encrypted password they could simply use it as if it were the actual password, the server wouldn't know the difference. The only advantage it would provide is protecting users that use the same password for multiple sites, but it wouldn't make your site any safer.
As indicated, generally the security layer of HTTPS is trusted.
Technically speaking, it is possible to split the password hashing in two. You can simply perform one number of iterations on the client (browser) and the remaining on the server. You want to perform at least one iteration on the server as you would otherwise get the value that the clients send to be stored in the database: i.e. getting a copy of the values in the database would directly leak all login credentials... not good.
So this would likely mean two separate bcrypt hashes to be performed if you want to keep using that algorithm. You can reuse the same salt I suppose, but storing a separate one should always be preferred. Of course, performing bcrypt at the client side will spike the CPU locally, which may hamper performance, spin up fans etc., and that's assuming the JS will run OK.
Finally, if the TLS is completely broken then somebody can simply inject a script that will leak the password. So hashing it locally will only increase security by a relatively small margin. It could still be somewhat useful against future decryption attempts, but in the end you'll have to rely on TLS anyways. So the answer to "How do you guys solve this?" is generally: we don't. It might make slightly more sense in a mobile app or full size application.
Interesting to know, there have been submissions such as Catena and Makwa to the password hashing competition that explicitly allow the client to perform part of the hashing. Generally this is more performed for offloading the password hashing to other systems and alleviate the use of valuable server resources.
First things first, this is likely a complicated question (I'm not sure if this is the correct place to ask this) but I've been thinking of a secure way for a user to log in to a service (for this example we'll go with a website) using a username and a password, while the server itself does not store either of these directly.
I came up with this in a lesson on hashing in school, so I wouldn't be surprised if there's a simple reason as to why this is not used by websites but I haven't found any examples at all of this being used online. This would use a form of asymmetric encryption on the server side to combine the username and password into one unique "userLoginID" that would be stored on the server. Code similar to this would be used on the server side, where "encrypt" would be a one-way encryption function:
userLoginID == "331845364410495642424788" # Just an example
if (encrypt(inputtedUsername,inputtedPassword) == userLoginID)
return True
else
return False
If anyone has any examples of similar processes to this or an explanation as to why it is not used more commonly, that would be great. Using this method, the user would have a different "Display Name" and "User ID" if necessary that they would be referred to by others / the server. I personally can't see any disadvantages to using this system so I would like it if someone with more knowledge in server security could explain a flaw in this type of system.
As far as I can tell, a hacker would have to brute force both the username and the password, and even if they had access to the full list of user login IDs they would not be able to do anything with them, but I'm certain this can't be flawless as I've just come up with it on a whim. Thanks, and I appreciate that this probably isn't the best place or way to ask this.
The current standard way to handle this scenario is pretty similar, just without including the username. When an account is created, the user's password is hashed with a password hashing algorithm (argon2, bcrypt etc.). This hash is stored alongside the username. The only difference with your suggestion is that the username is included in this hash.
A lot of the time, keeping the username "secret" isn't a big deal or required. I'm not saying your that your idea (with some adjustments) wouldn't work, I'm saying it may not be that useful, or would only be useful in specific circumstances.
What you are doing there is actually hashing (asymmetric encryption is a weird term tbh) the password using the username as a salt, which is a quite fine method to prevent table-lookup based attacks, like rainbow tables, online lookup, etc..
It's not a bad method at all if the hash function you use is secure, like SHA-1, but what it's actually recommended today is to use a key derivation function where you do the same hash funcion multiple times to also prevent brute force attacks (or at least make them incredibly harder), see PBKDF2 for a pretty good implementation, you could use it with the username+password salt thing too.
I've been struggling with this for some time now, hopefully someone has done this before and can help me on my way. I went to the Firebase people to request the scrypt params in order to migrate our user authentication away from Firebase to our own server. Now I got those params, but I have no clue as how they should map towards the node scrypt package (https://www.npmjs.com/package/scrypt). The Firebase params are of the following format:
hash_config: {
algorithm: SCRYPT,
base64_signer_key: asdf1234
base64_salt_seperator: xxxx
rounds: 123456
mem_cost: 098765
}
Somehow these should map onto the nodejs scrypt params, but I can't find the similarities. Any help would be much appreciated!
Struggled a lot with getting scrypt work properly. The documentation from here https://github.com/firebase/scrypt#password-hashing looks like outdated. Decided to share knowledge how we did things correctly in our team.
Working command
scrypt {key} {salt} {saltSeparator} {rounds} {memcost} [-P]
No need for salt+separator concatenation and base64 manipulations.
Firebase uses a custom version of Scrypt for user authentication. We take the derived key from standard scrypt, and then AES encrypt it with a "pepper", stored with the hashed password.
We just open sourced Firebase's version so that you can do your own password verification. Check it out at github.com/firebase/scrypt
I've been running into the same problem with migrating my firebase users over. I've also been going back and forth with firebase technical support - they said they couldn't share their hashing libraries unfortunately. As an alternative I've migrated my users over to my new db and checked for the "salt" variable whenever someone signs in. If the salt exists then query firebase, otherwise query your own db.
I am coding up the security for a website in express.js and postgresql db. Now I have been reading about salting and hashing and I have the code set up with pdkdf2 using the crypto module, but my issue is how I will structure the account table in the db. What If i would create a login role which will have an MD5 encrypted format for the password, which password will be the derived key from the salt n hash "procedure". Would that be an overkill of protection?
There will be a table which will be as follows: UID (the ID from the login role), SALT , HASH.
And also the loginrole.
So on a try for authentication, the code will try to login as that role, first by getting the assosiated UID, generating the salt n hashed password for the password provided and auth on a DB level.
Hope I am making some sense..
var usrSalt = crypto.randomBytes('128').toString('base64');
//text , salt ,iterations , keylen , callback
crypto.pbkdf2(usr, usrSalt, 10000, 512, function (err, derivedKey) {
if (err) { console.log(err); }
else {
usr = derivedKey;
next();
}
});
P.S Would a pgcrypto module be better again in the same scenario, just by removing the code on node.js.
This answer is at a higher level, not the low level of actual code.
"Overkill of protection" is relative to your project. The 10000 iterations will take some amount of time and MD5 will provide some level of encryption. Both might be suitable for your project, and will have to rank as a priority compared to other aspects (speed, features, etc.).
To keep speaking in generalities, some level of good security practices will protect some percentage of your user data, and with a determined attacker some other percentage might "always" be compromised.
The choice for pgcrypto is similar. If it is as sufficient as the code you plan to write (it is defacto more tested than your current code), its handling will be on your DB server. Good to keep it off the Node server? Easy to maintain? Less work? "Better" will be relative to your project.
Salting and hashing passwords is not overkill, it is the absolute minimum you should do if you cannot avoid dealing with passwords entirely.
It's hard to figure out what you mean with the second part, regarding this being used to auth on a DB level. You usually either do application level authentication using your own usernames/passwords, or you create real users in PostgreSQL and let PostgreSQL authenticate them by simply passing their password and username through to PostgreSQL when you create a connection.
There's an intermediate way, which you might be trying to get at. Authenticate the user yourself, then use SET SESSION AUTHORIZATION to have your PostgreSQL database session "become" that user. It's a bit of a specialized approach, and not one I tend to use most of the time. It is mostly used by connection poolers.
See also:
Secure method for storing/retrieving a PGP private key and passphrase?