Database encryption - php/mysql - php

I have some doubts about the best way to do a database with passwords. I need encryption in the passwords, but if i use MD5 i can't recover the pass, isn't it?
And the base64 encoder ? it is secure? with this encryption the recover isn't more a problem.
Suggestions? what is the best way? e prefer a solution that permit to remember the old pass, and not define a new one password.
Thanks!!!
If anybody know a good tutorial about secure passwords in a database i really appreciate that

if i use MD5 i can't recover the pass,
isn't it?
Indeed, if you hash your password using md5 or sha1 (adding a salt is a good idea, btw), you will not be able to recover the password ; and that's the goal of doing so !
The idea is if anyone is able to take a look at your database (be it some evil doer, or one of your employees -- who can be an evil-doer), he will not be able to find any usefull password.
what is the best way? e prefer a solution that permit to
remember the old pass, and not define
a new one password.
The best way is to do the opposite of what you want : not allow one to get his old password -- and develop some way of generating a new password.
This way, you will ensure that no-one is able to get a dump of your logins and corresponding password ; which will make your service safer for your users (especially considering that many people use the same login/password couple of several websites).

MD5 is not used for encryption (which implies that it can be decrypted) but rather for message digestion/hashing. Base64 is also not encryption but rather encoding, which can be decoded with no effort.
There is usually little point in storing encrypted passwords in a database if they can be easily decrypted.
The secure approach is to store only hashes and compare submitted passwords to stored hashes after hashing them on the fly.
You should be doing something along the lines of:
$salt = 'some2%string!!here1';
$hash = sha1( $salt . $_POST['password'] );
to create a hash of the password. You store that hash in the database. When a user wants to log in, you take his submitted function, hash it using the same process, and compare to the hash in the database. If they match, the password is correct.

First off, there's a Significant Difference Between Hashing and Encryption. I suggest that you give that a read before going on...
Now, as to your exact question, there are a few ways to go about it.
Encrypt your passwords with a strong cipher so that you can decrypt them when necessary. A solution such as the one in this post may work for that. However, please note that this isn't a great idea, since if your system is ever compromised, all the passwords will be leaked (never a good idea). There are very few use-cases where it makes sense to store them encrypted, but if you absolutely must, please use a strong cryptographic encryption routine to do it...
Store your passwords using a strong one-way hashing method. No, md5($password) is not good enough. But neither is sha1($salt . $password). The first is trivial to lookup most passwords, and the second can be brute-forced in a reasonable amount of time by simple trial and error. Instead, stretch your passwords iteratively. The best way is to use the standard PBKDF2 function to generate a strong one-way key from the password.
As far as how to recover if the user forgets a password, don't worry about it. If the user forgets his password, create a new one and give that one to the user. It's the industry standard way of dealing with forgotten passwords (Heck, both Windows and Mac do it that way). You may think that you're doing your users a favor by sending it to them, but all you're doing is turning off anyone who has a clue about security from every using your application (and making a lot of people mad if you get compromised).

base64 isn't "encryption". It's intended to convert binary data into a format that's safe for transmission through potentially "broken" email systems that can't process 8-bit binary data properly. It's a best the equivalent of a cereal box decoder ring.
If you want encryption, there's AES, DES, and various other functions available. Problem is, if your code can decrypt the password, the it's trivial for an attacker to figure out how you do it, and/or subvert your code to do it for them.
Passwords should never be stored in a format where the plaintext can be retrieved. If a user forgets their password, you wipe out the old one, generate a new temporary one, and force them to change this temporary password to something else on first login.

