Search code examples
phpcryptographyaes

slowAES decrypt to another key


There was a problem with the old slowAES library. When trying to decrypt, in js it produces one, and in php it produces another. There are a lot of errors in the console that I can’t figure out. Tell me what's wrong? How to get the same keys?

<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

$a = "cd36b76f96b103402924bd5f76d3c204";
$b = "680eb6a492f48ea1b342aea7b79e18eb";
$c = "f746749b113236227058bd471f5c91dc";

function toHex($args){
    if(func_num_args() != 1 || !is_array($args)){
        $args = func_get_args();
    }
    $ret = '';
    for($i = 0; $i < count($args) ;$i++)
        $ret .= sprintf('%02x', $args[$i]);
    return $ret;
}

function toNumbers($s){
    $ret = array();
    for($i=0; $i<strlen($s); $i+=2){
        $ret[] = hexdec(substr($s, $i, 2));
    }
    return $ret;
}

function getRandom($min,$max){
    if($min === null)
        $min = 0;
    if($max === null)
        $max = 1;
    return mt_rand($min, $max);
}

function generateSharedKey($len){
    if($len === null)
        $len = 16;
    $key = array();
    for($i = 0; $i < $len; $i++)
        $key[] = getRandom(0,255);
    return $key;
}

function generatePrivateKey($s,$size){
    if(function_exists('mhash') && defined('MHASH_SHA256')){
        return convertStringToByteArray(substr(mhash(MHASH_SHA256, $s), 0, $size));
    }else{
        throw new Exception('cryptoHelpers::generatePrivateKey currently requires mhash');
    }
}

function convertStringToByteArray($s){
    $byteArray = array();
    for($i = 0; $i < strlen($s); $i++){
        $byteArray[] = ord($s[$i]);
    }
    return $byteArray;
}

function convertByteArrayToString($byteArray){
    $s = '';
    for($i = 0; $i < count($byteArray); $i++){
        $s .= chr($byteArray[$i]);
    }
    return $s;
}

include 'cryptovh/aes.php';

$aes = new AES();
$token = $aes->decrypt(toNumbers($c), 16, 2, toNumbers($a), 16, toNumbers($b));
echo toHex($token); // WHAT I HAVE
echo "<br>";
echo "016e9be78dd5130beb5febcd328ff588"; // WHAT I NEED
?>

cryptovh/aes.php that is copy of: https://github.com/aleaxit/slowaes/blob/master/php/aes_fast.php

use this library: https://github.com/aleaxit/slowaes

At the output, I get this token: dd2f6d60b939b390dc19688babc3873d

And console errors:

Notice: Undefined offset: 16 in /var/www/myuser/data/www/example.com/cryptovh/aes.php on line 386

Notice: Undefined index: in /var/www/myuser/data/www/example.com/cryptovh/aes.php on line 386

Notice: Undefined offset: 20 in /var/www/myuser/data/www/example.com/cryptovh/aes.php on line 386

Notice: Undefined index: in /var/www/myuser/data/www/example.com/cryptovh/aes.php on line 386

Notice: Undefined offset: 24 in /var/www/myuser/data/www/example.com/cryptovh/aes.php on line 386

Notice: Undefined index: in /var/www/myuser/data/www/example.com/panel/cryptovh/aes.php on line 386


Solution

  • In slowaes/php/aes_fast.php, the inversion of the MixColumns operation in the mixColumns method is implemented incorrectly, the else-block must be:

    ...
    } else {
        for ($c = 0; $c < 4; $c++) {
            $t[   $c] = self::$GEX[$state[$c]] ^ self::$GBX[$state[4+$c]] ^ self::$GDX[$state[8+$c]] ^ self::$G9X[$state[12+$c]];
            $t[ 4+$c] = self::$G9X[$state[$c]] ^ self::$GEX[$state[4+$c]] ^ self::$GBX[$state[8+$c]] ^ self::$GDX[$state[12+$c]];
            $t[ 8+$c] = self::$GDX[$state[$c]] ^ self::$G9X[$state[4+$c]] ^ self::$GEX[$state[8+$c]] ^ self::$GBX[$state[12+$c]];
            $t[12+$c] = self::$GBX[$state[$c]] ^ self::$GDX[$state[4+$c]] ^ self::$G9X[$state[8+$c]] ^ self::$GEX[$state[12+$c]];
        }
    }
    ...
    

    The inverse of the MixColumns operation is required for decryption.

    There is also a typo in the method invMain, line 3, where i must be replaced by $i.

    With these changes, the expected result is obtained, which can be verified e.g. here. The warnings are also no longer displayed.

    I've filed an issue here. Note the ReadMe: The code is intended more for didactic purposes. In practice, openssl_encrypt / openssl_decrypt or similar should be used.