SHA 1 hash_hmac wrong - php

I have a big problem with hash_hmac
function
function hmac($key, $data){
$blocksize = 64;
$hashfunc = 'sha1';
if (strlen($key) > $blocksize)
$key = pack('H*', $hashfunc($key));
$key = str_pad($key, $blocksize, chr(0x00));
$ipad = str_repeat(chr(0x36), $blocksize);
$opad = str_repeat(chr(0x5c), $blocksize);
$hmac = pack('H*', $hashfunc(($key ^ $opad) . pack('H*', $hashfunc(($key ^ $ipad) . $data))));
return bin2hex($hmac);
}
example is:
<?php
echo hmac('111111', '222222');//=1558ab6c5ab2b0d1cd129b9ad11527cf33486705
but my
$jeden = 111111;
$dwa =222222;
$hashWiadomosci = hash_hmac('sha1', $jeden, $dwa);
is: 22f91d281349bb3081d3cec9f906572eec5c55b2
how i do wrong?

You have your input variables in the wrong order. If you look at the example from the comment you got this from; you can see that it is hmacsha1($key, $data) and not hmacsha1($data, $key) like you are using it and how hash_hmac($algorithm, $data, $key) works.
echo hash_hmac('sha1', '111111', '222222'); // 22f91d2813...
echo hmacsha1('111111', '222222'); // 1558ab6c5a...
echo hash_hmac('sha1', '111111', '222222'); // 22f91d2813...
echo hmacsha1('222222', '111111'); // 22f91d2813...

Related

CryptoJS equivalent in PHP using openssl method