You should not ever need to remember the user's password - to do so is a violation of their trust and presents a security hole.
Normally you will hash the password with MD5 (these days it's better to use SHA-2), and when the user submits their password to try and log in, hash that password as well, and see if the hashes are a match.
For added security, you can create a "salt" column to the database and generate a random salt when the password is first submitted. Add the salt to the beginning of the password, and then hash it. Store the hash of the salt+password, and the salt together. Now when the user submits his password to log in, you would combine it with the salt, hash it, and check if the hash is a match.
The salt ensures that if multiple users have the same password (chances are they do), their password hashes will not be identical.
If the user forgets their password they will have to provide a new one, simply storing their password and sending it back to them when they forget is bad practice and a sign to the user that you aren't handling their privacy very well.

As mentioned, use a hash instead of encryption when saving passwords. I generally don't use a random salt since this means an extra field in the DB so that you can authenticate the user. The simplest solution is to use the password as the salt as shown below. Easy to use and easy to authenticate.
$salt = $_POST['password'];
$hash = sha1( $salt . $_POST['password'] );

Stop now and read this. Then go find an open source library to do user authentication. I'm not a PHP dev, so I can't refer you to one, but I'm sure they exist. They'll have had the security holes found already.
Also, for passwords, you should be looking at bcrypt or similarly slow hash functions for passwords anyways, instead of using a fast hash algorithm like MD5 or SHA.

Related

Password Database on PHP file

A quick question for you! This is my first WEB application...
Is it safe leaving the password visible in the PHP file or there is a way to protect/hide it?
Thank you
Davide
There exists different situations to store a password, which cannot be handled in the same manner.
The worst case for security is, when you need the password later in cleartext for another service. From your comment i can see that this is your situation, you need to store the database login credentials. There is not much you can do, but storing the password in a separate include file, and place it somwhere above the root directory.
A little better is the case, when your application needs to store a fix password only for verification. Then you can store a hash of the password, so even if somebody can read your code, he doesn't know the plaintext password. An example of this case is a protected directory with HTTP-auth.
The best case is when you have to store user passwords. Then one should absolutely calculate a hash of the password, so that nobody but the user ever knows (or can retrieve) the password. Recommended algorithms are BCrypt, PBKDF2 and SCrypt (see password_hash()). Never use MD5 or SHA-* because they are too fast and can be brute-forced too easily.
I included the three cases in the answer, because sooner or later surely you will stumble over the other cases as well.
No, it is not safe or a good practice to keep the password visible anywhere. Even you/developer should not know the password except the user.
Use hash for encrypting the password and sha256/sha512 is considered best algorithm for hashing.
No, You must always think about security. If passwords are stored in plain text, what happens if an attacker gains access to your database? He can easily read all of the users’ passwords. That’s why we use a technique called password hashing to prevent attackers from getting user passwords.
Use md5() php function to secure your password .
$password = md5($password);

What is md5() for?

I was reading this tutorial for a simple PHP login system.
In the end it recommends that you should encrypt your password using md5().
Though I know this is a beginners' tutorial, and you shouldn't put bank statements behind this login system, this got me thinking about encryption.
So I went ahead and went to (one of the most useful questions this site has for newbies): What should a developer know before building a public web site?
There it says (under security) you should:
Encrypt Hash and salt passwords rather
than storing them plain-text.
It doesn't say much more about it, no references.
So I went ahead and tried it myself:
$pass = "Trufa";
$enc = md5($pass);
echo $enc; #will echo 06cb51ce0a9893ec1d2dce07ba5ba710
And this is what got me thinking, that although I know md5() might not the strongest way to encrypt, anything that always produces the same result can be reverse engineered.
So what is the sense of encrypting something with md5() or any other method?
If a hacker gets to a password encrypted with md5(), he would just use this page!.
So now the actual questions:
How does password encryption work?
I know I have not discovered a huge web vulnerability here! :) I just want to understand the logic behind password encryption.
I'm sure I'm understanding something wrong, and would appreciate if you could help me set my though and other's (I hope) straight.
How would you have to apply password encryption so that it is actually useful?
What about this idea?
As I said, I may/am getting the whole idea wrong, but, would this method add any security in security to a real environment?
$reenc = array(
"h38an",
"n28nu",
"fw08d"
);
$pass = "Trufa";
$enc = chunk_split(md5($pass),5,$reenc[mt_rand(0,count($reenc)-1)]);
echo $enc;
As you see, I randomly added arbitrary strings ($reenc = array()) to my md5() password "making it unique". This of course is just a silly example.
I may be wrong but unless you "seed the encryption yourself" it will always be easily reversible.
The above would be my idea of "password protecting" and encrypted password, If a hacker gets to it he wont be able to decrypt it unless he gets access to the raw .php
I know this might not even make sense, but I can't figure out why this is a bad idea!
I hope I've made myself clear enough, but this is a very long question so, please ask for any clarification needed!
Thanks in advance!!
You should have an encryption like md5 or sha512. You should also have two different salts, a static salt (written by you) and then also a unique salt for that specific password.
Some sample code (e.g. registration.php):
$unique_salt = hash('md5', microtime());
$password = hash('md5', $_POST['password'].'raNdoMStAticSaltHere'.$unique_salt);
Now you have a static salt, which is valid for all your passwords, that is stored in the .php file. Then, at registration execution, you generate a unique hash for that specific password.
This all ends up with: two passwords that are spelled exactly the same, will have two different hashes. The unique hash is stored in the database along with the current id. If someone grab the database, they will have every single unique salt for every specific password. But what they don't have is your static salt, which make things a lot harder for every "hacker" out there.
This is how you check the validity of your password on login.php for example:
$user = //random username;
$querysalt = mysql_query("SELECT salt FROM password WHERE username='$user'");
while($salt = mysql_fetch_array($querysalt)) {
$password = hash('md5',
$_POST['userpassword'].'raNdoMStAticSaltHere'.$salt[salt]);
}
This is what I've used in the past. It's very powerful and secure. Myself prefer the sha512 encryption. It's actually just to put that inside the hash function instead of md5 in my example.
If you wanna be even more secure, you can store the unique salt in a completely different database.
Firstly, "hashing" (using a cryptographic one way function) is not "encrypting". In encryption, you can reverse the process (decryption). In hashing, there is (theoretically) no feasible way of reversing the process.
A hash is some function f such that v cannot be determined from f(v) easily.
The point of using hashing for authentication is that you (or someone seeing the hash value) do not have any feasible way (again, theoretically) of knowing the password. However, you can still verify that the user knows his password. (Basically, the user proves that he knows v such that f(v) is the stored hash).
The weakness of simply hashing (aside from weak hash functions) is that people can compile tables of passwords and their corresponding hash and use them to (effectively) get the inverse of the hash function. Salting prevents this because then a part of the input value to the hash is controlled and so tables have to be compiled for that particular salt.
So practically, you store a salt and a hash value, and authenticate by hashing a combination of the salt and the password and comparing that with your hash value.
MD5 is a one way hashing function which will guard your original password more or less safely.
So, let's say your password is "Trufa", and its hashed version is 06cb51ce0a9893ec1d2dce07ba5ba710.
For example, when you sign in to a new webpage, they ask you for your username and password. When you write "Trufa" as your password, the value 06cb51ce0a9893ec1d2dce07ba5ba710 is stored in the database because it is hashed.
The next time you log in, and you write "Trufa", the hashed value will be compared to the one in the database. If they are the same, you are authenticated! Providing you entered the right username, of course.
If your password wasn't stored in its hashed form in database, some malicious person might run a query somehow on that database and see all real passwords. And that would be compromising.
Also, since MD5 is a 128 bit cryptographic function, there are 2^128-1 = 340282366920938463463374607431768211455 possible combinations.
Since there are more possible strings than this, it is possible that 2 strings will generate the same hash value. This is called a collision. And it makes sure that a hashed password cannot be uniquely reverse engineered.
The only vulnerability with salting is that you need to know what the salt is in order to reconstruct the hash for testing the password. This is gotten around by storing the entry in the authdb in the form <algorithm>$<salt>$<hash>. This way the authdb entry can be used by any code that has access to it.
You're missing the important step - the salt. This is a unique (per user, ideally) bit of extra data that you add to the password before hashing it.
http://en.wikipedia.org/wiki/Salt_%28cryptography%29
Your idea (salting) is well known and is actually well-implemented in the PHP language. If you use the crypt() function it allows you to specify a string to hash, a method to encrypt (in some cases), and a salt. For example,
$x = crypt('insecure_password', $salt);
Returns a hashed and salted password ready for storage. Passwords get cracked the same way that we check if they're right: we check the hash of what the user inputs against the hash of their password in the database. If they match, they're authenticated (AFAIK this is the most common way to do this, if not the only). Insecure passwords (like password) that use dictionary words can be cracked by comparing their hash to hashes of common passwords. Secure passwords cannot be cracked this way, but can still be cracked. Adding a salt to the password makes it much more difficult to crack: since the hacker most likely doesn't know what the salt is, his dictionary attack won't work.
For a decent hash the attacker won't be reversing the hash, they'll be using a rainbow table, which is essentially a brute-force method made useful if everyone uses the same hash function.
The idea of a rainbow table is that since hashing is fast I can hash every possible value you could use as a password, store the result, and have a map of which hash connects to which password. If everyone just takes their passwords and hashes them with MD5 then my hash table is good for any set of password hashes I can get my hands on!
This is where salting comes in. If I take the password the user enters and add some data which is different for every user, then that list of pre-determined hashes is useless since the hash is of both the password and some random data. The data for the salt could be stored right beside the password and even if I get both it doesn't help me get the password back since I still have to essentially brute force the hash separately for every single user - I can't form a single rainbow table to attack all the hashes at once.
Of course, ideally an attacker won't get the list of hashed passwords in the first place, but some employees will have access so it's not possible to secure the password database entirely.
In addition to providing salt (or seed), the md5 is a complex hashing algorithm which uses mathematical rules to produce a result that is specifically not reversable because of the mathematical changes and dataloss in throughput.
http://en.wikipedia.org/wiki/Cryptographic_hash_function
md5 (or better put: hash algorithms in general) are used to safely store passwords in database. The most important thing to know about hashes is: Hashes are not encryptions per se. (they are one-way-encryptions at most). If you encrypt something, you can get the data back with the key you used. A hash generates a fixed-length value from an arbitrary input (like a string), which can be used to see if the same input was used.
Hashes are used to store sensitive, repeatly entered data in a storage device. Doing this, nobody can recreate the original input from the hash data, but you can hash an incoming password and compare it to the value in the database, and see if both are the same, if so, the password was correct.
You already pointed out, that there possibilites to break the algorithm, either by using a database of value/hash pairs or producing collisions (different values resulting in the hash value). You can obscure this a bit by using a salt, thus modifying the algorithm. But if the salt is known, it can be used to break the algorithm again.
I like this question. But I think you've really answered yourself.
The site you referenced uses dictionary lookups of known, unsalted, md5's - it doesn't "crack" anything.
Your example is almost good, except your application needs to be able to regenerate the md5 using the same salt every time.
Your example appears to use one of the random salts, which will fail 2 of 3 times if you try to compare a users password hash to something input.
People will tell you to also use SHA1 or SHA256 to be have a 'stronger' hash - but people will also argue that they're all 'broken.'
That documentation is misleading -- it teaches a "vulnerable" concept and presents it as somehow being "secure" because it (the saved password) looks like gibberish. Just internet junk that won't die. The following link should clear things up (you have already found a good bit of it though, it seems. Good work.)
Enough With The Rainbow Tables: What You Need To Know About Secure Password Schemes talks about MD5 (and why it should not be used) along with salt (e.g. how to thwart rainbow attacks) as well as provides useful insights (such as "Use someone else’s password system. Don’t build your own"). It is a fairly good overview.
This is my question about the aspects of md5 collision, slightly related to your question:
Is there any difference between md5 and sha1 in this situation?
The important part is in the first 3 rows, that is: you must put your salt before the password, if you want to achieve stronger protection, not after.
To simply answer the title of your question, md5's only real use nowadays is for hashing large strings (such as files) to produce checksums. These are typically used to see if both strings are identical (in terms of files, checksums are frequently used for security purposes to ensure a file being distributed hasn't been tampered with, for example).
To address each of your inline questions:
How does password encryption work?
How would you have to apply password encryption so that it is actually useful?
Secure password hashing works by taking the password in plain text form, and then applying a costly hashing function to it, salted with a cryptographically secure random salt to it. See the Secure hash and salt for PHP passwords question for more detail on this.
What about this idea?
Password hashing does not need to be complicated like that, and nor should it be. Avoid thinking up your own algorithms and stick with the tried and tested hashing algorithms already out there. As the question linked above mentions, md5() for password hashing has been obsolete for many years now, and so it should be avoided.
Your method of generating a "random" salt from an array of three different salts is not the randomness you're looking for. You need unique randomness that is suitable for cryptographically secure (i.e. using a cryptically secure pseudo-random number generator (CSPRNG)). If you're using PHP 7 and above, then the random_bytes function can be used to generate a cryptographically secure salt (for PHP 5 users, the random_compat library can be used).

