C到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
}

我知道我基本上是在要求你们为我做点什么,但是我真的坚持要这样做(自动…).

真正帮助我的提示/解释是:

>在这种情况下,BF_ecb_encrypt会做什么? (用伪代码甚至是php?)(不停地拍打.“不要索要成品”)
>转换的翻译是否正确?
>什么是{{0}},BF_set_key(& key,16,key_data);?
>什么是reinterpret_cast< unsigned char *>(&(* it))?

我确实看过这些文档页面,但无济于事:

> php mcrypt-decrypt
> BF_ecb_encrypt
> C++ transform

full source is available on github.
此特定代码来自src / parser.cpp

解决方法:

原始代码正在执行的“ CBC解密的残破变体”可以等效地描述为ECB解密,然后将每个明文块与前一个进行(累加)XOR.

对于XOR,您不需要任何花哨的东西:PHP bitwise XOR operator可以在字符串上运行.

因此,您的C代码的简单PHP版本可能如下所示(警告:未经测试的代码):

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,我只是选择忽略所有这些内容,并假设消息长度可被块大小整除.

上一篇:Java-Winzipaes在Android上解密10 MB文件的速度很慢


下一篇:java-Android中的字符串加密