Issue with decrypting aes password in php - php

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.

Related

Message: mcrypt_encrypt(): The IV parameter must be as long as the blocksize

this is the first time I have come across this error and I am very confused as to how to fix this error. I will post my code below. Kindly request for whatever else is needed to facilitate in this. Any help will be greatly appreciated.
function encryptAes($string, $key)
{
$string = $this->addPKCS5Padding($string);
$crypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $string, MCRYPT_MODE_CBC, $key);
return strtoupper(bin2hex($crypt));
}
UPDATE: code on line number 777
function _encode_crypt($post = NULL)
{
return "#".$this->encryptAes($post,$this->encryption_password);
}
I'm going to assume the error you're getting is accurate and that you've actually made an honest mistake in having your encryption key ($key) and your initialisation vector (also $key) as the same value. This is wrong, in so many ways...
Instead try this:
$iv = mcrypt_create_iv(
mcrypt_get_iv_size(
MCRYPT_RIJNDAEL_128,
MCRYPT_MODE_CBC
),
MCRYPT_DEV_URANDOM
);
encryptAes('blah blah', 'some super secret key', $iv);
function encryptAes($string, $key, $iv)
{
$string = $this->addPKCS5Padding($string);
$crypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $string, MCRYPT_MODE_CBC, $iv);
return strtoupper(bin2hex($crypt));
}
You will need to store this initialisation vector somewhere to be able to decrypt.
Obviously, the $key value you were passing through was the incorrect length for the initialisation vector of the encryption algorithm you are using. You are using MCRYPT_RIJNDAEL_128 and as such the iv size should be 128 bits (16 bytes).

PHP AES 128 Decryption returning result with garbage in front

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.

Decryption is not working with AES 128 bit CBC in PHP

I'm trying to encrypt and decrypt a token with the AES 128 bit CBC encryption in PHP.
If I try to encrypt and decrypt a token, the result is not the original token.
Here is my code:
$decrKey = "123456789abcdefg";
$decrIV = "xyz123456789abcd";
function encryptAES($data,$key,$iv)
{
$decr= mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, base64_encode($data), MCRYPT_MODE_CBC, $iv);
return $decr;
}
function decryptAES($data,$key,$iv)
{
$decr= mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, base64_decode($data), MCRYPT_MODE_CBC, $iv);
return $decr;
}
$token = "abcdefghijk";
echo $token;
$tokenEncrypt = encryptAES($token,$decrKey,$decrIV);
echo "encrypt: ".$tokenEncrypt ;
$tokenDecrypt = decryptAES($tokenEncrypt,$decrKey,$decrIV);
echo "decrypt: ".$tokenDecrypt ;
What do i miss?
You should base 64 encode the result of the encryption method (called the ciphertext), and decode it again before decryption. You are currently base 64 encoding the plain text in the encryption function instead of the ciphertext. Encoding the plain text is not necessary. It would be however a good idea to use a well defined character-encoding for the plain text.
$encr = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv));
return $encr

DES encryption in PHP

I am coding a Drupal payment method module and within this I need to generate a hash to send to a bank. Bank asks me to code certain strings into the DES/ECB hash. They also provide test environment and here comes my problem. With the string B7DC02D5D6F2689E and key 7465737465703031 I should get result hash 3627C7356B25922B (after bin2hex, of course). This is by the bank test page and I have also checked this on this page: http://www.riscure.com/tech-corner/online-crypto-tools/des.html (encryption java applet).
My problem is that whatever I do I cant get my PHP code to provide the correct result. This is a simple function I am trying to use:
function encrypt($hash, $key)
{
$hash = strtoupper(substr(sha1($hash), 0, 16));
$key = strtoupper(bin2hex($key));
$block = mcrypt_get_block_size('des', 'ecb');
if (($pad = $block - (strlen($hash) % $block)) < $block) {
$hash .= str_repeat(chr($pad), $pad);
}
$sig = strtoupper(bin2hex(mcrypt_encrypt(MCRYPT_DES, $key, $hash, MCRYPT_MODE_ECB)));
return $sig;
}
and I have been trying sth like this as well:
function encrypt( $value, $key) {
$hash = strtoupper(substr(sha1($value), 0, 16));
$key = strtoupper(substr(bin2hex($key), 0, 16));
// encrypt hash with key
if (function_exists('mcrypt_module_open')) { // We have mcrypt 2.4.x
$td = mcrypt_module_open(MCRYPT_DES, "", MCRYPT_MODE_ECB, "");
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size ($td), MCRYPT_RAND);
mcrypt_generic_init($td, $key, $iv);
$signature = strtoupper(bin2hex(mcrypt_generic ($td, $hash)));
mcrypt_generic_end ($td);
}
else
{ // We have 2.2.x only
$signature = strtoupper(bin2hex(mcrypt_ecb (MCRYPT_3DES, $key, $hash, MCRYPT_ENCRYPT)));
}
return $signature;
}
None of these gave the correct signature. Any idea what's wrong? For now I am dealing with this issue more than 3 hrs, so I appreciate any help. I am not very familiar with this encryption stuff. Thanks a lot.
Btw.: Those $hash and $key mentioned above are after the strtoupper, substr and bin2hex functions at the beginning of my code snippets.
Simple solution:
function encrypt($hash, $key) {
return mcrypt_encrypt("des", pack("H*", $key), pack("H*", $hash), "ecb");
}
print bin2hex(encrypt("B7DC02D5D6F2689E", "7465737465703031"));
This prints 3627c7356b25922b for me, so it looks like that's working.
You were on the right track with bin2hex(), but that was converting in the wrong direction. (There's unfortunately no hex2bin() function, so you have to use pack() instead.)
You also don't need an IV for a single-block encryption like this.
You plaintext, B7DC02D5D6F2689E, is 8 bytes = 64 bits. This is an exact block for DES so you don't need any padding in ECB mode. I suggest that you remove the padding code entirely. All DEC-ECB needs in this case is the block to encrypt and the key; no padding and no IV.

How to do AES256 decryption in PHP?

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);

Categories