Password recovery with sha1 password hashing

I'd like to implement a forgot password function for my website. I hash the passwords using sha1. How would I recover this for the user?
What's the best method for implementing this?
Short answer, you can't.
You want to implement a password reset function, not a password retrieval function. The whole point of hashing passwords is that you don't get to store the user's password, and you can't recover it if it is lost.
This should give you a rough idea of how to allow users to reset forgotten passwords:
The best method is to not attempt to recover the original password. If a user loses their password then generate a new, random one and use an out-of-band method for sending it to them (e.g. email). Remember that the whole point of hashing the password is to prevent recovery.
I know, I know, email is insecure. But if you require users to immediately change the generated password then the risk is mitigated.
By the way, I cannot recommend enough that you also salt the password and iterate the hash to prevent brute-force attacks in the event that an attacker obtains the hashed value.
NO
There is no known effective way of reverting a sha1 hash to it's original text (since it's a one way function by design). If you would like to be able to show users their password at a later time, you will have to store it in a method that would be reversible (IE encryption, plaintext). This still is probably a bad idea, try to find a better way of doing it.

PHP & MySQL security: one-way encryption Vs two-way encryption

I have read about using MySQL AES_ENCRYPT/AES_DECRYPT (two-way encryption) is less secure than using PHP - hash() (one-way encryption).
http://bytes.com/topic/php/answers/831748-how-use-aes_encrypt-aes_decrypt
Is it true that it is more secure that 'Rather than send the User his password, simply send him a link that he can click on to reset his password, instead.'?
And on top of that, if I am using MySQL AES_ENCRYPT/AES_DECRYPT (which I quite keen on...), how do I define the key which can be accepted by MySQL? for instance, is the length of the key important? or can I simple use '123123#123123' as my key?
thanks!
There is a fundamental difference between the two concepts, hashing and encryption:
Encryption can be reversed, hashing can't (at least that's the idea).
If a malicious user gains access to the passwords in a database and knows the key you used to encrypt them, they will be able to recover said passwords. If they are hashed, they won't be able to do that.
That's why passwords should be always be hashed (and salted), never encrypted.
for instance, is the length of the key important? or can I simple use '123123#123123' as my key?
AFAIK MySQL's AES_ENCRYPT can take keys of arbitrary length; but obviously shorter keys will make it easier for an attacker to bruteforce it (ie: try all possible combinations)
Two way encryption is inherently less secure because the real data is stored somewhere. That is, you have a password "hello." Then you hash it, you get 5d41402abc4b2a76b9719d911017c592. This is meaningless to a normal person and they will not know how to decrypt it without knowing the correct encryption algorithm. They cannot use this either because only the original password is used. You check a password by hashing it and comparing it to the hash (also stored). 5d41402abc4b2a76b9719d911017c592 hashed is 69a329523ce1ec88bf63061863d9cb14, so they don't match. Even if a user knows the hashed password, he can't get anything out of it.
So you can store the encrypted data, but if you decrypt it when you are pulling it out then anyone can use it.
The security of sending a user a link compared to giving them the password is a different issue. If you email the password, it is printed out in plain text for all to see (and use). Giving them a link to allow them to input a new password means no one will see it which is a bit more secure, but if someone committing fraud has access to that link anyway it is going to cause problems.
About AES, I can't find out too much on it at a glance, but it looks like it doesn't matter what you encrypt. So if you use AES_DECRYPT(AES_ENCRYPT('x', 'b'), 'b'); it will return 'x'. You have to keep track of the key.
If you are storing passwords on your server with symmetric encryption, you have to decode the stored password to test it against a user-submitted password. That means the key also has to be stored on the server. Which means anyone who compromises your webapp can retrieve and decrypt every user's password. (And use them to compromise other accounts where the user has used the same password.)
Hashing a password means that you can't leak the password to an attacker because you don't even know what it is yourself. You can still check whether a submitted password is the same as the original password by hashing it using the same algorithm and salt, so you can still tell whether a submitted password is right or wrong, without having to know what the password is.
Using hashed passwords does mean you can't tell the user what their password was in a ‘recover password’ option. But you don't really want to do that anyway, especially over an insecure mechanism like e-mail. One-time, time-limited reset-password links serve the same purpose with less potential damage.
For passwords, one-way hashes are almost always the way to go. One-way hashes mean that there is far less likelihood that anyone but the user would be able to know their password.
If you choose the one-way route, then you'll need to set up a password reset method. If this is done correctly, it should be fairly secure for most purposes. To gain better security, you can add things like security questions (e.g., "What is your favorite color?") that the user would have to answer before receiving a password reset link in an email.
As for keys for AES_ENCRYPT/DECRYPT-- MySQL will accept variable lengths for the key parameter to the functions, but it will use a 128-bit key regardless, so it's to your advantage to pass at least 128 bits' worth.
One-way encryption means you can only encrypt. (For example, you encrypt a password and store the result. Whenever a user authenticates, you encrypt what the user enters and compare. There is no need for a decrypt function in such a scenario.)
Two-way encryption means, there is both an encrypt and decrypt function available. In PHP, that is accomplished through the mcrypt_encrypt() and mcrypt_decrypt() functions.
An update! mcrypt is deprecated in PHP 7.1 and removed in 7.2. See OpenSSL or Sodium instead for encrypt and decrypt functions.

