I am using following way to encrypt user's passwords which is AES Encryption. I just want to know is this a good practice or is there any other method should I follow. Because someone made me confused saying "Why don't you use "SALT". Can I use SALT AES Encryption? with Bellow is a sample query I am using.
INSERT INTO user(id,passowrd) VALUES (1,AES_ENCRYPT('mypassword','key'));
I hope your database column isn't named "passowrd".
That aside..
Salt isn't an encryption method, it's a random bit you need to add to each password before hashing to protect against dictionary attacks.
You should not be storing user passwords using AES encryption, which is reversible. You don't care what the user's password is, only that they know it: so don't store the password in a reversible form.
Instead, you use a secure one-way hash, such as SHA256 or even bcrypt, of the password plus some random data. This random junk, the "salt", is generated for each user and appended to the password before hashing. It is then stored in the database along with the hashed data to enable you to compare the passwords later.
This way, an attacker with what's called a rainbow table (a big dictionary of hash-to-plaintext mappings) can't come along and see "oh look, Joe User decided to make his password 'password'!". This also protects against someone brute-forcing all the passwords in your database, since if each account has its own independent salt, each password must be independently attacked.
You wouldn't use "SALT" with AES, typically it's used with SHA.
Great details and explanation can be found at:
https://stackoverflow.com/a/4351749/1232478
A salt is a sequence of characters added to a string about to being hashed, so it's harder for an attacker to obtain the original string.
However, for a cipher algorithm that is not based on hash, a salt isn't necessary, because the attackers will obtain anyway the original string with the salt, and it's just needed logic to remove it.
With AES_ENCRYPT the key you're using IS the salt. I prefer one-way hashes like MD5 or SHA, but many like decryptable passwords like you're storing.
Related
I'm working on a site which is (try to be) super secure. I read a lot about password hashing and using salts, but not everything is clear to me. I would like to use sha-256 hash algorithm with salt. I know about salts that all of them should be unique per-user per-password.
I'm wondering what if I use the password as salt too? Hash the password with sha256 and then hash it with an other algorithm and use it as salt. In this way I don't have to store the salt in the database. Is this possible? or should I generate a random string?
No, that is still a one-way algorithm.
If another user uses the same password the hash value will be the same as the hash of the pass of the first user. That misses the point that hash values must be different for each user and each pass entry.
I suggest to use the date of registration of a user (for example) as salt. This way for each user and each pass the hashing algorithm will be different (ok, if two users have the same pass AND the same reg. date it will be the same).
Or maybe you can use user id for salt, or some combination between user id and reg.date and user name.
Edit:
Your approach is actualy better than hashing with known algorithm without salt, but worse than hash+propper salt.
What you do is just applying custom hash function of your own. That can't be easyly brute-forced without knowing the custom algorithm, but is vunerable to other attacks.
And I suggest not placing a table with name "SALT" in the db, for if DB is hacked the attacker wii get the passwords AND the salts for them.
Preface: Making a simple ecommerce website. Users are automatically added, when they register, via registration page. I want to automatically encrypt their passwords.
Problem: The MySQL website shows how to use AES_ECRYPT, but it seems like it's for Terminal-type settings where the Admin would manually do this.
I want to add some code to register.php to make it automatically encrypted.
Thanks!
As the other answers have stated, you should not encrypt your passwords. They should be hashed.
They should NOT use MD5 or SHA
You SHOULD use bcrypt
Encryption should not be used because you never want to be able to decrypt the values and see the passwords, because hackers could also do the same.
Hashes are like one way encryption, you create a hash, and when logging in, you hash the password they entered on login and compare it against the stored hash.
MD5 and SHA are not suitable for this anymore as computers are faster and faster they can hash dictionary words and common passwords at a rate of 60+ billion per second to try to get your passwords.
This topic has been covered to death on StackOverflow.
See this for how to use bcrypt How do you use bcrypt for hashing passwords in PHP?
And this for an explanation as for why: Secure hash and salt for PHP passwords
You are going to want to hash passwords and not encrypt them. An encryption can be undone with the key. The password the user types in is called the plaintext password, the plaintext password should NEVER be written or stored anywhere.
When something is hashed, it is a one way translation, a hash cannot easily be translated back to its plaintext form, so when someone enters their password, you hash it and then compare it with the hashed password stored in the database.
A few hashing algorithms are MD5, SHA1, etc- in PHP, you can use the crypt function to hash a password. I should note that MD5 and SHA1 are not as secure anymore as they are very fast, which means that they can be brute forced fairly quickly (there are also databases where you can reverse engineer the hashes fairly quickly). You should use PHP's crypt function.
tl;dr - Hash passwords, don't encrypt them (for security, especially eCommerce).
I was researching about hashing and storing passwords to database on PHP.NET.
This site said:
If you are for example storing the data in a MySQL database remember that varchar fields automatically have trailing spaces removed during insertion. As encrypted data can end in a space (ASCII 32), the data will be damaged by this removal. Store data in a tinyblob/tinytext (or larger) field instead.
which of this suggests are better? or may be I have to ask: Is one of them better? and if the answer is yes, which?
and finally how should I store passwords to db using PDO. I thought I can write information to a blob row just like files, but if I get the values from input, which method or function have to used?
Would you explain about please?
When storing hashed passwords, then whitespace removal is a non-issue:
You never store the passwords themselves, but the output of a hash function instead.
This hash function produces fixed-size output (or you are likely using a reversible encryption algorithm).
The output of most hash functions is already fixed-sized plaintext[1] that doesn't include any spaces. Otherwise, you are probably using a hash function not intended for password hashing.
The fixed-sized salt is stored along with the hash output (Password hashing functions which are aware of salting usually output the salt with the hashed password).
If you want to be flexible and be able to upgrade to a better hash function in the future, you also have to remember which hash function was used. It is recommendable to use plaintext[1] for this information, which makes the complete record variable-length. RFC 2307 describes such a possible plaintext[1] storage scheme.
Passwords should be hashed with a modern and proven key-stretching algorithm, but not with cryptographic hash functions like SHA-256 or MD5. Suitable algorithms include PBKDF2, bcrypt, or scrypt.
For example, hashing the string "pass phrase" with bcrypt and a new salt may produce
$2a$12$PuYHvYwgKeD.hQ1Dv6nLQuxUkv5zP3lYLPHqdMOzgwPVaGGSAs07u
`-----'`-----------······· ·········-------'
algorithm random salt password hash
parameters
The whole string can be used as salt, as the actual password hash will be cut off and not be used as salt.
Recommended workflow for validating a login attempt:
The user provides an username and password. Be careful to handle Unicode normalization and encodings.
The hashed password is fetched from the DB based on the username.
The hashed password is parsed to determine the algorithm used.
The correct algorithm is invoked with the user password as input with the hashed password as salt.
If the two hashes match, then a correct password was provided by the user.
Recommended workflow for setting a new password:
If the user already exists, authenticate him.
Obtain a new password from the user. Take care to handle Unicode normalization and encodings. Give the user feedback on the strength of his password (but do not frustrate the user with silly requirements like forbidden characters or restrictive maximal lengths).
Create a new salt, which must not depend on user input like the password or user names.
Pick a strong password hashing function and hash the password with the new salt.
Update the DB to store the new password along with an identifier for the hash function.
Further comments:
Encrypted data is binary data, and should not be stored as text (use a blob instead).
Hashes are usually often represented as plaintext and not as binary data because text is easier to store.
In many scenarios you can use OpenID instead of implementing your own authentication. E.g. Stack Exchange offers login with OpenID. Because I use this option, I never had to disclose a password to SE.
I have no cryptographic background. Information Security is frequented
by people who understand more of the matter.
[1] Here, “plaintext” means printable ASCII characters. It does not refer to the clear text of a password.
I've been using PHPass to hash my passwords for a long time. I admit that there's still things I don't fully understand (or ignore) to hash a password properly so today I was reviewing all the info I could find about it.
Reviewing PHPass documents, I've steped into this:
Besides the actual hashing, phpass transparently generates random salts when a new password or passphrase is hashed, and it encodes the hash type, the salt, and the password stretching iteration count into the "hash encoding string" that it returns. When phpass authenticates a password or passphrase against a stored hash, it similarly transparently extracts and uses the hash type identifier, the salt, and the iteration count out of the "hash encoding string". Thus, you do not need to bother with salting and stretching on your own - phpass takes care of these for you.
I've bolded the sentence that bothered me.
I always though that the salt should be somewhat secret, in the sense that it should not be known to the attacker. So if a understood correctly, PHPass stores the salt used in the same hash so it is able to use it when comparing passwords and check if valid.
My questions are
Is this secure? If the hash is compromised, the attacker has the salt used to hash the password... There's something I miss here.
I'm here really free to bother about salting passwords? Can I really rely on PHPass?
A little background
A salt is not meant to be secret, instead, a salt 'works' by by making sure the hash result unique to each used instance. This is done by picking a different random salt value for each computed hash.
The intention of the salt is not compromised when it is known; the attacker still needs to attack each hash separately. Therefore, you can simply store the salt alongside the password.
So, is PHPass secure?
YES! PHPass (according to the best practices) generates a strong random salt for you. It is a well reviewed and good quality library.
Links of interest:
How to securely hash passwords?
How to store salt?
Password Hashing add salt + pepper or is salt enough?
Salt Generation and open source software
The purpose of a salt is not to be a secret. The purpose is to add a unique component to each hash input, so identical passwords will not hash to identical hashes, thereby making the brute-force process more difficult and time consuming since each hash has to be tried individually.
Yes, it would be marginally more secure if the salt was secret, but that's hard to realize in practice, since your application needs the salt as well, so it needs to be stored somewhere where the password is accessible as well. Therefore, in practice, when the attacker gets the password hash, he's typically also able to get the salt anyway.
If I understand correctly, salts are primarily used to thwart precomputed hash/rainbow tables attacks. As long as the hash that is used is generated so that it is reasonably globally unique (not hardcoded in PHPass for example), you're OK.
I've been reading a bunch of stuff about security and I'm just now starting to try and play around with the code. I want to use MD5 encryption with a salt. I ran across this nifty PHP script with random salt:
substr(str_shuffle(str_repeat('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',5)),0,10);
It randomly generates some characters as salt, but then I was thinking: How would I go about checking logins? Do I remove the salt, or should I store it in the database?
You shouldn't be using MD5 for password hashing. See How can I store my users' passwords safely?
To answer your original question, the salt is stored alongside the HASHED password in the database. The salt is not meant to be secret if the hashed password is discovered. Its purpose is to prevent attackers from using rainbow tables.
Store it in database. Otherwise you can't compare password provided by user with hashed one.
Some even regenerate hash (with new salt) upon each successful login of given user, although commenters below argue this is not the best idea (see comments)
Okay, so salts are used for both one-way hashes and encryption. They make it harder to reverse the encryption or the hash. I think it's easier to draw the point out with hashes, so I'll write from that point of view, but the principles apply to encryption in general.
Imagine that you're saving passwords. One of your users chooses the word "kiwi" as a password. Because storing passwords in plain-text is stupid, you don't want to do that. You want to hash the password.
But, those pesky hackers out there have compiled huge databases of hash look-up tables. (Check this one out!)
So, how do we foil the hackers? By salting the user's input! The salt is a random string (or set of bits, properly) that is cryptographically combined with the user's input to produce a more secure hash.
For example, if the string to be hashed is still "kiwi" and our salt is "5m3d", a simple salt mechanism might concatenate the two into: "kiwi5m3d". The hackers probably have "kiwi" in their database, but probably don't have "kiwi5m3d". A good salting system will probably perform a much more complicated function than this.
So now the hackers need a new look-up database for each possible salt. Using a random salt means that the hacker will have to do a full-on brute force attack, rather than recycling previous computations or using someone else's look-up table.
You could choose a different salt for everything, or the same salt for all the things on your site. A different salt of each entity necessitates a new brute force attack for each entity, but it can make implementation more difficult because each salt must be saved, rather than having one global salt (which, for data which is already somewhat random, e.g. passwords, should be sufficient).
In the case of encryption, look-up tables are still a possibility, but the data to be encrypted is generally varied enough that they're not feasible. So it becomes a game of playing "guess the password". It's easy to guess "kiwi" and hard to guess "kiwi5m3d".
You will have to save the salt somewhere, because it's the only way to "know" what's been hashed or encrypted. In the case of a hashed, you compare the user's original hash against the salted hash of their input. In the case of encryption, you need the salt to decrypt the data.
Where do you go from here?
First, don't use MD5. I gave you a link to an MD5 look-up database above. The function's increasingly considered to be weak. The sha class of algorithms is a better choice.
Second, make sure you choose a good salt. Longer and randomer is better. Computers are kind of bad at generating random data. This site could be one good choice and has a pretty good break-down of how it generates its random numbers.
Third, consider salt algorithms. Simple concatenation should work, but maybe HMAC (something I don't know much about) would be better.
You would have to store it in the database, otherwise you would not have anything to compare it to. The thing to remember with using a salt, is that the complexity can vary and without knowing what the salt is, the likelihood of it being brute forced hack is dramtically decreased.
Example:
$password = "banana";
$salt = "a12dsfg33B1cD2eF3G"; # Can be any assortment of characters
$password = md5($salt.$password);
Then you would just attach the same salt (would have to match to work) and pass the same function to your login script that combines the salt and the supplied password. You would then check that to the value in your database to authenticate the user.
Do not invent your own password-hashing scheme, however nifty it may look. Having a secure system is hard because you cannot really test for security. What you need is the following:
For each password instance, a random salt of sufficient length is created.
The random salt is stored along the hashed value; you will need it to verify the password afterward.
The password hashing process must be (configurably) slow, with many (many) nested invocation of whatever hash function is internally used.
Preferably, the internal hash function should use operations which are efficient on a PC but slow on a parallel architecture (a GPU).
Such a thing exists, it is called bcrypt and you can get it in PHP with the portable PHP password hashing framework.