RIJNDAEL шифр - мусор в хвосте данных (С# и PHP)

Discussion in 'PHP' started by fbidesign, 23 Jun 2018.

  1. fbidesign

    fbidesign Member

    Joined:
    13 Jul 2008
    Messages:
    72
    Likes Received:
    12
    Reputations:
    0
    Доброе утро!
    Помогите подружить С# и PHP

    Есть десктопное приложение, написанное на C#. Оно формирует JSON массив, шифрует его и POST'ом шлет веб серверу, веб сервер расшифровывает, обрабатывает, составляет ответ, шифрует тем же алгоритмом и возвращает в ответе.

    Функция дешифровки в C# приложении создает исключение и все это летит в трубу с ошибкой
    "Заполнение неверно и не может быть удалено". Пишу серверную часть на PHP, но тут то как раз и обнаруживается что если строку зашифровать, а результат расшифровать - строка будет другой, отличаться только мусором добавляемым в конец строки, который в случае PHP решается костылем с отрезанием всего что после последней скобки }. Предполагаю что точно такое же дерьмо присутствует и при обратном преобразовании, на него C# и ругается. Собственно результат выполнения дешифровки ответа моего сервера на C# без обработки исключений:
    А вот и PHP код, который демонстрирует ошибку несоответствия данных на входе и на выходе после шифрования и дешифровки
    PHP:
    <?php
    $theiv 
    "xiuxuixuixuixuix";
    $lastkey "12341234abcdabcd12341234abcdabcd";

    $data = array();
    $data['Success'] = 1;
    $data['Status'] = "Success";
    $data['SomeArray'] = array();
    $data['Created'] = "2018-06-22T19:50:49.29";

    $datajson json_encode($data);
    $dataencrypted encrypt($datajson);

    echo 
    "LENGTH JSON ".strlen($datajson)."<BR>DATA: ".$datajson."<br>LENGTH ENCRYPTED ".strlen($dataencrypted)." ENCRYPTED RAW ".strlen(base64_decode($dataencrypted))."<br>DATA: ".$dataencrypted."<hr>\r\n";

    $decrypted decrypt($dataencrypted);
    echo 
    "LENGTH DECRYPTED ".strlen($decrypted)."<BR>";

    //ТУТ КОСТЫЛЬ
    $ii strrpos($decrypted'}');
    echo 
    "<b>} POSITION IS ".$ii."</b><br>";
    if (
    $ii!==false$decrypted substr($decrypted0$ii+1);
    //КОНЕЦ КОСТЫЛЯ */

    $json2 json_decode($decryptedtrue);
    echo 
    "LENGTH DECRYPTED ".strlen($decrypted)."<BR>DATA: ".$decrypted."<hr>JSON:<pre>"print_r($json2); echo "</pre>";

    if (
    $decrypted == $datajson) echo "JSON STRINGS ARE EQUAL<br>";
    if (
    $json2 == $data) echo "JSON ARRAYS ARE EQUAL<br>";

    function 
    decrypt($encrypted)
    {
        global 
    $lastkey$theiv;
        return 
    mcrypt_decrypt(MCRYPT_RIJNDAEL_128$lastkeybase64_decode($encrypted), MCRYPT_MODE_CBC$theiv);
    }

    function 
    encrypt($data)
    {
        global 
    $lastkey$theiv;
        return 
    base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128$lastkey$dataMCRYPT_MODE_CBC$theiv));
    }
    ?>
    Как видно, при выполнении длина дешифрованной строки (являющейся json представлением массива) 96 знаков, хотя исходная строка была 82 знака но выглядят они одинаково. Закрывающая } находится на 81й позиции и после обрезания длины совпадают и все работает.
    LENGTH JSON 82
    DATA: {"Success":1,"Status":"Success","SomeArray":[],"Created":"2018-06-22T19:50:49.29"}
    LENGTH ENCRYPTED 128 ENCRYPTED RAW 96
    DATA: lnoGULBO8DDhSIA+lqnV8qwxY9Oh823/A9/6Zz5S+vo+G3ZDeZyK3amfGcVXcrmztL6eCtWx6FgbhM/0NVSJcl2Py42JjbEsDCzfwyo4ussdrpAtc3fFO4O27bupM25g
    LENGTH DECRYPTED 96
    } POSITION IS 81
    LENGTH DECRYPTED 82
    DATA: {"Success":1,"Status":"Success","SomeArray":[],"Created":"2018-06-22T19:50:49.29"}
    JSON STRINGS ARE EQUAL
    JSON ARRAYS ARE EQUAL

    Взял 2 строки длиной 23 и 26 байт соответственно (набор букв и цифр) и зашифровал с одним и тем же ключем кодом на C# и кодом на PHP. Результаты отличаются, первая половина Base64 представления совпадает, вторая нет. При детальном анализе (в бинарном виде, все имеют длину 32 байта) в обоих случаях первые 16 байт зашифрованного буфера данных совпадают, вторые 16 абсолютно разные. При расшифровке получаю одинаковую (на вид) исходную последовательность, но в случае C# в файл пишется именно исходная, а в случае PHP - та же исходная но дополненная до 32 знаков символом с кодом 6. Уже встречал дополнение нулями и символом с кодом 7. Криво работают функции mcrypt_decrypt / mcrypt_encrypt ?

    ====
    Не актуально, это баг Mcrypt. Перешел на openssl_encrypt / openssl_decrypt - на этом проблемы кончились. На то чтобы это понять убил больше 6 часов...
     
    #1 fbidesign, 23 Jun 2018
    Last edited: 23 Jun 2018
    crlf likes this.