爆炸后字符编码会发生变化

时间:2013-01-17 23:10:29

标签: php utf-8 character-encoding ascii explode

我正在尝试这个脚本,但字符编码不断变化:

    $v1 = "text1";
    $v2 = "text2";
    $v3 = "text3";

    $result = encrypt($v1 . ":" . $v2 . ":" . $v3, SALT);
    $result = decrypt($result , SALT);
    list($v1, $v2, $v3) = explode(":", $result);
    echo mb_detect_encoding($v1); // gives ASCII
    echo mb_detect_encoding($v2); // gives ASCII
    echo mb_detect_encoding($v3); // gives UTF-8 <<<<

但是通过添加另一个var,它会给出:

    $v1 = "text1";
    $v2 = "text2";
    $v3 = "text3";
    $result = encrypt($v1 . ":" . $v2 . ":" . $v3. ":COTROLFLAG", SALT);
    $result = decrypt($result , SALT);
    list($v1, $v2, $v3, $v4) = explode(":", $result);
    echo mb_detect_encoding($v1); // gives ASCII
    echo mb_detect_encoding($v2); // gives ASCII
    echo mb_detect_encoding($v3); // gives ASCII <<<<
    echo mb_detect_encoding($v4); // gives ASCII

任何人都可以帮助我吗?

这些是加密和解密功能:

    function encrypt($str, $key)
    {
        $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
        $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
        $block = mcrypt_get_block_size('des', 'ecb');
        if (($pad = $block - (strlen($str) % $block)) < $block) {
            $str .= str_repeat(chr($pad), $pad);
        }
        $result = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $str, MCRYPT_MODE_ECB, $iv));
        return $result;
    }
    function decrypt($str, $key)
    {
        $str = base64_decode($str);
        $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
        $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
        $str = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $str, MCRYPT_MODE_ECB, $iv);
        $block = mcrypt_get_block_size('des', 'ecb');
        $pad = ord($str[($len = strlen($str)) - 1]);
        if ($pad && $pad < $block && preg_match('/' . chr($pad) . '{' . $pad . '}$/i', $str)) {
            return substr($str, 0, strlen($str) - $pad);
        }
        return $str;
    }

在第一个答案之后,我知道应该在哪里寻找解决方案..

我发现这是为了填充和剥离:

function addpadding($string, $blocksize = 32){
    $len = strlen($string);
    $pad = $blocksize - ($len % $blocksize);
    $string .= str_repeat(chr($pad), $pad);
    return $string;
}
function strippadding($string){
    $slast = ord(substr($string, -1));
    $slastc = chr($slast);
    $pcheck = substr($string, -$slast);
    if(preg_match("/$slastc{".$slast."}/", $string)){
        $string = substr($string, 0, strlen($string)-$slast);
        return $string;
    } else {
        return false;
    }
}

更改的加密和解密功能:

function encrypt($str, $key)
{   
    global $domain;
    $key = base64_decode($key);
    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
    setcookie("IV_CODE", $iv, time()+86400, "/", $domain);//more security

    $enc = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, addpadding($str), MCRYPT_MODE_CBC, $iv));
    return $enc;
}
function decrypt($str, $key)
{
    $str = base64_decode($str);
    $iv = (isset($_COOKIE['IV_CODE'])) ? base64_decode($_COOKIE['IV_CODE']) : 0;
    if ($iv != 0) {
        $key = base64_decode($key);
        $dec = strippadding(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $str, MCRYPT_MODE_CBC, $iv));    
        return $dec;
    }
    return false;
}

谢谢

1 个答案:

答案 0 :(得分:1)

这与爆炸无关,它是你的加密和解密功能。我会冒险猜测并说出这个

if (($pad = $block - (strlen($str) % $block)) < $block) {
    $str .= str_repeat(chr($pad), $pad);
}

this post on php.netAES_256提及的内容有关。 (你应该记住它对MCRYPT_RIJNDAEL_128的说法)

但是,decrypt()函数中的代码存在很多问题。例如,如果填充长度为27,则您的正则表达式模式很容易被破坏。它也绝对不应该不区分大小写。但是,提取子字符串并使用==之类的

进行比较可能更容易,也更快
$substr = substr($str, -$pad);
if ($pad && $pad < $block && $substr == str_repeat(chr($pad), $pad)) {
    return substr($str, 0, -$pad);
}