How to generate secure passwords for new users?

I have a list of students that are being added via a form inside the admin area. I'm trying to come up with a password generating solution for each addition that will be both secure and viewable from the admin panel (like below).
I need it to be viewable so that the admin will be able to print out the passwords and hand them out to the parents. But I also want them to be secure in case there's a database breach. Any ideas?
If you want the passwords to be viewable, they can never be really secure in case of a breach.
You may be interested in checking out the following Stack Overflow posts for further reading:
Difference between Hashing a Password and Encrypting it
How should I ethically approach user password storage for later plaintext retrieval?
Store passwords in 2 forms:
1) MF5/SHA1 hash for secure validation
2) AES encripted with master password. I.e. in order to view passwords you enter master password and bingo. In case of theft attacker would not get passwords that easy (but can bruteforce).
This is one of the few times I would say the software shouldn't be adjusted to the user(s). You're talking a major security risk here.
I would advice making some kind report generator to print passwords that creates (generates / salts and hashes and saves) them on the fly for printing. With this, you could generate the letters to be send as well. Makes the process mostly automated and a person would only have to send them to the printer (if that's even necessary).
Good luck.
You should not do this.
Generate a one-time password that can be used (and could also be stored in clear text) to set a new password via web.
As soon as the passwords are printed, they can be easily accessed by others, so it does not matter at all if you store them encrypted or not.
You can have one XOR the other.
If the passwords are to be secure, you mustn't store them in the database (store some_hash(per_user_salt + password) and compare that on login (as #Daniel Vassallo says)
If the passwords are to be viewable, then you must provide some way to get to the passwords - and if there is one, it can be abused (e.g. passwords stolen). If you decide that you absolutely, positively need to do this, encrypt the passwords in your application before storing them to the database. This won't shield you from all threats, but at least the passwords won't be readable if someone "only" steals your database.
Others have had the right idea, but were missing an essential step. You should use asymmetric encryption and store a public-key encrypted form of the password + salt.
To verify a password, take the proffered password, combine it with the salt, use the public key to encrypt the combination, and compare it with the stored value.
To retrieve the password, use the private key (kept secure, i.e. on another isolated machine) to decrypt the password + salt and throw away the salt.
Cons: asymmetric encryption can be expensive, computationally, but passwords tend to be short.
You could combine this with other ideas above (i.e. also store a salted hash), and you should pad the password so that the length of the encrypted text doesn't leak the password length.

Categories