I have given a task to integrate our company system to external system via API. When I read about the API, it stated that the data should be encrypted using MD5 and Triple Des Encryption, so I made some research about how to do it.
// Here's the credentials to be used for encryption.
$key = 'dEvu4MHkqz7mRgeqmB1mQEXi';
$iv = "avz9bUNx";
The data should be formatted as JSON String before encryption.
$params = array(
'Number' => '+11177109886' // example
);
$text = json_encode($params);
After that I made some codes to encrypt it.
function apiEncode($text, $key, $iv)
{
// to append string with trailing characters as for PKCS7 padding scheme
$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
$padding = $block - (strlen($text) % $block);
$text .= str_repeat(chr($padding), $padding);
$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CBC, $iv);
return base64_encode($crypttext);
}
The error I got is.
Warning: mcrypt_encrypt(): Received initialization vector of size 0,
but size 32 is required for this encryption mode in
/Applications/XAMPP/xamppfiles/htdocs/dapsapi/rdremit.php on line 20
Related
I use the following PHP code to decrypt my AES 128 string.
function aes128_cbc_encrypt($key, $data, $iv) {
if(16 !== strlen($key)) $key = hash('MD5', $key, true);
if(16 !== strlen($iv)) $iv = hash('MD5', $iv, true);
$padding = 16 - (strlen($data) % 16);
$data .= str_repeat(chr($padding), $padding);
return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv);
}
$password = "mypasswordonthefirstrunoftheprogram";
$salt = "mysalthereitisfinallyitturnedoutok";
$encrypted = "BxGi119ltnYVNikXSP8jMJtSNIDKoMsPfd/nUEwlgSviVRM50/UgMF36j6Cqe+I/";
echo aes128_cbc_decrypt($key, $encrypted, $iv);
RIGHT RESULT =
this is my test sentence
RESULT RETURNED =
º±h©MM®StOfthis is my test sentenceok
Furthermore I decoded the string in C# with the right key and IV succesfully, so there is no error in that.
I wonder how this come ? I did the right padding and also tried the some other methods in php but all returning garbage in front of the right answer.
$encrypted length is not correct for encrypting "this is my test sentence".
The plain text is 26 characters
The padding would be 6-bytes
The string encrypted would be 32-bytes
The encrypted data would be 32-bytes
The Base64 encrypted data would be 44-bytes
The provided Base64 encrypted data is be 64-bytes
The provided encrypted data is be 48-bytes
There are an extra 16 bytes in the encrypted data
Examing the encrypted data there are an additional 16 bytes prepended to the encrypted bata prior to Base64 encoding.
Additionally the padding is not being removed from the decrypted data.
I'm trying to send an encrypted json file to the mobile app.
I'm using RIJNDAEL_128 with MODE_CBC using PHP Mcrypt module; all works perfect on Server A ( Hostmetro provider ) but when i try the same script to Server B ( Hostgator provider ) the data encrypted can't be decrypted from mobile app.
I'm using the same key and the same IV ( the IV is set to 'zero' : \0 ).
I have checked the mcrypt version and it is the same on server A and B, only PHP version is different.
I test the script on my localhost and the json encrypt is changed again.
All my test say that if i try to encrypt a string like 'text' the result is the same everywhere, but if i try with a json the result is very different : where is the problem?
Thanks.
Update:
The code of the encrypt function is:
$str = $decrypted;
$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
if (($pad = $block - (strlen($str) % $block)) < $block)
{
$str .= str_repeat(chr($pad), $pad);
}
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = ''; for($i=0;$i<$iv_size;$i++){ $iv .= "\0";}
return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $this->the_key, $str, MCRYPT_MODE_CBC, $iv));
This is the code of the decrypt funciton:
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = ''; for($i=0;$i<$iv_size;$i++){ $iv .= "\0";}
$str = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $this->the_key, base64_decode($encrypted), MCRYPT_MODE_CBC, $iv);
# Strip PKCS7 padding.
$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$pad = ord($str[($len = strlen($str)) - 1]);
if ($pad && $pad < $block && preg_match(
'/' . chr($pad) . '{' . $pad . '}$/', $str))
{
return substr($str, 0, strlen($str) - $pad);
}
return $str;
UPDATE 08/12/2014
I have tested the generation of encrypted file and my localhost and my first server ( Hostmetro ) give me a valid file; only Hostgator create a "corrupted" file that can't be decrypted.
Try a base64_encode / decode before encryption / decription ..
Ok, i have found the problem: the problem is that when json_encode() try to encode an multidimensional array and not all the contents are cast to string when you encrypt this json object it can be decrypted by PHP in other server or the same but not by the mobile app.
THE SOLUTION
The solution is cast data into String, transform the array with json_encode(), encrypt the json with mcrypt : all is working now.
I am working on some PHP code to perform AES string encryption and decryption. The encryption is working fine but I can't seem to decrypt it.
Below is the code that does the encryption and adds the required padding.
function encrypt($data)
{
$iv = "PRIVATE";
$key = CIPHERKEY;
return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, addpadding($data), MCRYPT_MODE_CBC, $iv));
}
function addpadding($string, $blocksize = 16)
{
$len = strlen($string);
$pad = $blocksize - ($len % $blocksize);
$string .= str_repeat(chr($pad), $pad);
return $string;
}
The code above is working fine the code below where it does the decryption keeps on failing. I try and do the decryption and then strip the padding but false is always returned from the padding function.
Below is the code that does the decryption and the stripping.
function strippadding($string)
{
$slast = ord(substr($string, -1));
$slastc = chr($slast);
$pcheck = substr($string, -$slast);
if(preg_match("/$slastc{".$slast."}/", $string)){
$string = substr($string, 0, strlen($string)-$slast);
return $string;
} else {
return "false";
}
}
function decrypt($data)
{
$iv = "PRIVATE";
$key = CIPHERKEY;
//$decoded = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv);
$decrytped = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv);
$base64Decoded = base64_decode($decrytped);
return strippadding($base64Decoded);
}
Thanks for any help you can provide.
In your decryption method, the decrypt and base64 steps are backwards. It's important that in whatever order you do your operations for encrypting, you do the reverse to decrypt.
In your encrypt method, you're base64 encoding the ciphertext:
base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, addpadding($data), MCRYPT_MODE_CBC, $iv));
When you decrypt, you need to undo the base64 encoding, and then decrypt that result.
$base64Decoded = base64_decode($data);
$decrytped = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $base64Decoded, MCRYPT_MODE_CBC, $iv);
Also, it looks like mcrypt will handle padding uneven blocks, so your addpadding() method might be superfluous.
You are using a too-short IV which is less than the blocksize. I assume this results in using a different IV on decryption. Blocksize is 16 bytes, so the IV should be 16 bytes, but your fixed-string IV is only 7 bytes (8 if you count the terminating zero byte which the underlying C code probably adds).
Instead of using a fixed string, you should be using a random IV generated by mcrypt_create_iv(). You can find out the length of one block by using mcrypt_get_iv_size() as shown in Example 1 in the mcrypt_create_iv() PHP manual. You would then send/store the random IV prepended to the ciphertext so you know what the IV was on decryption.
Also, mcrypt does its own padding, so you don't need to. And, as mfanto pointed out, you need to decode Base64 before decryption, not after.
I need to generate symmetrics keys with standard AES in ECB mode block and with PKCS5Padding, but I can't do it.
During my searches, I only found functions to encrypt something with this conditions above. But I don't want this; I want to generate a symmetric key.
I need to can communicate with a webservice and I need this, because is one part of encryption.
I have looked at phpseclib, but the library doesn't generate symmetric keys either.
First, to do PKCS#5 padding on the input you need to improvise:
// source: http://php.net/manual/en/ref.mcrypt.php#69782
function pkcs5_pad($text, $blocksize)
{
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}
Then select your algorithm and generate the IV:
$alg = MCRYPT_RIJNDAEL_128; // AES
$mode = MCRYPT_MODE_ECB; // not recommended unless used with OTP
$iv_size = mcrypt_get_iv_size($alg, $mode);
$block_size = mcrypt_get_block_size($alg, $mode);
$iv = mcrypt_create_iv($iv_size, MCRYPT_DEV_URANDOM); // pull from /dev/urandom
Initialize your encryption key:
$key = "This is a very secret key";
Apply padding to the input and encrypt it
$input = pkcs5_pad($input, $block_size);
$crypttext = mcrypt_encrypt($alg, $key, $input, $mode, $iv);
In php I have used this to create a symmetric key.
<?php
srand((double)microtime()*1000000 );
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', MCRYPT_MODE_CFB, '');
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
$ks = mcrypt_enc_get_key_size($td);
$key = substr(sha1('Your Secret Key Here'), 0, $ks);
mcrypt_generic_init($td, $key, $iv);
$ciphertext = mcrypt_generic($td, 'This is very important data');
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
print $iv . "\n";
print trim($ciphertext) . "\n";
?>
This would be a good starting place :
http://php.net/manual/en/function.mcrypt-create-iv.php
You can do this with a call to the phpseclib library, which can be adjusted to any cipher (AES, DES..), encryption mode, key length and optional PBKDF2 derivation.
Please see:
http://phpseclib.sourceforge.net/crypt/examples.html
I have an encrypted bit of text that I need to decrypt. It's encrypted with AES-256-CBC. I have the encrypted text, key, and iv. However, no matter what I try I just can't seem to get it to work.
The internet has suggested that mcrypt's Rijndael cypher should be able to do this, so here's what I have now:
function decrypt_data($data, $iv, $key) {
$cypher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
// initialize encryption handle
if (mcrypt_generic_init($cypher, $key, $iv) != -1) {
// decrypt
$decrypted = mdecrypt_generic($cypher, $data);
// clean up
mcrypt_generic_deinit($cypher);
mcrypt_module_close($cypher);
return $decrypted;
}
return false;
}
As it stands now I get 2 warnings and the output is gibberish:
Warning: mcrypt_generic_init() [function.mcrypt-generic-init]: Key size too large; supplied length: 64, max: 32 in /var/www/includes/function.decrypt_data.php on line 8
Warning: mcrypt_generic_init() [function.mcrypt-generic-init]: Iv size incorrect; supplied length: 32, needed: 16 in /var/www/includes/function.decrypt_data.php on line 8
Any help would be appreciated.
I'm not terribly familiar with this stuff, but it seems like trying MCRYPT_RIJNDAEL_256 in place of MCRYPT_RIJNDAEL_128 would be an obvious next step...
Edit: You're right -- this isn't what you need. MCRYPT_RIJNDAEL_128 is in fact the right choice. According to the link you provided, your key and IV are twice as long as they should be:
// How do you do 256-bit AES encryption in PHP vs. 128-bit AES encryption???
// The answer is: Give it a key that's 32 bytes long as opposed to 16 bytes long.
// For example:
$key256 = '12345678901234561234567890123456';
$key128 = '1234567890123456';
// Here's our 128-bit IV which is used for both 256-bit and 128-bit keys.
$iv = '1234567890123456';
I send to you one example,
Please, check the code, ok
$data_to_encrypt = "2~1~000024~0910~20130723092446~T~00002000~USD~F~375019001012120~0~0~00000000000~";
$key128 = "abcdef0123456789abcdef0123456789";
$iv = "0000000000000000";
$cc = $data_to_encrypt;
$key = $key128;
$iv = $iv;
$length = strlen($cc);
$cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128,'','cbc','');
mcrypt_generic_init($cipher, $key, $iv);
$encrypted = base64_encode(mcrypt_generic($cipher,$cc));
mcrypt_generic_deinit($cipher);
mcrypt_generic_init($cipher, $key, $iv);
$decrypted = mdecrypt_generic($cipher,base64_decode($encrypted));
mcrypt_generic_deinit($cipher);
echo "encrypted: " . $encrypted;
echo "<br/>";
echo "length:".strlen($encrypted);
echo "<br/>";
echo "decrypted: " . substr($decrypted, 0, $length);