I am trying to use mcrypt to store a password on my database. First of all, it WORKS, but only some of the time.
Here is my encryption code:
//Encryption/Decryption key
$key = $username.$username.$username.$username.$username;
//Encryption Algorithm
$cipher_alg = MCRYPT_RIJNDAEL_256;
$iv = mcrypt_create_iv(mcrypt_get_iv_size($cipher_alg, MCRYPT_MODE_ECB), MCRYPT_RAND);
$password = mcrypt_encrypt($cipher_alg, $key, $pass1, MCRYPT_MODE_CBC, $iv);
This then uploads the $username, the $iv and the $password to the MySQL database.
Here is my decryption code:
//Encryption/Decryption key
$key = $username.$username.$username.$username.$username;
//Encryption Algorithm
$cipher_alg = MCRYPT_RIJNDAEL_256;
$dbpass = mcrypt_decrypt($cipher_alg, $key, $encpass, MCRYPT_MODE_CBC, $random);
$dbpass = trim($dbpass); // Trim the fat
The $username, $iv, and $encpass(encrypted password) are retrieved from the database and the key is recreated using the username.
This WORKS but only sometimes. I can't figure out why. My only assumption is that the database can't accept some of characters the encryption produces such as quotations.
Any help would be greatly appreciated!
$salt = time(); // I would use something other than time(), something more random
// store it in the db and redirect user
connect();
$query = mysql_query("INSERT INTO user VALUES
('".mysql_real_escape_string($username)."',
'".mysql_real_escape_string(sha1($password . $salt))."',
'".mysql_real_escape_string($salt)."') ");
// returning user
$username = $_POST['username'];
$password = $_POST['password'];
// retrieve stored password
connect();
$result = mysql_query("SELECT * FROM user WHERE username = '".mysql_real_escape_string($username)."' ");
$row = mysql_fetch_assoc($result);
if (!$result) {
// user doesn't exist
}
$storedPassword = $row['password'];
$salt = $row['salt'];
$hashedPassword = sha1($password . $salt);
if ($storedPassword != $hashedPassword) {
// exit
}
else {
// redirect user
}
I'm not claiming this is the most secure, it is simply just a small example of one way hashing with a salt.
You can try below code for 2 way encryption. You may add salt with password as per your requirement.
$key = 'ecryptionkey';
$string = 'password';
$encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), $string, MCRYPT_MODE_CBC, md5(md5($key))));
$decrypted = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($key), base64_decode($encrypted), MCRYPT_MODE_CBC, md5(md5($key))), "\0");
var_dump($encrypted);
var_dump($decrypted);
I got this code from below URL and I'm using it in my application.
https://stackoverflow.com/a/9262137/1724762
If you are storing a user's password in the database, you should be using one-way hashing
Here is just a very minimalist example
$username = $_POST['username'];
$password = $_POST['password'];
$salt = 'Some Salt';
$result = mysql_query("SELECT username, password
WHERE username = '".mysql_real_escape_string($username)."'
AND password = '".mysql_real_escape_string(sha1($password . $salt))."'
LIMIT 1");
if(mysql_num_rows($result)) {
// we have a match
}
else {
// no match
}
You would have to be inserting user passwords with an appended salt using sha1 in my example. Keep in mind, this is just a suggestion for storing user passwords in the database.
Agreed that for your particular use case (storing users' passwords), a one-way hash would be best.
But for people who really do need to use mcrypt and PHP and MySQL, see the various options in MySql insert binary data to db without errors. One easy option is base64_encode/base64_decode -- here's an example.
Related
I'm creating users with encrypted passwords on database using mcrypt method like this:
$key = '1234567890123456';
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size);
$encryp_pass = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $password2, MCRYPT_MODE_ECB, $iv);
mysql_query("UPDATE usuarios SET pass_usuario = '".$encryp_pass."' WHERE id_usuario = '".$id_user[0]."' ");
...so that user just created is stored in database with his password encrypted.
Now, when that user logs into the system what i do (or what i'm trying to do) is encrypt the password he inputs on the textfield so then i compare that value with the value on the database. I encrypt the password the same way i did when creating the user like this:
$key = '1234567890123456';
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size);
$encryp_pass = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $password, MCRYPT_MODE_ECB, $iv);
$query_pass_existe = mysql_query("SELECT pass_usuario FROM usuarios WHERE nick_usuario = '".$nick."'");
$pass_user_fromDB = mysql_fetch_assoc($query_pass_existe);
Then i compare both passwords: the one extracted from database and the one encrypted from the login form:
if (utf8_encode($encryp_pass) == utf8_encode($pass_user_fromDB['pass_usuario'])) {
echo 'both are equals';
}else{
echo 'they're totally different';
}
Right now, i'm getting both as different. So i print them to see the result:
echo utf8_decode($pass_user_fromDB['pass_usuario']);
echo "<br>";
echo utf8_decode($encryp_pass);
echo "<br>";
but they are ALMOST alike, take a look:
=???0?1y?Y7h???[.?0????1m
=???0?1y?Y7h???\[.?0????1m
They are ALMOST the same but because of that \ i can't continue with the login successfully. I've checked the column and i have set it as: utf8_general_ci. I'm thinking on using AES encryption but i read on this article that for mysql is better to use mcrypt.
When I store my hashed password, it goes in as 29 characters, but when I hash for the password validation it is 64. The first 29 characters match, but I either need to lengthen the stored hash or shorten the validation hash. I have looked around the net and SO but can't seem to explicitly find out how to do this.
Which option (lengthen or shorten) is preferable and how would I go about doing this?
Here is my hash storage:
$hash = hash('sha256', $password1);
function createSalt(){
$text = md5(uniqid(rand(), true));
return substr($text, 0, 3);
}
$salt = createSalt();
$password = hash('sha256', $salt . $hash);
and here is my password validation and echoing of the hashes (which don't match up):
$userData = mysql_fetch_array($result, MYSQL_ASSOC);
$hash = hash('sha256', $userData['salt'] . hash('sha256', $password) );
if($hash != $userData['password']) // Incorrect password.
{ echo $userData['password'];
echo $hash;
die ('incorrect password : ' . mysql_error());
}
Thanks for any help, I sincerely appreciate it!
I am having a serious issue with trying to validate my password when logging into my site. I am using php to create a blowfish encrypted password with salt using the code below.
<?php
function cryptPass($p, $rounds = 9) {
$salt = "";
$saltChars = array_merge(range('A','Z'),range('a','z'),range('0','9'));
for($i = 0; $i < 22; $i++){
$salt .= $saltChars[array_rand($saltChars)];
}
return crypt($p, sprintf('$2y$%02d$', $rounds) . $salt);
}
?>
This works fine and the crypted password is put into my mysql database. the problem is on login it will not validate. this is the login script.
if(isset($_POST["u"])){
// CONNECT TO THE DATABASE
include_once("php_includes/db_connect.php");
// GATHER THE POSTED DATA INTO LOCAL VARIABLES AND SANITIZE
$u = mysqli_real_escape_string($db_connect, $_POST['u']);
include_once("php_includes/hasher.php");
$p = (cryptPass($_POST['p']));
// GET USER IP ADDRESS
$ip = preg_replace('#[^0-9.]#', '', getenv('REMOTE_ADDR'));
// FORM DATA ERROR HANDLING
if($u == "" || $p == ""){
echo "login_failed";
exit();
} else {
// END FORM DATA ERROR HANDLING
$sql = "SELECT id, username, password FROM users WHERE username='$u' AND activated='1' LIMIT 1";
$query = mysqli_query($db_connect, $sql);
$row = mysqli_fetch_row($query);
$db_id = $row[0];
$db_username = $row[1];
$db_pass_str = $row[2];
if($p != $db_pass_str){
echo "login_failed";
exit();
} else {
//goto the users account
should I not be running the cryptPass function on the incoming user data?
Also of note would be that the mysql database password column is set up as VARCHAR(255) so its got plenty of room. At this point the password crypts right, I am just not able to compare it to the one in database properly. This is my first real try with blowfish pieced together from tutorials all over, I wanted to get away from md5 as php.net advises. Any help would be greatly appreciated. Thanks in advance for reading this.
Here's a slightly more in-depth demonstration as what's found on the PHP crypt() man page:
// Only for demonstration, see mcrypt_create_iv() for a better salt:
// http://php.net/manual/en/function.mcrypt-create-iv.php
$salt = substr(sha1(date('r')), rand(0, 17), 22);
$cost = 10;
$hash = '$2y$' . $cost . '$' . $salt;
$pass = 'mypass';
$notpass = 'notmypass';
$hashed = crypt($pass, "$hash");
echo "
Hash:
$hash
Hashed:
$hashed
Verified:
" . crypt($pass, $hashed) . "
Not Verified:
" . crypt($notpass, $hashed);
https://ignite.io/code/51323c3aec221e7b73000000
Which gives (at least this time):
Hash:
$2y$10$a80ded6289240c2e41a5e4
Hashed:
$2y$10$a80ded6289240c2e41a5euUFPvmt.sb6lBwOE.JTAdxQsDWmmM.Me
Verified:
$2y$10$a80ded6289240c2e41a5euUFPvmt.sb6lBwOE.JTAdxQsDWmmM.Me
Not Verified:
$2y$10$a80ded6289240c2e41a5euj06Emi8HigWM6BpqVFZ.ZtpA9wK5c8G
To verify the password you need the salt that was used to create the first password hash. This salt is included in the output string of the crypt() function, and crypt can extract this salt from the password hash.
You can see well how it works when you look at the new hash functions from PHP 5.5 password_hash() and password_verify()...
$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT);
$isPasswordCorrect = password_verify($password, $existingHashFromDb);
...the function that verifies the login password, needs the hash of the first password. It then can extract the salt and the cost factor from this string, to hash the login password with the same parameters.
I can recommend this new functions, there is a compatibility pack for earlier versions.
Is it a good way to change password value each time a user log in to the database?
I have wrote a hash function to hash the password when a user register a new account on the system.
Each time the user logs in, the hash value in the database will be changed. Is it good or bad?
If you designed this hash function all by your self then... It is a very very bad idea. Why would you need something like this? If you store salted SHA-256 hashed passwords the security is good enough. You do not need to regenerate passwords, it does not provide any additional security. If lets say your app is prone to SQL-Injection, then this scheme won't protect your app. You would be a lot better if you used salted and keyed SHA-256, something like this: (I'm not a php coder, I just want our apps to be secure)
$username = 'Admin';
$password = 'gf45_gdf#4hg';
$key = 'MySuperSecretKEY!!!!';
$salt = hash('sha256', uniqid(mt_rand(), true) . 'something random' . strtolower($username));
$hash = $salt . $password . $key;
$hash = hash('sha256', $hash);
$hash = $salt . $hash;
and then checking:
$username = 'Admin';
$password = 'gf45_gdf#4hg';
$sql = '
SELECT
`hash`
FROM `users`
WHERE
`username` = "' . mysql_real_escape_string($username) . '"
LIMIT 1
;';
$r = mysql_fetch_assoc(mysql_query($sql));
$salt = substr($r['hash'], 0, 64);
$hash = $salt . $password . $key;
$hash = hash('sha256', $hash);
$hash = $salt . $hash;
if ( $hash == $r['hash'] ) {
//OK
}
So even if attacker will be able to trick the salting algorithm he does not know, a key so he won't be able to reproduce a valid hash in SQL-Injection attack.
I have registered a new user and saved the username, password & salt in the DB using the following hashing method:
if(isset($_POST['register']))
{
$password = $_POST['password']
function sanitize($data)
{
$data=trim($data);
$data=htmlspecialchars($data);
$data=mysql_real_escape_string($data);
return $data;
}
$password = sanitize($password);
function createSalt()
{
$salt = bin2hex(mcrypt_create_iv(32,MYCRYPT_DEV_URANDOM));
$hash = hash("sha256", $salt);
$final = $salt.$hash;
return $final;
}
$hashedPassword = hash("sha256", $password);
$salt = createSalt();
$hashedPassword = hash("sha256", $hashedPassword.$salt);
$query = sprintf("INSERT INTO users(username, password, salt) VALUES('%s','%s','%s')",$username, $hashedPassword, $salt);
}
And Later while trying the login.php, I am entering the same password which I saved during registration and using the below code to check if the entered password is the same as the one in the DB
if(isset($_POST['login']]))
{
$password = $_POST['password']
function sanitize($data)
{
$data=trim($data);
$data=htmlspecialchars($data);
$data=mysql_real_escape_string($data);
return $data;
}
function validateUser()
{
session_regenerate_id (); //this is a security measure
$_SESSION['valid'] = 1;
$_SESSION['username'] = $username;
}
$password = sanitize($password);
$query = sprintf("SELECT * FROM users WHERE username = '%s'",$username);
$sql = mysql_query($query);
$count = mysql_num_rows($sql);
$row = mysql_fetch_array($sql);
if($count<1)
{
echo $count;
unset($_POST['login']);
header("location:login.php");
exit;
}
$hash = hash("sha256", $password);
$salt = $row['salt'];
$hash = hash("sha256",$hash.$salt);
echo $hash."<br />".$row['password']."<br /><br />";
if($hash != $row['password'])
{
unset($_POST['login']);
header("location:login.php");
exit;
}
else
{
validateUser();
unset($_POST['login']);
header("location:index.php");
exit;
}
}
These passwords are not getting matched.
Kindly let me know what's wrong in this code.
There is nothing wrong with your code.
the salt value stored in the database is truncated because the varchar value is low increase the varchar value of your salt column to 200-300 something and than try this.. it will run fine.
I facepalmed when I found out this was screwing the result..
Dins
Actually i didn't see why this should not work, the code you have shown, should produce the same value, maybe you could check, whether the salt you read from the database is really the same as you wrote to the database.
Nevertheless i would not engourage to go further on this route, there are quite a lot of problems here.
First of all, SHA-256 is not a good choice to hash passwords, instead use a slow key-derivation function like BCrypt.
You should not escape input data without need, and if you need to escape them, you should do it only for the specific target system (htmlspecialchars and mysql_real_escape_string make no sense if you are going to calculate a hash anyway).
To create a salt, you use the random source, that is good. Using a hash afterwards creating the salt, will in no way make the salt more random.
There is no need to have two separate fields for password and salt in the database. Php's crypt() function will create a hash value, that already contains the salt.
I would invite you to read this tutorial about hashing passwords, you will find a PHP example too, and i would recommend to use the phpass library.