Should i hash passwords
HTTPS generates a random, shared transaction key when opening up a communication channel. That's hard to crack, as you're pretty much limited to brute forcing the shared key used for a relatively short-term transaction. Whereas your hash can be just sniffed, taken off-line and looked up in a rainbow table or just brute forced over a long amount of time. If I'm not mistaken this technique is actually used by some banks.
The purpose of this technique is not to protect the password from sniffing over the wire. You can imagine that websites that used just HTTPS would show up with clear-text passwords in the log, but websites with very basic obfuscation ROT13 as well would show up with passwords that are not immediately of use. Disclaimer: I'm by no stretch a security expert-- and I'm posting with the hope that others will critique my position as overly cautious or improvable and I will learn from it.
With that said, I just want to emphasize that hashing when it leaves your client doesn't mean you get to don't have to hash on the backend before putting it in the database. Hashing on the ride over helps cover vulnerabilities of transport, if SSL connection is compromised, they still can't see the raw password.
Most people don't follow best practice and use the same password for many their accounts, so this can be a serious vulnerability to your visitors. If someone, somehow was able to read passwords from the database this does happen, think SQL injection , they still won't be able to execute privileged actions impersonating users through my API.
This is because of hash asymmetry; even if they know the hash stored in your DB, they won't know the original key used to create it and that's what your auth middleware uses to authenticate. This is also why you should always salt your hash storage. Granted, they could do a lot of other damage if they had free rein to read what they want from your database. I just want to emphasize here that if you do decide to hash the key before departure from your clients, that isn't enough-- the backend hashing is, imo, much more important and this is why: If someone is intercepting traffic from your client, then they will see the contents of the password field.
Whether this is a hash, or plain text, it doesn't matter-- they can copy it verbatim to impersonate an authorized client. Unless you follow the steps which user outlines, and I recommend you do.
Hashing the DB column, on the other hand, is a necessity and not at all difficult to implement. If you're connected to an https server the data stream between the server and browser should be encrypted. The data is only plain text before being sent and after being recieved. Wikipedia article. Whether there's an advantage, and whether it's more or less secure really depends on implementation.
There's arguably some advantage, but if you implement it poorly, you could definitely create a solution that is less secure than passing even a plaintext password.
This can be looked at from the perspective of two types of attacks-- one with access to the network traffic, and another with access to the database. If your attacker can intercept the plaintext version of the network traffic, then seeing a hash of the password is more secure than seeing the password in plaintext. Although the attacker could still log in to your server using that hash, it would require a brute-force crack sometimes pre-computed of that hash to determine the password that might be useful on other systems.
People should use different passwords on different systems, but often don't. If an attacker gained access to the database, perhaps through a copy of a backup, then you'd want to ensure that one couldn't log in with only that knowledge.
In that case, sending the password in plaintext would have been more secure because the attacker would need to know the plaintext in order to log in, even having a copy of the database.
This is where implementation is key. Whether you send a plaintext password or a client-side hash of that password, you should hash that value at the server-side and compare that hash with the hash stored in the user record. If you want to achieve the same reliability as when transferring over https, then yes - one option - the implementation of an asymmetrically encrypted channel at the ajax level.
If we are not talking about registration for example, the first transmission of the password is always protected , then there are options. An attacker would have to attack the bluefish key using a random source and ciphertext.
The task is not easy. It would actually be less secure to hash the password and send it over a non-encrypted channel. You will expose your hashing algorithm on the client. Hackers could just sniff the hash of the password and then use it to hack in later. Stack Overflow for Teams — Collaborate and share knowledge with a private group. Create a free Team What is Teams? Collectives on Stack Overflow. Learn more. Should I hash the password before sending it to the server side? Ask Question. Asked 11 years, 3 months ago.
Active 1 month ago. Viewed 69k times. Improve this question. Jader Dias Jader Dias In fact, it might make it less secure, since you exposes your salt. Also, talking out my back-side here , the mixing of algorithms might cause more hash collisions, and make it more hackable. Merlyn "hash collisions" good point!
A mathematical formula and hashing table decide which symbols in the input data will become which symbols in the output data. Hackers cannot directly turn a hashed value into the password, but they can determine what the password is if they continually generate hashes from passwords until they find one that matches.
This is referred to as a brute-force attack. With enough time and access to hashing tables, a hacker could reverse engineer a password, which is where salting comes in. This means that, without any additional security, if you input the same password you would see the same output every time. SHA hash — With cryptographic hashing algorithms, similar inputs produce vastly different outputs. Using the SHA hash generator creates an entirely different hashed output even if only one character is changed.
This makes it much more difficult for hackers to reverse engineer the input values from the output values. As a result, SHA is the hashing algorithm with Bitcoin cryptocurrency.
MD5 Message Digest Algorithm — MD5 is a cryptographic algorithm that will always produce an output of bits typically expressed as a 32 digit hexadecimal number no matter the length of the input. It was one of the most widely used hashing algorithms but is now no longer recommended. The most common salt implementation errors are reusing the same salt in multiple hashes, or using a salt that is too short.
A common mistake is to use the same salt in each hash. Either the salt is hard-coded into the program, or is generated randomly once. This is ineffective because if two users have the same password, they'll still have the same hash.
An attacker can still use a reverse lookup table attack to run a dictionary attack on every hash at the same time. They just have to apply the salt to each password guess before they hash it.
If the salt is hard-coded into a popular product, lookup tables and rainbow tables can be built for that salt, to make it easier to crack hashes generated by the product. A new random salt must be generated each time a user creates an account or changes their password. If the salt is too short, an attacker can build a lookup table for every possible salt. For the same reason, the username shouldn't be used as a salt.
Usernames may be unique to a single service, but they are predictable and often reused for accounts on other services. An attacker can build lookup tables for common usernames and use them to crack username-salted hashes. To make it impossible for an attacker to create a lookup table for every possible salt, the salt must be long. A good rule of thumb is to use a salt that is the same size as the output of the hash function.
For example, the output of SHA is bits 32 bytes , so the salt should be at least 32 random bytes. This section covers another common password hashing misconception: wacky combinations of hash algorithms. It's easy to get carried away and try to combine different hash functions, hoping that the result will be more secure.
In practice, though, there is very little benefit to doing it. All it does is create interoperability problems, and can sometimes even make the hashes less secure. Never try to invent your own crypto, always use a standard that has been designed by experts. Some will argue that using multiple hash functions makes the process of computing the hash slower, so cracking is slower, but there's a better way to make the cracking process slower as we'll see later.
Here are some examples of poor wacky hash functions I've seen suggested in forums on the internet. Note: This section has proven to be controversial.
I've received a number of emails arguing that wacky hash functions are a good thing, because it's better if the attacker doesn't know which hash function is in use, it's less likely for an attacker to have pre-computed a rainbow table for the wacky hash function, and it takes longer to compute the hash function. An attacker cannot attack a hash when he doesn't know the algorithm, but note Kerckhoffs's principle , that the attacker will usually have access to the source code especially if it's free or open source software , and that given a few password-hash pairs from the target system, it is not difficult to reverse engineer the algorithm.
It does take longer to compute wacky hash functions, but only by a small constant factor. It's better to use an iterated algorithm that's designed to be extremely hard to parallelize these are discussed below. And, properly salting the hash solves the rainbow table problem. But if your reason for doing so is to make the hash computation slower, read the section below about key stretching first.
Compare these minor benefits to the risks of accidentally implementing a completely insecure hash function and the interoperability problems wacky hashes create. It's clearly best to use a standard and well-tested algorithm. Because hash functions map arbitrary amounts of data to fixed-length strings, there must be some inputs that hash into the same string.
Cryptographic hash functions are designed to make these collisions incredibly difficult to find. From time to time, cryptographers find "attacks" on hash functions that make finding collisions easier.
A recent example is the MD5 hash function, for which collisions have actually been found. Collision attacks are a sign that it may be more likely for a string other than the user's password to have the same hash. However, finding collisions in even a weak hash function like MD5 requires a lot of dedicated computing power, so it is very unlikely that these collisions will happen "by accident" in practice. A password hashed using MD5 and salt is, for all practical purposes, just as secure as if it were hashed with SHA and salt.
This section describes exactly how passwords should be hashed. The first subsection covers the basics—everything that is absolutely necessary. The following subsections explain how the basics can be augmented to make the hashes even harder to crack.
Warning: Do not just read this section. We've seen how malicious hackers can crack plain hashes very quickly using lookup tables and rainbow tables.
We've learned that randomizing the hashing using salt is the solution to the problem. But how do we generate the salt, and how do we apply it to the password? As the name suggests, CSPRNGs are designed to be cryptographically secure, meaning they provide a high level of randomness and are completely unpredictable. The salt needs to be unique per-user per-password. Every time a user creates an account or changes their password, the password should be hashed using a new random salt.
Never reuse a salt. The salt also needs to be long, so that there are many possible salts. As a rule of thumb, make your salt is at least as long as the hash function's output.
The salt should be stored in the user account table alongside the hash. If you are writing a web application, you might wonder where to hash. Should the password be hashed in the user's browser with JavaScript, or should it be sent to the server "in the clear" and hashed there? Even if you are hashing the user's passwords in JavaScript, you still have to hash the hashes on the server. Consider a website that hashes users' passwords in the user's browser without hashing the hashes on the server.
To authenticate a user, this website will accept a hash from the browser and check if that hash exactly matches the one in the database. This seems more secure than just hashing on the server, since the users' passwords are never sent to the server, but it's not. The problem is that the client-side hash logically becomes the user's password. All the user needs to do to authenticate is tell the server the hash of their password. If a bad guy got a user's hash they could use it to authenticate to the server, without knowing the user's password!
So, if the bad guy somehow steals the database of hashes from this hypothetical website, they'll have immediate access to everyone's accounts without having to guess any passwords. This isn't to say that you shouldn't hash in the browser, but if you do, you absolutely have to hash on the server too. Hashing in the browser is certainly a good idea, but consider the following points for your implementation:.
If the connection between the browser and the server is insecure, a man-in-the-middle can modify the JavaScript code as it is downloaded to remove the hashing functionality and get the user's password. Some web browsers don't support JavaScript, and some users disable JavaScript in their browser. So for maximum compatibility, your app should detect whether or not the browser supports JavaScript and emulate the client-side hash on the server if it doesn't.
You need to salt the client-side hashes too. The obvious solution is to make the client-side script ask the server for the user's salt. Don't do that, because it lets the bad guys check if a username is valid without knowing the password.
Since you're hashing and salting with a good salt on the server too, it's OK to use the username or email concatenated with a site-specific string e. This can make hashing long passwords significantly more expensive than hashing short passwords. If a user can supply very long passwords, there is a potential denial of service vulnerability, such as the one published in Django in Manual pre-hashing can reduce this risk but requires adding a salt to the pre-hash step.
For older applications built using less secure hashing algorithms such as MD5 or SHA-1, these hashes should be upgraded to modern password hashing algorithms as described above. When the user next enters their password usually by authenticating on the application , it should be re-hashed using the new algorithm.
It would also be good practice to expire the users' current password and require them to enter a new one so that any older less secure hashes of their password are no longer useful to an attacker.
However, this approach means that old less secure password hashes will be stored in the database until the user logs in. Two main approaches can be taken to avoid this dilemma. One method is to expire and delete the password hashes of users who have been inactive for an extended period and require them to reset their passwords to login again. Although secure, this approach is not particularly user-friendly. Expiring the passwords of many users may cause issues for support staff or may be interpreted by users as an indication of a breach.
An alternative approach is to use the existing password hashes as inputs for a more secure algorithm. Layering the hashes avoids the need to know the original password; however, it can make the hashes easier to crack. These hashes should be replaced with direct hashes of the users' passwords next time the user logs in. Assume that whatever password hashing method is selected will have to be upgraded in the future. Ensure that upgrading your hashing algorithm is as easy as possible.
For a transition period, allow for a mix of old and new hashing algorithms. Using a mix of hashing algorithms is easier if the password hashing algorithm and work factor are stored with the password using a standard format, for example, the modular PHC string format.
Ensure your hashing library is able to accept a wide range of characters and is compatible with all Unicode codepoints. Users should be able to use the full range of characters available on modern devices, in particular mobile keyboards. They should be able to select passwords from various languages and include pictograms.
Prior to hashing the entropy of the user's entry should not be reduced. Password hashing libraries need to be able to use input that may contain a NULL byte. Skip to content.
0コメント