I mean actually making it hard to exploit even if the user has chosen a relatively simple password(s)? I can't think of anything besides using additional cryptographic functions.
There are a few things you can do:
A cryptographically stronger hashing algorithm.
Salts
Key strengthening (e.g. bcrypt / scrypt / PBKDF2)
Use all these techniques for the best security.
The last is not particularly efficient in terms of performance, but that's deliberate. The problem with most commonly used cryptographic hash functions is that they are designed to be fast to compute, which means that they are also fast to crack if the password is a dictionary word. The idea of key strengthening is to make the algorithm so slow to compute that even a weak password will take a long time to crack.
Don't think, read ;) (and ask on SO) You'll want to salt passwords with their own individual salt so that the same password won't result in the same hash
http://en.wikipedia.org/wiki/Salt_(cryptography)
You might want to add a salt http://en.wikipedia.org/wiki/Salt_(cryptography) to the password you're going to hash. Anyway, be aware that there'll always be some risk associated with hashing a password, take a look at this article http://www.f-secure.com/weblog/archives/00002095.html
Leave crypto security, and analysis of it, to the experts, and just use a better crypto function.
Not using MD5 for hashing passwords. The same goes for about any hash function that's optimized for throughput. The idea of SHA1 and MD5 is, that you can generate a compact representation of virtually unlimited amounts of data, so that you can check it's integrity and also sign it cryptographically.
The idea of hashing passwords is, that you cannot retrieve the password from the hash. However most passwords are shorter than their hash, and implementing a brute force or dictionary attack is trivial. So given a hash, the used hash function one can implement the check logic locally -- possibly on a massive parallel computer, think GPU -- and break passwords reasonably fast.
What you actually want to do is using a hash function, that's so computationally intense that hashing takes so much time, that even attempting a brute force attack on a 4 character password took hours.
Just add some salt to the user entered password.
$salt = 'random string';
md5(sha1(md5($salt . $_POST['password'])));
Almost no way that result can be cracked.
Related
So let's say we somehow got the hashed password of a victim.
So the brute force approach is to take every possible string, hash it and check if it matches the victims hashed password. If it does we can use that string is the password and hence hacked.
But this requires a great deal of computational power and good amount of time even for strings with 6-8 characters.
But what if we can hash every possible string with less than 10(some) characters and store it in storage like a sorted database before hand. So that when you get the hashed password you can easily look up the table and get the password.
P.S:-
For this example let's say we are working with only one type of hashing algorithm and have huge data servers to store data.
I'm new to security and this a very very basic question but for some reason the answer to the question was really hard to find on the internet.
This is called a rainbow table, and is very much a known concept.
It is also the reason you should never just store the hash of passwords. A salt (a random string added to the password and then stored with the hash as plaintext for verification) can easily mitigate this attack by effectively making it impossible to use a rainbow table and force recomputation.
Also just for completeness it's important to note that plain cryptographic hashes are not adequate anymore to be used for credentials (passwords), because they are too fast, which means it's too fast to generate a rainbow table for a given salt, effectively bruteforcing a password. Specialized hardware makes it feasible to recover relatively strong passwords if only hashed with a plain crypto hash, even if using a salt.
So the best practice is to use a key derivation function (KDF) to generate your password hashes in a way that makes it very slow (infeasible) to brute force, but fast enough to verify. Also in most known implementations adding a random salt to each hash is automatic and the whole thing is just secure.
Such algorithms are for example PBKDF2, bcrypt, scrypt or more recently, Argon2. Each of these have different characteristics, and are more resistant against different attacks.
I'd like to incorporate the encryption and decryption of files in one of my C# .NET apps. The scenario is simple: User A sends an AES256-encrypted file to user B. The clear text password is exchanged on a different channel (e.g. phone call or whatever).
From what I understand I should use Rfc2898DeriveBytes for converting the user's clear text password into a more secure password using maybe 10,000 rounds. (see this article).
What I don't understand is the role of salt in my scenario. Usually salt is used in hashing passwords to prevent dictionary attacks. But in my scenario the PBKDF2 algo is used to compensate weaknesses of short or easy to guess clear text passwords by adding extra calculations required by the PBKDF2-rounds.
If I choose a random salt then the receiver will need to know that salt also in order to decrypt correctly. If I use a constant salt, then hackers can easily reverse engineer my code and run brute force attacks using my constant salt (although they'll be really slow thanks to the PBKDF2 iterations).
From what I understand I have no choice but to use a constant salt in my scenario and enforce a good clear text password rule to make up for the weakness of constant salt. Is my assumption correct?
Salts, in the context of password hashing (and key derivation), are used to prevent precomputation attacks like rainbow tables.
Note that the salt must be different and unpredictable (preferably random) for every password. Also note that salts need not be secret – that's what the password is for. You gain no security by keeping the salt secret.
The recommended approach in your case is to generate a random salt every time a file is encrypted, and transmit the salt along with the ciphertext.
Is there a specific reason you're using AES-256 by the way? It's around 40% slower than AES-128 due to the extra rounds, and it offers no practical security benefit (particularly not in the case of password-based encryption).
It's also worth considering using a well-established standard like PGP rather than building your own protocol from cryptographic primitives, because building secure protocols is so hard that even experts don't always get it right.
Your assumption is correct. If they have access to the password, they will also have access to the salt. The BCrypt implementations I've seen put the number of iterations, the hash, and the salt all in the same result string!
The idea is: your hash should be secure even if the salt and number if iterations is known. (If we could always know that the salt and number of iterations and even the algorithm would be unknown to attackers, security would get a whole heck of a lot easier! Until attackers politely decline to read our salts, we must assume they will have access to them in the event of a breach.) So you're right, they can brute force it - if they have a few supercomputers and a couple million years of computing time at their disposal.
Ok, so I understand why salting a password prior to hashing is such a good idea.
The question is, normally people suggest appending or prepending the salt to the password, why not do both?
My thinking is, so if Mr hacker got hold of the DB and wants to get the password for person x,
he thinks to himself, well most people suggest appending or prepending the salt, so lets do that..
He generates a rainbow table with of all the combinations of password + salt, and tries his luck. If that doesn't work he does the same but salt + password.
To make much it more difficult to do the attack why don't developers go the step further and do 'salt + password + salt', or 'reverse(salt) + password + salt', or you could be fancy and start cutting up the password/salt, start putting bits of salt here and there etc.
The only way the hacker would be able to find the password is if he has access to the source code (to know how the salt was weaved into the password prior to hashing)
A further note is, people suggest doing a minimum of 1000 iterations when key-stretching, again why not 1147, 1652, etc :)
A 2nd further note, when looking at a hash string, is it possible to work out the hashing function used?
It's much easier to guess the manner in which the salt is applied than it is to brute for the passwords, especially in the cases in which the attacker has a database of hashed passwords and one known match (his own password). Even if he has no knowledge of it, he can simply use his known password and the known hash to brute force the salt and salting algorithm.
The same goes with the hashing algorithm. There are only a few unbroken hash functions, and the chances are that any competent administrator would be using one of those.
One of the premises of cryptography is that ALL of the information about the algorithms used is assumed to be public. You should not rely on attackers to be unable to break your system because you are using an obscure algorithm to hash things, because compared to the expense of brute forcing passwords on a compromised database like that, brute forcing every hash algorithm is very inexpensive.
If you distribute your program to users, they can figure out exactly how it hashes things by disassembling or debugging it. If it's a server program, they can break in with some other vulnerability, or they can buy/steal/acquire your software, or whatever. I would even go so far as to say that ALL GOOD CRYPTOGRAPHIC SOFTWARE IS OPEN SOURCE: even though the entire world knows how it works, its still not breakable.
What you are trying to rely upon is security by obscurity. Lots of people and companies have used this as a method of securing their products. The last big incident I can remember was when the source code of Symantec's PCAnywhere software was stolen. You might remember how that turned out. Moral of the story is it isn't secure if nobody knows how it works, its secure if EVERYONE knows how it works (and it's cryptographically sound).
Reverse engineering your code would not be too hard for a determained hacker, once that happens, every one of your passwords is now compromised.
You should use proven hashing techniques. Take, for example, something similar to the bcrypt algorithm. When you want to hash a password, go through the following steps:
Generate a sufficiently strong random salt (16 - 32 bytes)
Set a hash cost (15 - 20) (the larger the cost, the slower and stronger the hash)
Calculate the number of hash rounds you will perform (2^cost)
Do the following:
hash = ""
for(numberOfHashRounds)
{
hash = SHA256(hash + salt + password)
}
Then store the hash along with the salt and cost used. When you need to verify, do the same with the stored salt and cost. As computers get faster, you can up the cost of the algorithm. Try and get it so your hash takes ~500ms to compute, or as long as you are willing to sacrafice.
This is secure because a cracker would have to generate a rainbow table for every salt, and perform the same number of rounds. This will take decades even with a GPU array used to crack.
If you want to add obfuscation on top of that, go ahead, just dont break the security of your algorithm in the process.
So passwords should not be stored in plaintext but many do anyway. For the others is there a standard way passwords are stored? I mean a SHA1 hash or MD5 hash and if so what will the salt size be? Is there a better place to ask this?
I am trying to pick the brains of sys admins and consultants working on directory services. I am trying to see if there is a pattern or not.
EDIT: I would like to clarify that I am not trying to learn how to store the passwords better myself but more trying to see how many different ways they are stored and if there is a standard if any.
MD5 has been broken for a while and SHA-1 also has problems.
If you want to store a hash that will be secure for a long time to come, SHA-256 or SHA-512 (part of the SHA-2 family of hashes, designed as secure replacements for SHA-1) are a good choice and somewhere between 128 and 256 bits of salt are standard.
However, the use of plain hashes is not the best way to do this nowadays. Adaptive hashes are specifically designed for this type of storage as the amount of time necessary to compute a result can be made to slow down with additional computations. This is a very important trait to have to prevent brute-force attacks against your stored passwords. A strong, and standard, implementation of an adaptive hash is bcrypt, based on modifications to the Blowfish encryption algorithm to make it suitable for this purpose (which is explained well here).
Passwords should be hashed and the hashes should be stored in the database.
However SHA* and MD5 are too fast a hashing algorithms to be used for the purpose of hashing passwords.
For hashing passwords, you'd ideally want something much slower which doesn't lend itself well to brute force/rainbow table attacks.
You can sure hash a password 1000s of times before storing the hash to make it time and computationally intensive but why bother doing that when you have algorithms like bcrypt that do the job for you.
You should use bcrypt to hash your password. Read more about it at
http://codahale.com/how-to-safely-store-a-password/
In bcrypt, since the salt is appended to hash - you don't even need two columns 'password_hash' and 'salt' in the table. Just 'password_hash'. The less clutter the better.
You can see this question for the answer to how long the salt should be (between 128-256 bits seems to be the consensus).
As far as what algorithm to use, you should definitely use SHA1. MD5 was considered broken long ago even though it is still commonly used (see wikipedia MD5.
I'm building a site where security is somewhat important (then again, when is it not important?) and I was looking for the best way to store my passwords. I know that MD5 has issues with collisions as well as SHA-1, so I was looking into storing my passwords via either SHA-256 or SHA-512.
Is it wiser to store a longer hash variant as opposed to a smaller one? (ie 512 vs 256) Does it take significantly more time to crack a SHA-512 encoded password versus a SHA-256 encoded password?
Also, I've read about using "salts" for the passwords. What is this and how does it work? Do I simply store the salt value in another database field? How do I use that as a part of the hash value calculation?
For password storage, you need more than a mere hash function; you need:
an extremely slow hash function (so that brute force attacks are more difficult)
and a salt: a publicly known value, stored along the hash, distinct for each hash password, and entering in the password hashing process. The salt prevents an attacker from efficiently attacking several passwords (e.g. using precomputed hash tables).
So you need bcrypt.
For the point of the hash output size: if that size is n bits, then n shall be such that an attacker cannot realistically compute the hash function 2n times; 80 bits are quite enough for that. An output of 128 bits is thus already overkill. You still would not want to use MD5, because it is way too fast (100000 nested invocations of MD5 might be slow enough, though) and because some structural weaknesses have been found in MD5, which do not directly impact its security for hashing passwords, but are bad public relations nonetheless. Anyway, you should use bcrypt, not a homemade structure.
Some of the answers here are giving you dubious advice. I recommend you to head over to the IT Security Stack Exchange and search on "password hashing". You will find lots of advice, and much of it has been carefully vetted by folks on the security stack exchange. Or, you could just listen to #Thomas Pornin, who knows what he is talking about.
Collisions are not relevant in your scenario, so MD5's weaknesses are not relevant. However, the most important thing is to use a hash that takes a long time to compute. Read http://codahale.com/how-to-safely-store-a-password/ and http://www.jasypt.org/howtoencryptuserpasswords.html (even if you're not using Java the techniques are still valid).
I would stay away from MD5 in any case, since there are other hashes that perform just as well.