I created this question to share a PHP version (based on the version at CryptoJS extra parameter in AES Encrypt. How to replicate with PHP?) of a script that has the same return as CryptoJS, this version in PHP that no longer uses the mbcrypt methods (which are deprecated after PHP 7.1.0)
<?php
class CryptoJS {
const ALGO_METHOD = 'AES-256-CBC';
public static function encrypt(string $plaintext, string $password) {
$salt = substr(md5(mt_rand(), true), 8);
$block = openssl_cipher_iv_length(self::ALGO_METHOD);
$pad = $block - (strlen($plaintext) % $block);
$data = $plaintext . str_repeat(chr($pad), $pad);
$iv_len = openssl_cipher_iv_length(self::ALGO_METHOD);
$key_len = $iv_len * 2;
$total_len = $key_len + $iv_len;
$salted = '';
$dx = '';
while (strlen($salted) < $total_len) {
$dx = md5($dx . $password . $salt, true);
$salted .= $dx;
}
$key = substr($salted, 0, $key_len);
$iv = substr($salted, $key_len, $iv_len);
$encrypted_data = openssl_encrypt($data, self::ALGO_METHOD, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
return base64_encode('Salted__' . $salt . $encrypted_data);
}
public static function decrypt(string $edata, string $pass) {
$data = base64_decode($edata);
$salt = substr($data, 8, 8);
$ct = substr($data, 16);
$rounds = 3;
$data00 = $pass . $salt;
$md5_hash = array();
$md5_hash[0] = md5($data00, true);
$result = $md5_hash[0];
for ($i = 1; $i < $rounds; $i++) {
$md5_hash[$i] = md5($md5_hash[$i - 1] . $data00, true);
$result .= $md5_hash[$i];
}
$key = substr($result, 0, 32);
$iv = substr($result, 32, 16);
return openssl_decrypt($ct, self::ALGO_METHOD, $key, true, $iv);
}
}
$pass = $text = '{TextAndPass}';
$encrypted = CryptoJS::encrypt($text, $pass);
$decrypted = CryptoJS::decrypt($encrypted, $pass);
var_dump($encrypted, $decrypted);

Equivalent to hash_hmac in oppenssl_* functions

What would be an equivalent for:
hash_hmac('sha256', 'data', 'key')
if I were using openssl_*?
openssl_digest does not take $key parameter.
This function uses the openssl_* extension to hash the data and the key:
Code
function openssl_hmac($algo, $data, $key, $raw_output = false)
{
$algo = strtolower($algo);
$pack = 'H' . strlen(openssl_digest('test', $algo));
$size = 64;
$opad = str_repeat(chr(0x5C), $size);
$ipad = str_repeat(chr(0x36), $size);
if (strlen($key) > $size) {
$key = str_pad(pack($pack, $algo($key)), $size, chr(0x00));
} else {
$key = str_pad($key, $size, chr(0x00));
}
for ($i = 0; $i < strlen($key) - 1; $i++) {
$opad[$i] = $opad[$i] ^ $key[$i];
$ipad[$i] = $ipad[$i] ^ $key[$i];
}
$output = openssl_digest($opad . pack($pack, openssl_digest($ipad . $data, $algo)), $algo);
return ($raw_output) ? pack($pack, $output) : $output;
}
Usage
echo openssl_hmac('sha256', 'data', 'key', false);
Result:
5031fe3d989c6d1537a013fa6e739da23463fdaec3b70137d828e36ace221bd0
The result is the same as when using the hash_hmac function:
echo hash_hmac('sha256', 'data', 'key');
Result:
5031fe3d989c6d1537a013fa6e739da23463fdaec3b70137d828e36ace221bd0

Some Strings Won't Decrypt

I have a function to encrypt and decrypt a string with a salt/password, but there's an issue, I have no problem encrypting any string, but with decrpyting it has a problem decrypting some strings...
For example it will decrypt "Hello World", but not "Login" or "RedeemToken"... The code i'm using is below with some outputs and debugging stuff:
function encrypt($data)
{
$secret = "FUSIONIDISTOPNOTCHCODEDBYMELTYNET";
//Generate a key from a hash
$key = md5(utf8_encode($secret), true);
//Take first 8 bytes of $key and append them to the end of $key.
$key .= substr($key, 0, 8);
//Pad for PKCS7
$blockSize = mcrypt_get_block_size('tripledes', 'ecb');
$len = strlen($data);
$pad = $blockSize - ($len % $blockSize);
$data .= str_repeat(chr($pad), $pad);
//Encrypt data
$encData = mcrypt_encrypt('tripledes', $key, $data, 'ecb');
return base64_encode($encData);
}
function decrypt($data)
{
$secret = "FUSIONIDISTOPNOTCHCODEDBYMELTYNET";
//Generate a key from a hash
$key = md5(utf8_encode($secret), true);
//Take first 8 bytes of $key and append them to the end of $key.
$key .= substr($key, 0, 8);
$data = base64_decode($data);
$data = mcrypt_decrypt('tripledes', $key, $data, 'ecb');
$block = mcrypt_get_block_size('tripledes', 'ecb');
$len = strlen($data);
$pad = ord($data[$len-1]);
return substr($data, 0, strlen($data) - $pad);
}
Also the functions above are used like this:
echo encrypt($string);
echo decrypt($string);
Example of some strings that encrypt, but will not encrypt:
Login - Doesn't Decrypt
RedeemToken - Doesn't Decrypt
Blacklist - Decrypt Works
Email - Decrypt Works
If anyone can point out the issue or help, please let me know, thanks!
HERE IS MY CODE:
USE - "http://example.com/test.php?st=xeJuD3+A0Po="
<?php
$string123 = mysql_escape_string($_GET["st"]);
echo decrypt($string123);
function encrypt($data)
{
$secret = "FUSIONIDISTOPNOTCHCODEDBYMELTYNET";
//Generate a key from a hash
$key = md5(utf8_encode($secret), true);
//Take first 8 bytes of $key and append them to the end of $key.
$key .= substr($key, 0, 8);
//Pad for PKCS7
$blockSize = mcrypt_get_block_size('tripledes', 'ecb');
$len = strlen($data);
$pad = $blockSize - ($len % $blockSize);
$data .= str_repeat(chr($pad), $pad);
//Encrypt data
$encData = mcrypt_encrypt('tripledes', $key, $data, 'ecb');
return base64_encode($encData);
}
function decrypt($data)
{
$secret = "FUSIONIDISTOPNOTCHCODEDBYMELTYNET";
//Generate a key from a hash
$key = md5(utf8_encode($secret), true);
//Take first 8 bytes of $key and append them to the end of $key.
$key .= substr($key, 0, 8);
$data = base64_decode($data);
$data = mcrypt_decrypt('tripledes', $key, $data, 'ecb');
$block = mcrypt_get_block_size('tripledes', 'ecb');
$len = strlen($data);
$pad = ord($data[$len-1]);
return substr($data, 0, strlen($data) - $pad);
}
?>
Found ;)
In your URL, use http://example.com/test.php?st=xeJuD3%2BA0Po%3D as =+ and other char are not allowed tu be used in URL.
Take a look at http://php.net/manual/fr/function.rawurlencode.php to craft right URL from your base64 encrypted data
If you can't change the URL before it hit PHP, you'll have to change back the space in + :
$_GET['st'] = str_replace(' ', '+', $_GET['st']);
And BTW, remove the $string123 = mysql_escape_string($_GET["st"]); mysql_ is for mysql, nothing else, it's not a magic spell you cast everywhere. the only thing it does is change ' to \' and it wont help you anywhere; even in MySQL it's now depreciated and you need to use PDO or mysqli
for this :
<?php
function encrypt($data)
{
$secret = "FUSIONIDISTOPNOTCHCODEDBYMELTYNET";
//Generate a key from a hash
$key = md5(utf8_encode($secret), true);
//Take first 8 bytes of $key and append them to the end of $key.
$key .= substr($key, 0, 8);
//Pad for PKCS7
$blockSize = mcrypt_get_block_size('tripledes', 'ecb');
$len = strlen($data);
$pad = $blockSize - ($len % $blockSize);
$data .= str_repeat(chr($pad), $pad);
//Encrypt data
$encData = mcrypt_encrypt('tripledes', $key, $data, 'ecb');
return base64_encode($encData);
}
function decrypt($data)
{
$secret = "FUSIONIDISTOPNOTCHCODEDBYMELTYNET";
//Generate a key from a hash
$key = md5(utf8_encode($secret), true);
//Take first 8 bytes of $key and append them to the end of $key.
$key .= substr($key, 0, 8);
$data = base64_decode($data);
$data = mcrypt_decrypt('tripledes', $key, $data, 'ecb');
$len = strlen($data);
$pad = ord($data[$len-1]);
return substr($data, 0, strlen($data) - $pad);
}
echo "'". ($a = encrypt('Email'))."'<br>\n";
echo "'".decrypt($a)."'<br>\n";
echo "'".decrypt('AA/PpTmKWjY=')."'<br>\n";
echo "'".($e= encrypt('Login'))."'<br>\n";
echo "'".decrypt($e)."'<br>\n";
echo "'".decrypt('xeJuD3+A0Po=')."'<br>\n";
I get :
'AA/PpTmKWjY='
'Email'
'Email'
'xeJuD3+A0Po='
'Login'
'Login'
So, for me it work fine...

