I use codeigniter a lot, however I am not really understanding why when I use the encryption library in version 3 the encryption string never comes out the same, even using the same salt/key.
So I have stored a user password as an encrypted string, which uses their own key to encrypt. The key is stored in the database. But when they come to login, and i want to encrypt the entered password to check the strings match, they never do match!
It seems the library always spits out different encrypted strings, no matter if the key is the same or not, how is this going to be useful if I can't match the stored encrypted password to the password they enter at login?
For example, password is 12456 with key a0956f251b9d957071005a2d11e4630a
SAVED PASSWORD IS: 0e6effa48949d6bf19e84530bc86e9a1407086b3b88fc368b6f8b7b53304b313eeebdb695c9cca10b3e7072f608bf4137e7fcc7d24fed54df2b6dcba3f94dcb6Tm05Qmay9G8JuUXps6UstWebmBmJ71BcIPgrW78OvSY=
PASSWORD GENERATED FROM USER LOGIN
6b893dac92155bc663b126b805c7189214ac4667b226f0c6fc22cf0c6bcca5e897c49961e8852ade1c3e85cbecab89df76ea7891727af6bf0bcc232b75d0d441LLUMZgOy4zLwAypuVQuK0lKTXrlXYptKpVdByytH2D8=
935c8f564c4a5ecb53510faa835eca8622069c34d534df6b9c2ea52de2d9bea5976128f6ff83a572ac677be4ebd690bc18e488518c2eed8b1b40a16c9e61d6b2hbKJ6B1VDuLPCXBeDDFzvrlSBIYCtN19M6dQGZRCvUE=
b8e020c7c10d564cfc3a9cc4d50b85ea3422422b73a2dd79930ead1fb601493279ba97645584d6dfa188e62f5eba5dc66d0dafdb7a82c08bf847bc84fc0718daSOVRrDlFmVMB/12ok9kR68ekXJcJvw0yfo/cnU9ojtI=
see they are different every time I try to encrypt the user input? It's not making any sense.
Likewise, if I try to decode the password in the database, with the same key it was encrypted with, I get nothing back, no decrypted password.
So, does anyone know what is going on here?
Randomized encryption is a security property necessary to achieve semantic security. If the encryption would not be randomized then an attacker might detect whether (prefixes of) messages were previously sent only by observing the ciphertexts. You generally don't want the attacker to know anything about the plaintexts except the length.
An encryption function has always a corresponding decryption function. It seems that you're only using one way of the two functions. You should never encrypt your user's passwords. You need to use hashing instead with some strong ones being PBKDF2, bcrypt, scrypt and Argon2. Since hash functions are one-way function, you won't be able to "decrypt" the hashes. In order to authenticate your user, you can run the password through the hash function again in order to compare with the hash that is stored in the database. See more: How to securely hash passwords?
Codigniter documentation:
DO NOT use this or any other encryption library for user password
storage! Passwords must be hashed instead, and you should do that via
PHP’s own Password Hashing extension.
http://www.codeigniter.com/userguide3/libraries/encryption.html
Fully explained here:
http://php.net/manual/en/faq.passwords.php
Try the md5 encryption its good and best till now.
In controller before send password like this:
md5($this->input->post('password));
or use hash() or SHA256/SHA512 they do it well.
It will do the trick.
Enjoy!
I have a hashed password using the Hash::make() function of laravel when a user is created. I eventually need to take that hashed password, and pass it to a python script to perform a login and download of site resources. I know the hash is a one-way action, but I'd like to keep the password hashed to be security conscious if at all possible.
Any suggestions on how to accomplish this task while keeping security intact would be helpful!
Thanks,
Justin
you cant the best you can do is encrypt it with a reversible encryption ... but then you need to store the key somewhere ... eventually you will have some plain text somewhere (or encoded at best) that will allow decryption ... you could store the hash and do a query against a db that maps hashes to pw's but you still have the password in plaintext somewhere ... you cannot login with just a hash anywhere ... (because the hash ends up getting hashed and then no longer matches the expected hash)
an option may be to use rainbow tables to find something that results in an identical hash and use that instead ... but if they are adding salts or anything you are once again out of luck
I am using php for a basic application to login into the system, be able to edit account information, and delete account. I have a mysql database. I need to encrypt/decrypt password using salt. How do I do it? Just need to make sure data is secure.
You don't want to encrypt passwords. You want to hash them.
Some reading:
http://php.net/manual/en/faq.passwords.php
Related SO post: how to hash the password and get it back
Passwords should be hashed, in contrast to encryption this is a one-way function, that should make it impossible to get back the original password.
Store only the hash-value in the database, and compare against this value for login.
Use a unique salt per password, it can be stored plaintext in the same database field as your hash-value.
Use a slow key-derivation function like Bcrypt, to prevent brute-force attacks.
It's recommended to use a well established library like phpass to build the hashes. For further reading have a look at this tutorial.
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).
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.