перевод с ++ на php, функция дешифрования

Итак, я пытаюсь перевести часть кода C ++ в php.
C ++ взят из внешнего источника, и мои знания как C ++, так и расшифровки, по меньшей мере, отсутствуют.

Исходный код C ++:

void parser_t::decrypt(buffer_t &replay_data, const unsigned char *key_data) {
/*\
|*| Performs an in place decryption of the replay using the given key.
|*| The decryption is a (broken) variant of CBC decryption and is performed as follows:
|*| -# Set the variable previous_block (with size of 16 bytes) to 0
|*| -# Decrypt a block with the given key
|*| -# XOR the block with the previous (decrypted) block
|*| -# Go back to step 2, until there are no more blocks.
\*/
BF_KEY key = {{0}};
BF_set_key(&key, 16, key_data);

const int block_size = 8;

size_t padding_size = (block_size - (replay_data.size() % block_size));
if (padding_size != 0) {
size_t required_size = replay_data.size() + padding_size;
replay_data.resize(required_size, 0);
}

unsigned char previous[block_size] = {0};
for (auto it = replay_data.begin(); it != replay_data.end(); it += block_size) {
unsigned char decrypted[block_size] = { 0 };
BF_ecb_encrypt(reinterpret_cast<unsigned char*>(&(*it)), decrypted, &key, BF_DECRYPT);
std::transform(previous, previous + block_size, decrypted, decrypted, std::bit_xor<unsigned char>());
std::copy_n(decrypted, block_size, previous);
std::copy_n(decrypted, block_size, reinterpret_cast<unsigned char*>(&(*it)));
}

if (padding_size != 0) {
size_t original_size = replay_data.size() - padding_size;
replay_data.resize(original_size, 0);
}
}

Что у меня так далеко:

function decrypt($data){ // $data is a encrypted string
$key = array(0xDE, <.....>, 0xEF); // (16 entries in the array)

//BF_KEY key = {{0}};             // ?
//BF_set_key(&key, 16, key_data); // ?

$block_size = 8;

$padding_size = ($block_size - (strlen($data) % $block_size));
if ($padding_size != 0) {
$required_size = strlen($data) + $padding_size;
//replay_data.resize(required_size, 0);
// Seems unnecessary in php? string lengths are pretty dynamic.
}

$keyString = '';
for($i = 0; $i < count($key); $i++){
$keyString .= chr($key[$i]);
}
$output = '';

for ($i = 0; $i < stlen($data); $i += $block_size) {
$char = array(0, 0, 0, 0, 0, 0, 0, 0);                     // ?
$decrypted_piece = mcrypt_decrypt(MCRYPT_BLOWFISH, $keyString, $data, "cbc"); // ??
// And this is where I completely get lost.
$output = transform($in, $start, $end, $in2);
}
}

function transform($in, $start, $end, $in2){
$out = ''; // Yea, that won't work...
for($x = $start; $x < $end; $x++){
$out[$x] = $in[$x] ^ $in2[$x];
}
return $output
}

