3

そのため、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

4

3 に答える 3

2

この場合、BF_ecb_encrypt は何をしますか?

BF_ecb_encrypt() は、blowfish を使用して暗号化するための関数です。PHP に相当するもの (以前に Ilmari Karonen が述べたように) は次のとおりです。$plaintext = mcrypt_decrypt( MCRYPT_BLOWFISH, $key, $ciphertext, "ecb" );

reinterpret_cast(&(*it))とは?

BF_ecb_encrypt() は、最初のパラメーターが unsigned char* であることを想定しています。reinterpret_cast<unsigned char*>(&(*it))型キャストであり、「it」を unsigned char* にキャストします。'it' は (少なくとも提供されたコードでは) 未指定の型の反復子であり、キーワード 'auto' を使用して、'it' を正しい型として自動的に初期化します。reinterpret_cast<unsigned char*>(&(*it))次に、 unsigned char* を自動的に変換するために使用されます。

{{0}}, BF_set_key(&key, 16, key_data); とは?

これは、BF_KEY 'key' を初期化するために使用され、次に key_data の値を使用してキーを設定します。これには PHP に相当するものはありません。mcrypt はキーを内部的に設定します。

変換の変換で正しい軌道に乗っていますか?

一見すると、C++ バージョンではパディングが奇妙な方法で処理されます。これは、クラッキングの試みにレンチを投げ込む意図的なものである可能性があります。PHP への変換は、元の C++ のアルゴリズムを完全に理解していない限り、実際には不可能です。つまり、暗号化アルゴリズムだけでなく、使用されているプロセス全体 (暗号化の前後を含む) を完全に理解していなければなりません。

PHP に変換するのではなく、既存の C/C++ コードを使用して単純な PHP 拡張機能を作成することを検討しましたか? これは非常に簡単で、より複雑なアルゴリズムを C++ から PHP に変換するよりもはるかに簡単です。既存のコードは多かれ少なかれコピーして拡張機能に貼り付けることができbuffer_t &replay_data、PHP リソースとして登録される可能性があります。

于 2014-02-24T01:26:59.690 に答える
0

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 拡張機能ディレクトリにコピーし、「extension=my_decrypt.so」行を php.ini に追加する必要があります。

于 2014-03-01T10:38:29.767 に答える