mcrypt_encrypt fails to initialise

I am trying to encrypt some data in PHP using the Rijndael cipher in CBC mode with a 256bit key but for some reason I get the following error message:
mcrypt_encrypt() Module initialization failed
My code:
$hashKey = hash('sha256',$key);
$iv = hash('sha256',$hashKey);
// ------Cipher-------------key-------------Data-------------Mode---------IV--
$encryptedQuestion = base64_encode(mcrypt_encrypt('MCRYPT_RIJNDAEL_256', $hashKey , $_POST['question'], MCRYPT_MODE_CBC, $iv));
Can anyone see whats wrong with this?
There are a few issues with the code that I can spot:
Your $iv should not be dependent on $hashKey; rather, you should create it separately using mcrypt_create_iv().
Your $hashKey should be binary rather than textual.
MCRYPT_RIJNDAEL_256 is a constant, it should not be passed as a string.
The following code is more verbose than yours, but it should give you an insight in the steps required to encrypt something:
$crypto = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', MCRYPT_MODE_CBC, '');
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($crypto), MCRYPT_DEV_URANDOM);
$hkey = hash('sha256', $key, true);
mcrypt_generic_init($handle, $hkey, $iv);
$enc_question = mcrypt_generic($handle, $_POST['question']);
mcrypt_generic_deinit($handle);
mcrypt_module_close($handle);
I've also left out any error checks.
I got a similar error. I assigned the constants to a variable and passed the variable and that was the cause of the error.
This failed for me
>
return new encKey($cipher_name, $mode, $value);
Now this works
>
return new encKey(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB, $value);
In php 5.6 try mcrypt_ecb to overcome the invalid key issue
$choice ="2";
$key = "1234";
$key = hash("sha512", $key, TRUE);
for ($x = 0; $x < 8; $x++) {
$key = $key . substr($key, $x, 1);
}
$msg = "pato";
echo("key is".$key." \n");
if ($msg == ''){
die("Please enter a text to encrypt! ");
}
if ($key == ''){
die("Please enter a key! ");
}
function pkcs5_pad($text, $blocksize) {
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}
function pkcs_pad($text, $blocksize) {
//$pad = $blocksize - (strlen($text) % $blocksize);
$tes=substr($text,0,$blocksize) ;
return $tes;
}
function encryptnow( $thekey, $themsg)
{
$padded = pkcs5_pad($themsg, mcrypt_get_block_size(MCRYPT_3DES, MCRYPT_MODE_CBC));
echo("padded".$padded."\n");
$keypad = pkcs_pad($thekey, mcrypt_get_key_size(MCRYPT_3DES, MCRYPT_MODE_CBC));
$i;
//$iv=pkcs5_pad($i, mcrypt_get_block_size(MCRYPT_3DES, MCRYPT_MODE_CBC));
//$iv = mcrypt_create_iv(8, MCRYPT_DEV_RANDOM);
// echo("padded".$keypad."\n");
$encrypted = base64_encode(mcrypt_ecb(MCRYPT_3DES, $keypad, $padded, MCRYPT_MODE_CBC));
echo "<html><hr size='2' ></html>";
echo "<P><P><b>Plain Text : </b>";
echo($themsg);
echo "<p><b>Cipher Text : </b> ";
echo "$encrypted";
die();
}
if ($choice == '2'){
encryptnow($key, $msg);
}

Signature for OAuth

I'm trying to set up my own OAuth provider, but now I'm stuck at signing requests. Is this the right way for signing?
function generateSignature($consumerSecret, $requestURI, $requestData, $requestMethod) {
$signature = '';
$signature .= strtoupper($requestMethod) . '&';
$signature .= urlencode($requestURI) . '&';
asort($requestData);
$query = http_build_query($requestData);
$signature .= urlencode($query);
echo oauthHMACsha1($consumerSecret, $signature);
}
function HMACsha1($key, $data) {
$blocksize = 64;
$hashfunc = 'sha1';
if (strlen($key) > $blocksize) $key = pack('H*', $hashfunc($key));
$key = str_pad($key, $blocksize, chr(0x00));
$ipad = str_repeat(chr(0x36), $blocksize);
$opad = str_repeat(chr(0x5c), $blocksize);
$hmac = pack('H*',$hashfunc(($key^$opad).pack('H*', $hashfunc(($key ^ $ipad) . $data))));
return $hmac;
}
function oauthHMACsha1($key, $data) {
return base64_encode(HMACsha1($key, $data));
}
Or can it be easier/more efficient? And why is signing important?
Have you seen hash_hmac php function?

Categories