Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MCrypt rijndael-128 to OpenSSL aes-128-ecb conversion

Since Mcrypt is deprecated, I want to use OpenSSL instead in my code since we already using php 7.0.17 in our server and there's no tell when they upgrade it.

Some third party API (hosted on PHP 5.x probably and using mcrypt), is taking encrypted data. They've provided methods which they are using to encrypt/decrypt strings.

Here are they

$secret = 'a0a7e7997b6d5fcd55f4b5c32611b87c' ;

public function encrypt128($str)
    {
        $block = mcrypt_get_block_size("rijndael_128", "ecb");
        $pad   = $block - (strlen($str) % $block);
        $str .= str_repeat(chr($pad), $pad);

        return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $secret, $str, MCRYPT_MODE_ECB));
    }

public function decrypt128($str)
    {
        $str = base64_decode($str);
        $str = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $secret, $str, MCRYPT_MODE_ECB);

        $len = strlen($str);
        $pad = ord($str[$len - 1]);

        return substr($str, 0, strlen($str) - $pad);
    }

using these methods string small1 if encrypted becomes v7IXp5vVaFVXXlt/MN8BVw==


We want to use openssl_encrypt in our side such that if we encrypt same string with OpenSSL it must give same results as Mcrypt. I've researched that mcrypt using rijndael-128 Mode ecb should be compatible with OpenSSL aes-128-ecb.

For last few hours, I've been trying to make my own method to encrypt strings serving same result by using OpenSSL. So far I've come to this

public function sslEncrypt128($str)
{
    $secret = 'a0a7e7997b6d5fcd55f4b5c32611b87c';
    return base64_encode(openssl_encrypt($str, 'aes-128-ecb', $secret, OPENSSL_RAW_DATA));
}

But it produces different string SxJ3+EdaeItZx3/EwGTUbw== for same as above input. I don't know if it is flag's problem or padding's, any pointers will be welcome.

I've added the code here to test online https://3v4l.org/v2J2N

Thanks in advance.

like image 522
Jamshad Ahmad Avatar asked Jul 20 '17 15:07

Jamshad Ahmad


2 Answers

Here is what worked for me:

<?php

$str = 'Content';
if (strlen($str) % 16) {
    $str = str_pad($str, strlen($str) + 16 - strlen($str) % 16, "\0");
}

$key = 'KEY';
if (strlen($key) % 16) {
    $key = str_pad($key, strlen($key) + 16 - strlen($key) % 16, "\0");
}

$res1 = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $str, MCRYPT_MODE_ECB);
echo strToHex($res1) . ' | mcrypt_encrypt';

echo "<hr>";
echo strToHex(openssl_decrypt($res1, "aes-128-ecb", $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING)) . ' | openssl_decrypt';

echo "<hr>";

$res2 = openssl_encrypt($str, "aes-128-ecb", $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING);
echo strToHex($res2) . ' | openssl_encrypt';

echo "<hr>";
echo strToHex(openssl_decrypt($res2, "aes-128-ecb", $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING)) . ' | openssl_decrypt';


function strToHex($string) {
    $hex = '';
    for ($i = 0; $i < strlen($string); $i++) {
        $ord     = ord($string[$i]);
        $hexCode = dechex($ord);
        $hex     .= substr('0' . $hexCode, -2);
    }

    return strToUpper($hex);
}
like image 179
Roland Soós Avatar answered Oct 23 '22 03:10

Roland Soós


In your specific example I've found that by changing aes-128-ecb to aes-256-ecb, it produces the same output as the legacy mcrypt_encrypt.

like image 8
Michael Butler Avatar answered Oct 23 '22 03:10

Michael Butler