What is a good, simple encryption scheme for protecting passwords in a database? I don't necessarily need anything that's hyper-secure nor do I need anything that's lightning fast, but those things would be nice. Primarily, I just want something that's easy to implement without being terribly slow or insecure.
As mk says, SHA1 or MD5 are the standard ones, along with SHA2.
Update: As processors have gotten faster over the years, hashes have gotten more brute-forceable. It's now recommended you use bcrypt.
Another update: bcrypt is still probably good, but if I was writing a new system today I would use scrypt.
What you want is more generally called a cryptographic hash function. Cryptographic hashes are designed to be one-way (given the resulting hash, you shouldn't be able to derive the original input). Also, the likelihood of two arbitrary strings having the same hash (known as a hash collision) should be low (ideally 1/number of hash values).
Unfortunately, just because your passwords are hashed doesn't free you from having to try really hard to keep the hashed versions safe. Far too many people will use weak passwords that would be vulnerable to an off-line brute-force attack.
Edit - several people have also already pointed out the importance of using a salt. A salt is a constant value that you mix in with the input before using the hash function. Having a unique salt prevents off-line attackers from using pre-computed tables of common passwords (rainbow tables) to brute-force your passwords even faster.
MD5 or SHA1 + salt.
If you use MD5 or SHA1 use a salt to avoid rainbow table hacks.
In C# this is easy:
MD5CryptoServiceProvider hasher = new MD5CryptoServiceProvider();
string addSalt = string.Concat( "ummm salty ", password );
byte[] hash = hasher.ComputeHash( Encoding.Unicode.GetBytes( addSalt ) );
Easy: BCrypt.
Use the SHA one way hashing algorithm along with a unique salt. It is the main algorithm I use for storing my passwords in the database.
If you're using SQL Server, there's the HashBytes function:
http://msdn.microsoft.com/en-us/library/ms174415.aspx
I second the vote for MD5 or SHA with a salt. Any of the major web development languages have functions built-in for computing the hash (in PHP, for example, the mcrypt package contains the necessary functions).
You need to be using an uni-directional hash algorithm like SHA-1 suggested above with a salt. I would suggest this site for more information. It includes some sample code / implementation.
http://www.obviex.com/samples/hash.aspx
The key to better security, I think, is to use dynamic salts. This means that you generate a random string for each new user and use that string to salt the hash. Of course, you need to store this salt in the database to be able to verify the password later (I don't encrypt it in any way).
For a non-reversible encryption I would most definitely go with SHA256 or SHA1. MD5 has quite a lot of collisions now and a lot of effort has been put into breaking it, so not a good one to use.
If you want to future-proof your solution, I'd recommend SHA256 or SHA512. Cryptographic geekworld is getting the jitters about MD5 and, to a slightly lesser extent, SHA1.
Or, if you can, wait for SHA-3
Related
I'm working on a website (PHP + MySQL) that I've got to upgrade. Passwords are stored in the database in MD5, and I'd like it to be something more secure, like SHA-256.
I've already red this question about "converting" password hashes, but I got an other idea, and I'd like to know if it brings a security problem or not.
Currently, the passwords are checked in php by hashing (in MD5) the given password and compare it with the hash stored in database, ie: if(md5($password) == $hash)
Let's assume that I hash all the MD5 hashes in SHA-256. I'd have the sha-256 hash of a md5 hash.
Side note: I know it's not more secure to rehash a hash, that's not the point of my question
When a user wants to connect, I'd just have to change the md5($pass) in hash('sha256', md5($password), false) to make it match the value stored in database (assuming $password is the right one)
It seemed a good idea to me as I don't need to keep track of the md5 hash after conversion, ad this doesn't need me to create any new column in my table. I know that this is not going to give me the SHA-256 hash of the original password stored with md5 hash, but this is not my goal. It's just to change the encryption method. Moreover, brute-forcing it seems inefficient, as it is very unlikely that dictionary would have hashes of words...
Does this way of doing it is flawed?
Simple hashing of passwords is insufficient, it is subject to rainbow tables and is to fast.
Instead in PHP use Safe Password Hashing: password_hash() and password_verify() or a comparable function such as PBKDF2, Bcrypt or script. These function are more secure because of two additions: a repetition count and a random salt. It's all about raising the work factor the attacker must perform.
After all, the point is to have a secure system. Just making it more inconvenient for an attacker is not the answer, there are hacking programs out there to take advantage of poor password security.
I need to decrypt this hashed password: e59dc19f2a3a569417fa183696f91604 and have the salt: 4067. Is it possible to recover the password with this information?
You mentioned the word decrypt in your question, so I wanted to just mention firstly that hashes are not a means encryption. Encryption is a two way process of encryption and decryption. It's a way of securing data in transit or stasis.
Hashes are a one way algorithm and cannot be decrypted. However, there are means of finding out what was hashed. If you do some research into Rainbow tables, you'll see that you simply need to build a list of texts (with a salt, in your case) and their corresponding hash.
Hashes and Encryption are like bread and icecream. You can heat up bread and get toast, but you can't cool down toast to get bread. You can head up icecream to get cream, and you can cool it down again to get your icecream back.
No, hash algorithms are one way.
You can hash the original password again and see if the hash result match the previous one.
There is a way to decrypt this, but it is a long and laborious process. It's referred to as "brute-force", which means you would try a large (and by large, I mean significantly large dependent on the length of the password) number of inputs. Since the hash function is a one-way function that produces a non-random result, you will always map an input to the same output. So by using "brute-force", you're literally trying every possible combination and seeing if the hash produced is equal to the hash stored on the system (since you already know the salt). There are tools that do this such as John the Ripper (available on Kali Linux) but again, dependent on your computational power, it can take awhile.
It is impossible to decrypt it. However, you may be able to crack it using the brute force method to find matching passwords in a dictionary.
Best tool to use would be hashcat.
I tried to decrypt a hash with salt, and it works but only with the same encrypt application or method (I mean with the same exact thing, if u encrypt it on a website, or an app you have to decrypt that on the very same place).
I hope that helps
I had an idea about storing passwords in databases: since passwords can be cracked by simply looking up a hash in rainbow tables (etc. etc.), would it be much (or even a little) safer to store a manipulated hash instead of the real one? In my case, it's not a string hashed twice or something - I have a custom pattern of "scrambling" a hash (I'd prefer not to mention my approach to this), so I figured I'd ask if it's worth the trouble before I do something that's useless.
Passwords in the database are currently encrypted with Blowfish (salts are completely random) and SHA-1, is this otherwise safe enough (yeah, you can never be too safe - but should it suffice)? We really don't have many users either, as the site doesn't draw much attention.
I'm absolutely no expert of this kind of stuff, so go easy on me. The only thing I know, is that people are getting better and better at cracking passwords (and the possibilities seems to be increasing).
I'd prefer not to mention my approach to this
Security through obscurity is not security.
If the passwords of the users is long enough and you add a long enough salt and you use a good hashing / crypting algo you won't be able to find the hash in a rainbow table.
Take a look at for example: http://freerainbowtables.com which are distributed rainbow tables and see where they are.
You can however in stead of scrambling your password yourself (or with some selfmade function) use more iterations when encrypting.
I'm starting a new ASP.Net application from scratch. What should I use to encode passwords and what should my column be?
Just a simple varchar(512)? Thanks for any advice.
I would use the Membership API that's included with .NET. I believe it hashes passwords (and security answers) using salted SHA1. If you still want to reinvent the wheel, you could still use this as a guide for best practices.
Well, if you're using SHA1 you're hashes are only going to be 48 characters long, so 512 is overkill.
I use SHA 256 with a salt.
The FormsAuthentication namespace has a handy method that you can use to hash a password for storing [in the database].
As others have mentioned, be sure to salt your password.
FormsAuthentication.HashPasswordForStoringInConfigFile(saltedPassword, "SHA1")
People, please.
Encryption != Encoding != Hashing
These are 3 different terms that should not be used interchangeably.
Passwords should be hashed and salted, never encrypted, much less encoded. Use SHA as your hashing algorithm and remember to use a salt too. That's a very important countermeasure to avoid rainbow table attacks.
Also, all hash functions will generate an output that has a fixed size (32 characters in case of MD5, 40 in SHA1, etc.) so you don't need all that extra space.
References/Reading:
MSDN: SHA1 Class
Just hashing is far from enough
I would take a look at the System.Security.Cryptography namespace and devise a way to encrypt the passwords. Once you do that you can just take a look at the size of the encrypted passwords and create your column accordingly. Make sure you don't lose the encryption key of course. I would also have a different key in DEV than in PROD for added security. There are plenty of tutorials (and code) on how to do this in .NET.
Good luck!
Say a user registers for your site, you hash the password they have chosen then use that hash as a salt and rehash their password with that salt.
Example:
String hash1 = MD5(password);
String endHash = MD5(hash1 + password);
then store endHash in your database. Would this effective agaisnt Rainbow Table attacks if my database was comprimized? Or am i missing something that would make it easy to break?
This is key strengthening (http://en.wikipedia.org/wiki/Key_strengthening), a nice technique that nonetheless does not substitute for actual salt. It will not protect you against a rainbow table written with this double-hash function.
The point of salting is to prevent the use of huge precalculated tables. With this method it is possible to calculate the hash of any password without the need to access your database. You should store a random value and hash the password and that value together.
The weakness of hashed passwords is the attacker's knowledge of your hash function. If they know your hash function but not your salt, the salt has protected your passwords. If they know both the hash function and your salt, your data is at risk.
As this applies to your question - using dynamic salt generally makes it more difficult to figure out your salt. This increases security, but won't help if someone knows your algorithm.
Increasing your complexity in this way does make your system harder to crack. Nothing is uncrackable given enough resources, however.
Instead of hashing two times you should use the username as salt for the function:
String hash = MD5(username + password)
You should also consider using a different function as md5 is considered broken MD5
Doesn't make a difference: Your stored data is still based exclusively on the password, so there's no additional protection.
Also, you should avoid MD5 in favor of a currently-strong hash algorithm, such as SHA1, SHA-256, SHA-512.