Итак, я пытаюсь перевести часть кода 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
«Неработающий вариант дешифрования 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, я просто решил проигнорировать все эти вещи и предположить, что длина сообщения делится на размер блока.
Что 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.
Было бы это полезно, используя библиотеку 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 ¶ms)
{
// 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».