public function kryptonite($string){
$salt = "";
$salt_vars = array_merge(range("A","Z"),range("a","z"),range(0,9));
for($i=0;$i < 22;$i++){
$salt.= $salt_vars[array_rand($salt_vars)];
}
return crypt($string, '$6$'.$salt);
}
This returns on refresh:
$6$vnuqcEA70$CHWmPVsDVb.lVpq1PNsDn7.0fSmBX6FU2PlofK6dJOH7FQp6EdSsde3Aw6to8fY1L01/WOcWz8OIE0OxK1LTj.
$6$7lmp9sD4g$I0fAcDjno2Lf255gg6TxTLt9TRwR803ZXiU9BOWJXhWrGbJdPJ3LvAW9w2KbRZ/3EDSSbFrgF7rV7DdB0VliA0
If you closely at the first few lines it's changing constantly. I don't think Hashing is suppose to constantly change! So technically I'll never be able to test against this. Can someone help me with my kryptonite crypt function or explain to me what went wrong really.
As a matter of fact, hashing is supposed to randomly change - it's called random salting. Your crypt function is creating a random salt which is fed to the SHA-512 hasher.
The output of crypt() includes the salt value, which you would then use when hashing a password to compare it to the stored hash.
public function kryptonite($string, $salt = null){
if ($salt === null) {
$salt = "";
$salt_vars = array_merge(range("A","Z"),range("a","z"),range(0,9));
for($i=0;$i < 22;$i++){
$salt.= $salt_vars[array_rand($salt_vars)];
}
$salt = '$6$' . $salt;
}
return crypt($string, $salt);
}
To use this, you'd just do the following:
$storedHash = '.....'; // fetched from database
$inputPassword = '.....'; // from the user
$salt = preg_match('/\$[0-9]\$(.+)\$/')[1]; // php 5.4+
if (kryptonite($inputPassword, $salt) == $storedHash) {
//.... success
}
Note that the array_random implementation of creating a random salt isn't cryptographically secure - it'd be better to use openssl_random_pseudo_bytes() or mt_rand() or such.
You won't be able to get the same result when using array_rand() I'd recommend something like this if you're going to use salts and need a two way encryption
function parse($action, $string) {
$output = false;
$encrypt_method = "AES-256-CBC";
// hash
$key = hash('sha256', "random encryption key that must stay the same");
// iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
$iv = substr(hash('sha256', "ARANDOMIV"), 0, 16);
if($action == 'encrypt') {
$output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
$output = base64_encode($output);
} else if( $action == 'decrypt' ){
$output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv);
}
return $output;
}
You won't get the same hashes when you're using the array_rand() function. The result needs to be deterministic.
Is there a reason why sha1() isn't good enough?
Related
I am using this function to encrypt a string :
function encrypt_decrypt($action, $string)
{
$output = false;
$encrypt_method = 'AES-256-ECB';
$secret_key = 'gT4ThOvcaFDccFFV21mg5hPzglZsY73T';
$key = hash('sha256', $secret_key);
if ( $action == 'encrypt' )
{
$output = openssl_encrypt($string, $encrypt_method, $key, 0);
$output = base64_encode($output);
}
else if( $action == 'decrypt' )
{
$output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0);
}
return $output;
}
I am using this function in 2 php files (same function no changes at all )
the only difference between the 2 files is :
File1.php is getting the string in HTTP GET request:
$Email = htmlspecialchars($_GET["Email"]);
$ENC_Email = encrypt_decrypt("encrypt",$Email);
echo($ENC_Email);
and File2.php is getting the very same string from cookies:
$Email = $_COOKIE['Email'];
$enc = encrypt_decrypt("encrypt",$Email);
echo($enc);
echo of the variable $Email is same in both cases , but the resulting encrypted string is different.
What am I missing here ?
It's normal. You encrypt a string, it's not the samething as hashing a string. A hash will give you always the same result. But encryption use random salt, randomIV and differents other random parameters. Then the result is always different.
But, when you decrypt, you must get the string you have encrypted before.
I want to create and encryption for get variabile passed in url and for asynchronous call
for example:
$textToEncrypt = "Hello World";
$encryptionMethod = "AES-256-CBC";
$secretHash = "cVb67YtfAz328oOikl96vBn";
$iv = "adfrf54dmnlo09ax";
$encryptedText = openssl_encrypt($textToEncrypt,$encryptionMethod,$secretHash, 0, $iv);
result is: W2p0S2qlSierJnIcA/AM3g==
there are some special characters, == always at the end. I want to prevent this! How can I output only 0-9 and A-Z and a-z characters?
thanks
I had the same issue. I wanted to remove the special characters. So, this is what I did. Convert the encrypted text into hex value using base64_encode($encryptedText). So, there will be no special characters. Then for the revert, use base64_decode before passing to openssl_decrypt.
$ciphering = "AES-128-CTR";
use this as your cipher string, it'll remove any type of == from the end
I notice I had exactly 2 equal signs at the end of my encrypted string too. It seems theres always 2 equal signs at the end. Here's my solution
function encryptString($string, $action, $baseIP = 'false', $extraKey = ''){
global $flag;
$encryptedIP = '';
if($baseIP){
$encryptedIP = encryptString($_SERVER['REMOTE_ADDR'], 'encrypt', false);
}
$output = false;
$encrypt_method = "AES-256-CBC";
$secret_key = $flag['2nd-encrypt-key'].$encryptedIP.'-'.$extraKey;
$secret_iv = $flag['2nd-encrypt-secret'].$encryptedIP.'-'.$extraKey;
$key = hash('sha256', $secret_key);
$iv = substr(hash('sha256', $secret_iv), 0, 16);
$output;
if($action == 'encrypt'){
$output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
$output = base64_encode($output);
//replace equal signs with char that hopefully won't show up
$output = str_replace('=', '[equal]', $output);
}else if($action == 'decrypt'){
//put back equal signs where your custom var is
$setString = str_replace('[equal]', '=', $string);
$output = openssl_decrypt(base64_decode($setString), $encrypt_method, $key, 0, $iv);
}
return $output;
}
How to encrypt and decrypt data in php?
My code so far is:-
function encrypter($plaintext)
{
$plaintext = strtolower($plaintext);
$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256,FLENCKEY,$plaintext,MCRYPT_MODE_ECB);
return trim(base64_encode($crypttext));
}
function decrypter($crypttext)
{
$crypttext = base64_decode($crypttext);
$plaintext = mcrypt_decrypt(MCRYPT_RIJNDAEL_256,FLENCKEY,$crypttext,MCRYPT_MODE_ECB);
return trim($crypttext);
}
$test = "abc#gmail.com";
echo encrypter(test);
Output is
iLmUJHKPjPmA9vY0jfQ51qGpLPWC/5bTYWFDOj7Hr08=
echo decrypter(test);
Output is
��-
In your decrypter() function, you return the wrong data.
You should return $plaintext instead of $crypttext:
function decrypter($crypttext)
{
$crypttext = base64_decode($crypttext);
$plaintext = mcrypt_decrypt(MCRYPT_RIJNDAEL_256,FLENCKEY,$crypttext,MCRYPT_MODE_ECB);
//return trim($crypttext);
return trim($plaintext);
}
The other code samples on this page (including the question) are not secure.
To be secure:
Don't use mcrypt.
Use authenticated encryption.
Never use ECB mode (a.k.a. MCRYPT_MODE_ECB).
See this answer for secure encryption in PHP.
This is what I use. Super simple.
function encrypt_decrypt($action, $string) {
$output = false;
$key = '$b#bl2I#?%%4K*mC6r273~8l3|6#>D';
$iv = md5(md5($key));
if( $action == 'encrypt' ) {
$output = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), $string, MCRYPT_MODE_CBC, $iv);
$output = base64_encode($output);
}
else if( $action == 'decrypt' ){
$output = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($key), base64_decode($string), MCRYPT_MODE_CBC, $iv);
$output = rtrim($output, "");
}
return $output;
}
You can change $key to whatever you want, or leave it. (this is not my key, btw)
encrypt_decrypt('encrypt', $str) to encrypt
encrypt_decrypt('decrypt', $str) to decrypt
Inside the decrypter function, change the
return trim($crypttext);
to
return trim($plaintext);
But looking at your function, I am not quite sure whether it will return exactly the same string, because of the strtolower function. You can't just do a strtoupper function as the original text may not be all in capital letters.
Warning
mcrypt_encrypt has been DEPRECATED as of PHP 7.1.0. Relying on this function is highly discouraged.
Use openssl_encrypt instead.
I need two functions/methods, one to encode, one to decode. This is not for storing passwords. Each user will have a specific key/salt to encode the data.
This is how I would like it to work:
function encode($str, $key) {
// something fancy
}
function decode($str, $key) {
// something fancy
}
$key = $logged_in_user->get_key();
$plain = 'abc abc 123 123';
$encoded_data = encode($plain, $key);
// some_fancy_encrypted_data_that_is_really_cooooool
$decoded_data = decode($encoded_data, $key);
// abc abc 123 123
Another thing is that every time I use this function it needs to return the same thing every time I use the encode function with the same user key.
How would I do this??
$myVarIWantToEncodeAndDecode
Define key (salt, broth etc..): $key = "#&$sdfdfs789fs7d";
To encode:
$encoded = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), $myVarIWantToEncodeAndDecode, MCRYPT_MODE_CBC, md5(md5($key))));
To decode:
$decoded = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($key), base64_decode($encoded), MCRYPT_MODE_CBC, md5(md5($key))), "\0");
Note: mcrypt_decrypt has been DEPRECATED as of PHP 7.1.0. Relying on this function is highly discouraged.
Use openssl_encrypt instead of mcrypt_encrypt
mcrypt_encrypt DEPRECATED as of PHP 7.1.0 and REMOVED as of PHP 7.2.0.
So, Try this..
function encrypt_decrypt($string, $action = 'encrypt')
{
$encrypt_method = "AES-256-CBC";
$secret_key = 'AA74CDCC2BBRT935136HH7B63C27'; // user define private key
$secret_iv = '5fgf5HJ5g27'; // user define secret key
$key = hash('sha256', $secret_key);
$iv = substr(hash('sha256', $secret_iv), 0, 16); // sha256 is hash_hmac_algo
if ($action == 'encrypt') {
$output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
$output = base64_encode($output);
} else if ($action == 'decrypt') {
$output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv);
}
return $output;
}
echo "Your Encrypted password is = ". $pwd = encrypt_decrypt('spaceo', 'encrypt');
echo "Your Decrypted password is = ". encrypt_decrypt($pwd, 'decrypt');
I have the following c# code that generates keys:
public static byte[] Encrypt(byte[] plainData, string salt)
{
DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
DES.Key = ASCIIEncoding.ASCII.GetBytes(salt);
DES.IV = ASCIIEncoding.ASCII.GetBytes(salt);
ICryptoTransform desencrypt = DES.CreateEncryptor();
byte[] encryptedData = desencrypt.TransformFinalBlock(plainData, 0, plainData.Length);
return encryptedData;
}
private string GetEncryptedKey(string key)
{
return BitConverter.ToString(KeyGeneratorForm.Encrypt(ASCIIEncoding.ASCII.GetBytes(key), "abcdefgh")).Replace("-", "");
}
I'm trying to perform the same thing in PHP:
function get_encrypted_key($key){
$salt = "abcdefgh";
return bin2hex(mcrypt_encrypt(MCRYPT_DES, $salt, $key, MCRYPT_MODE_CBC, $salt));
}
However, there is a small discrepency in the results, as the last 16 chars are always different:
With key "Benjamin Franklin":
C# : 0B3C6E5DF5D747FB3C50DE952FECE3999768F35B890BC391
PHP: 0B3C6E5DF5D747FB3C50DE952FECE3993A881F9AF348C64D
With key "President Franklin D Roosevelt":
C# : C119B50A5A7F8C905A86A43F5694B4D7DD1E8D0577F1CEB32A86FABCEA5711E1
PHP: C119B50A5A7F8C905A86A43F5694B4D7DD1E8D0577F1CEB37ACBE60BB1D21F3F
I've also tried to perform the padding transform to my key using the following code:
function get_encrypted_key($key){
$salt = "abcdefgh";
$extra = 8 - (strlen($key) % 8);
if($extra > 0) {
for($i = 0; $i < $extra; $i++) {
$key.= "\0";
}
}
return bin2hex(mcrypt_encrypt(MCRYPT_DES, $salt, $key, MCRYPT_MODE_CBC, $salt));
}
But I end up with the same results as without padding.
If you have any clue as to what's going on, I'd be glad to hear about it! :)
Thanks
You mentioned trying a "classic" padding snippet. The following quick adaptation of the snippet posted on the mcrypt_encrypt documentation gives the same results you were getting from C#.
PKCS #7 (the default padding scheme used by C#'s SymmetricAlgorithm) pads with bytes where each padding byte's value is the same as the number of bytes of padding, not with zero bytes.
function get_encrypted_key($key)
{
$salt = 'abcdefgh';
$block = mcrypt_get_block_size('des', 'cbc');
$pad = $block - (strlen($key) % $block);
$key .= str_repeat(chr($pad), $pad);
return bin2hex(mcrypt_encrypt(MCRYPT_DES, $salt, $key, MCRYPT_MODE_CBC, $salt));
}
Test output:
php > echo get_encrypted_key('Benjamin Franklin');
0b3c6e5df5d747fb3c50de952fece3999768f35b890bc391
php > echo get_encrypted_key('President Franklin D Roosevelt');
c119b50a5a7f8c905a86a43f5694b4d7dd1e8d0577f1ceb32a86fabcea5711e1