I am attempting to figure out what is wrong with my encryption/decryption code but I seem to be hitting a dead end in my Google searching for issues similar to mine.
Here is my php code for the two functions but I will explain first. How these work is by using a salt, the user's password, and the unix epoch time that they last logged in (or the current epoch time if they have never logged in before) to create the encrypted password.
Right now I am testing out the code to see if it works or not before hooking it into the rest of my php code. The password being passed to the function is Test and it is using time() to supply the time and then storing that value during the encryption process to a global variable so I do not have to store it into the database while testing.
In one SO thread, this one, I read that using MCRYPT_RAND when creating the IV and then not saving that produced IV meant that decrypt would never work because the IV would be different if you re-called mcrypt_create_iv to create the IV during the decryption. So I made a global for the IV as well and tried that in the decryption process but it still does not decrypt properly. The code below reflects that change.
//Encrypt the user's password for storing in database
function encrypt($password, $id)
{
echo "Function: encrypt \n"; //For debugging
$salt2 = getTime($id);
$salt1 = 'akey'; //Changed for security purposes
global $cur_iv;
$key = substr(hash('sha256',$salt1.$password.$salt2),0,32);
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256,MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size,MCRYPT_RAND);
$encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $password, MCRYPT_MODE_ECB, $iv));
$cur_iv = $iv;
echo $encrypted;
echo "\n";
global $cur_time;
$cur_time = $salt2;
return $encrypted;
}
//Decrypt the user's password for loggin checking
function decrypt($password,$id)
{
echo "Function: decrypt \n"; //For debugging
//$salt2 = getTime($id);
global $cur_time;
$salt2 = $cur_time;
$salt1 = 'akey'; //Changed for security purposes
global $cur_iv;
$key = substr(hash('sha256',$salt1.$password.$salt2),0,32);
$iv = $cur_iv;
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($pass), MCRYPT_MODE_ECB, $iv);
echo $decrypted;
echo "\n";
return $decrypted;
}
Encrypted this is what the password looks like: xgr5YB0vHwJAkjkqwTl6rnZMjbZL0qmLE4D8JXDT1rM=
But decrypted it looks like this: NÞÚ±=º)cz_öUñŽP´è8Åáó»d—+ÒAÐ
Edit 2:
Here is the getTime function as requested by Saikios:
//Use the last login time for part of the encryption salt to ensure more secure hashing
function getTime($id)
{
global $sql;
echo "Function: getTime \n"; //For debugging
if ($salt_stmt = $sql->prepare("Select Last_Login From login_log Where User_ID = ?;"))
{
$salt_stmt->bind_param('i',$id);
$salt_stmt->execute();
$salt_stmt->store_result();
$salt_stmt->bind_result($time);
$salt_stmt->fetch();
if ($salt_stmt->num_rows < 1)
{
echo "No last login \n";
$time = time();
}
else
{
echo "Last Login Time: ".$time."\n";
}
return $time;
}
else
{
echo "Error: ".$sql->error;
}
}
Here you can use mine, but please don't use md5('password') as your key :)
function symEncode($decrypted, $key){
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_RAND);
$iv_base64 = rtrim(base64_encode($iv), '=');
// Encrypt $decrypted and an MD5 of $decrypted using $key. MD5 is fine to use here because it's just to verify successful decryption.
$encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $decrypted . md5($decrypted), MCRYPT_MODE_CBC, $iv));
// We're done!
return $iv_base64 . $encrypted;
}
function symDecode($encrypted, $key){
// Retrieve $iv which is the first 43 characters plus ==, base64_decoded.
$iv = base64_decode(substr($encrypted, 0, 43) . '==');
// Remove $iv from $encrypted.
$encrypted = substr($encrypted, 43);
// Decrypt the data. rtrim won't corrupt the data because the last 32 characters are the md5 hash; thus any \0 character has to be padding.
//pre_var_export(debug_backtrace(false));
$decrypted = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($encrypted), MCRYPT_MODE_CBC, $iv), "\0\4");
// Retrieve $hash which is the last 32 characters of $decrypted.
$hash = substr($decrypted, -32);
// Remove the last 32 characters from $decrypted.
$decrypted = substr($decrypted, 0, -32);
// Integrity check. If this fails, either the data is corrupted, or the password/salt was incorrect.
if (md5($decrypted) != $hash){
die('failed');
}
// Yay!
return $decrypted;
}
$key = md5('password');
$decrypted = 'some important data';
$encrypted = symEncode($decrypted, $key);
echo $encrypted . '<br>';
echo symDecode($encrypted, $key);
Outputs:
43p2K/0RG20fnuHEx2B3q18KM7FpGLRfb+BwFfYt1V1mMr5PsAroum/jEeO6LonmC4T9N6QQQfOfMwTmbyNRFG4Qi5imGPAq0LsbgYJHWZ50Lw0C7uSRDb7CC1I4Uv1/LFQ==
some important data
And
$key = md5('password');
$decrypted = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc bibendum augue et vehicula adipiscing. Maecenas interdum, enim a accumsan convallis, est urna posuere mauris, eu ultricies lacus enim at justo. Vestibulum auctor sed elit a';
Outputs:
431nn42sTg7/XlGw4nAw3aFmMiYOnOQCVMjs4xY2m3DNcgiTFyqs1scG3VCxx/srEV9OGePqD4qrV1AectSqIWCSjYCinsS1jThEL9OuxxXeaGCbycXybdeMUCz1gKJZ5zVegMjqcWzyaX6/32sMs+Mh/NO+e9uh9lOdgmpofHEUWc9m4n6yziX2TllDKxbbADogeRjfW5SzzhaR/bx24kV9/44QhMRA1IJwFteHzCI9qTLGL/586MziGUVbZJe9Y9TqhiWEAIgJ0tO0iWVGMBYV1ibwv8VzDr0LcN7qL4345ryoQ3hjrixpLnBNKewKhbCB/4EkJ7+FD1nUyHOZLEyhi52oMqs/uDv1qSk/Pgk+Poku8DCd5ZbxbAJQG6Wp8BlZzfXOak1tyTKaJUsRziM/zmaXvpYrq3WWJti4cQaxc
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc bibendum augue et vehicula adipiscing. Maecenas interdum, enim a accumsan convallis, est urna posuere mauris, eu ultricies lacus enim at justo. Vestibulum auctor sed elit a