Home » Php » php mcrypt to javascript aes integration

php mcrypt to javascript aes integration

Posted by: admin July 12, 2020 Leave a comment

Questions:

I am trying to use javascript to encode data with AES-256-CBC and php mcrypt libraries to decode, and vise versa.

I am aware of the problematic nature of javascript and the fact that anyone sees the key, but I am using javascript a scripting tool for non-web environment – so not worried about it.

I found pidder https://sourceforge.net/projects/pidcrypt/

and encrypted some data with the demo page, then tried to decrypt it via php, but something is wrong and I can’t seem to find what… I am using the same key with both ends, a 32 byte string

any pointers will be appreciated

~~~

$encrypted = "string after pidder encryption";  

$cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_256,'',MCRYPT_MODE_CBC,'');    

$iv_size = mcrypt_enc_get_iv_size($cipher);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);

mcrypt_generic_init($cipher, $key, $iv);


$encrypted = base64_decode($encrypted);

echo "after b64decode: " . $encrypted . "\n\n\n";

$encrypted = mdecrypt_generic($cipher, $encrypted);

echo "decrypt:" . $encrypted;

~~~

How to&Answers:

Try MCRYPT_RIJNDAEL_128 with a 32-byte key for AES-256.

AES is a 128-bit block cipher that supports 128-, 192-, and 256-bit keys. Rijndael-256 is a 256-bit block cipher and AES. AES is a 128-bit block specification for Rijndael.

Answer:

Pidder uses key derivation function to get the key from password (it should be HMAC-SHA1, i guess), but you seems to use plain password as a key.

Answer:

Javascript Mcrypt plays well with PHP mcrypt. You could use that instead of pidder.

Answer:

Your code is sequential, honestly, I dont tried to fix, but I have a function that work well and can help you.

    /**
 * Encrypt Token
 *
 * @param unknown $text         
 */
private function rijndaelEncrypt($text) {
    $iv_size = mcrypt_get_iv_size ( MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB );
    $iv = mcrypt_create_iv ( $iv_size, MCRYPT_RAND );
    $key = 'your key';
    return base64_encode ( mcrypt_encrypt ( MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_ECB, $iv ) );
}

/**
 * Decrypt
 *
 * @param unknown $text         
 */
private function rijndaelDecrypt($text) {
    $iv_size = mcrypt_get_iv_size ( MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB );
    $iv = mcrypt_create_iv ( $iv_size, MCRYPT_RAND );
    $key = 'your key';
    // I used trim to remove trailing spaces
    return trim ( mcrypt_decrypt ( MCRYPT_RIJNDAEL_256, $key, base64_decode ( $text ), MCRYPT_MODE_ECB, $iv ) );
}

See http://us3.php.net/manual/en/function.mcrypt-encrypt.php

Answer:

first of all: MCRYPT_RIJNDAEL_256 is NOT(!) AES-256-CBC, if you want this encryption you have to use MCRYPT_RIJNDAEL_128 with an 265bit aka 32 character key.

This would be the php part:

function decrypt($data, $key) {
    if(32 !== strlen($key)) $key= hash('SHA256', $key, true);

    $data = base64_decode($data);
    $data = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, str_repeat("
function decrypt($data, $key) { if(32 !== strlen($key)) $key= hash('SHA256', $key, true); $data = base64_decode($data); $data = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, str_repeat("\0", 16)); $padding = ord($data[strlen($data) - 1]); return substr($data, 0, -$padding); } 
", 16)); $padding = ord($data[strlen($data) - 1]); return substr($data, 0, -$padding); }

This php function includes padding which is an important part, because if the suplied data lenght is not a multiple of the key, you will get something odd.

For decoding we use some of my Node.js scripts with an emulated method of php’s str_repeat for the iv:

var crypto = require('crypto'); 

function encrypt(data, key) {
    key = key || new Buffer(Core.config.crypto.cryptokey, 'binary'),
        cipher = crypto.createCipheriv('aes-256-cbc', key.toString('binary'), str_repeat('
var crypto = require('crypto'); function encrypt(data, key) { key = key || new Buffer(Core.config.crypto.cryptokey, 'binary'), cipher = crypto.createCipheriv('aes-256-cbc', key.toString('binary'), str_repeat('\0', 16)); cipher.update(data.toString(), 'utf8', 'base64'); return cipher.final('base64'); } function str_repeat(input, multiplier) { var y = ''; while (true) { if (multiplier & 1) { y += input; } multiplier >>= 1; if (multiplier) { input += input; } else { break; } } return y; } 
', 16)); cipher.update(data.toString(), 'utf8', 'base64'); return cipher.final('base64'); } function str_repeat(input, multiplier) { var y = ''; while (true) { if (multiplier & 1) { y += input; } multiplier >>= 1; if (multiplier) { input += input; } else { break; } } return y; }

NOTE: It is not recommend to use a static IV (Initialization vector)!
NOTE: JavaScript part is for Node.js using it’s crypto library.

I hope this works for you.