Я понимаю, что в основном прошу вас, ребята, сделать что-то для меня, но я действительно застрял в содержании этого for (auto it...,

Подсказки / объяснения, которые действительно помогли бы мне в следующем:

  • Что значит BF_ecb_encrypt делать в этом случае? (В псевдокоде или даже в php?) (шлепает себя по пальцам. «не проси готовой продукции»)
  • Я на правильном пути с переводом transform?
  • Что такое {{0}}, BF_set_key(&key, 16, key_data);?
  • Что такое reinterpret_cast<unsigned char*>(&(*it))?

Я взглянул на эти страницы документации, но безрезультатно:

полный исходный код доступен на github.
Этот конкретный код исходит от src/parser.cpp

3

Решение

«Неработающий вариант дешифрования CBC», который выполняет исходный код, можно эквивалентно описать как ЕЦБ расшифровка с последующим (кумулятивным) XOR с каждым блоком открытого текста с предыдущим.

Для XOR вам не нужно ничего необычного: PHP побитовый оператор XOR может работать на струнах.

Таким образом, простая версия PHP вашего кода C ++ может выглядеть примерно так (предупреждение: непроверенный код):

function decrypt( $ciphertext, $key ) {
$plaintext = mcrypt_decrypt( MCRYPT_BLOWFISH, $key, $ciphertext, "ecb" );

$block_size = 8;  // Blowfish block size = 64 bits = 8 bytes
$blocks = str_split( $plaintext, $block_size );

$previous = str_repeat( "\0", $block_size );
foreach ( $blocks as &$block ) {
$block ^= $previous;
$previous = $block;
}

return implode( $blocks );
}

Обратите внимание, что я не реализовал никаких дополнений для усеченных последних блоков; есть что-то очень Я не знаю, как он может правильно дешифровать сообщения, длина которых не делится на 8 байтов. (Действительно ли это?) Вместо того, чтобы пытаться угадать, что, черт возьми, происходит и как его перевести на PHP, я просто решил проигнорировать все эти вещи и предположить, что длина сообщения делится на размер блока.

2

Другие решения

Что BF_ecb_encrypt делает в этом случае?

BF_ecb_encrypt () — это функция для шифрования с использованием blowfish. Эквивалент PHP (как упоминалось ранее Ильмари Каронен) $plaintext = mcrypt_decrypt( MCRYPT_BLOWFISH, $key, $ciphertext, "ecb" );

Что такое reinterpret_cast (&(*Это))?

BF_ecb_encrypt () ожидает, что его первый параметр будет беззнаковым символом *. reinterpret_cast<unsigned char*>(&(*it)) это приведение типа, приведение ‘it’ к неподписанному символу *. ‘it’ является итератором неопределенного типа (по крайней мере, в предоставленном коде), а ключевое слово ‘auto’ используется для автоматической инициализации ‘it’ как правильного типа. reinterpret_cast<unsigned char*>(&(*it)) затем используется для автоматического преобразования беззнакового символа *.

Что такое {{0}}, BF_set_key (&key, 16, key_data) ;?

Это используется для инициализации BF_KEY «ключ», а затем установить ключ, используя значение key_data. Это не имеет эквивалента PHP, mcrypt установит ключ внутренне.

Я на правильном пути с переводом трансформации?

Судя по всему, версия C ++ обрабатывает отступы странным образом. Это может быть намеренным, чтобы бросить рывок в попытки взлома. Перевод на PHP на самом деле невозможен, если вы не полностью понимаете алгоритм исходного C ++ — не только алгоритм шифрования, но и весь используемый процесс, включая до и после шифрования.

Рассматривали ли вы создание простого расширения PHP с использованием существующего кода C / C ++ вместо преобразования в PHP? Это должно быть очень прямолинейно, намного проще, чем преобразование более сложного алгоритма из C ++ в PHP. Существующий код можно более или менее скопировать в расширение с помощью buffer_t &replay_data скорее всего, будет зарегистрирован как ресурс PHP.

2

Было бы это полезно, используя библиотеку php-cpp (см. http://www.php-cpp.com):

/**
*  Decrypt function made accessible from PHP
*/

/**
*  Dependencies
*/
#include <phpcpp.h>
#include <openssl/blowfish.h>
#include <algorithm>

/**
*  Define buffer_t to be a vector
*/
typedef std::vector<uint8_t> buffer_t;

/**
*  Function that should be ported to PHP
*  @param  data
*  @param  key_data
*/
static void decrypt(std::string &replay_data, const unsigned char *key_data) {
/*\
|*| Performs an in place decryption of the replay using the given key.
|*| The decryption is a (broken) variant of CBC decryption and is performed as follows:
|*| -# Set the variable previous_block (with size of 16 bytes) to 0
|*| -# Decrypt a block with the given key
|*| -# XOR the block with the previous (decrypted) block
|*| -# Go back to step 2, until there are no more blocks.
\*/
BF_KEY key = {{0}};
BF_set_key(&key, 16, key_data);

const int block_size = 8;

size_t padding_size = (block_size - (replay_data.size() % block_size));
if (padding_size != 0) {
size_t required_size = replay_data.size() + padding_size;
replay_data.resize(required_size, 0);
}

unsigned char previous[block_size] = {0};
for (auto it = replay_data.begin(); it != replay_data.end(); it += block_size) {
unsigned char decrypted[block_size] = { 0 };
BF_ecb_encrypt(reinterpret_cast<unsigned char*>(&(*it)), decrypted, &key, BF_DECRYPT);
std::transform(previous, previous + block_size, decrypted, decrypted, std::bit_xor<unsigned char>());
std::copy_n(decrypted, block_size, previous);
std::copy_n(decrypted, block_size, reinterpret_cast<unsigned char*>(&(*it)));
}

if (padding_size != 0) {
size_t original_size = replay_data.size() - padding_size;
replay_data.resize(original_size, 0);
}
}

/**
*  The PHP function that will take care of this
*  @param  parameters
*  @return Value
*/
static Php::Value php_decrypt(Php::Parameters &params)
{
// check number of parameters
if (params.size() != 2) throw Php::Exception("2 parameters expected");

// read in the parameters
std::string replay_data = params[0];
std::string key_data = params[1];

// decrypt it
decrypt(replay_data, (const unsigned char *)key_data.c_str());

// return the result
return replay_data;
}

/**
*  Symbols are exported according to the "C" language
*/
extern "C"{
// export the "get_module" function that will be called by the Zend engine
PHPCPP_EXPORT void *get_module()
{
// create extension
static Php::Extension extension("my_decrypt","1.0");

// add custom function
extension.add("my_decrypt", php_decrypt);

// return the extension module
return extension.module();
}
}

Вы можете скомпилировать код с помощью следующей команды:

g ++ -std = c ++ 11 -fpic -shared my_decrypt.cpp -o my_decrypt.so -lphpcpp

My_descript.so должен быть скопирован в ваш каталог расширений PHP, а в ваш php.ini должна быть добавлена ​​строка «extension = my_decrypt.so».

0
По вопросам рекламы [email protected]