PHP char编码问题,但只有char T,至少这是我的猜测

时间:2011-12-25 13:04:23

标签: php encryption encoding

我在不同的地方发布了这个课程,但现在发现了一个错误。 它已经变得非常受欢迎,所以我想知道是否有人可以帮我解决这个问题。 我现在已经上了好几个小时,我发现99%的时间问题是大写字母T和T. 我尝试了不同的编码,并将t更改为不同的char。但它总是像它的接缝一样。

<?php
/**
 * An open source PHP library collection
 *
 * @category     RoboTamer
 * @author       Dennis T Kaplan
 * @copyright    Copyright (c) 2008 - 2011, Dennis T Kaplan
 * @license      http://www.RoboTamer.com/license.html
 * @link         http://www.RoboTamer.com
 **/

/**
 * RTCrypt
 *
 * RTCrypt allows for encryption and decryption on the fly using
 * a simple but effective method.
 *
 * RTCrypt does not require mcrypt, mhash or any other PHP extension,
 * it uses only PHP.
 *
 * @category     RoboTamer
 * @package      RTCrypt
 * @author       Dennis T Kaplan
 * @copyright    Copyright (c) 2011, Dennis T Kaplan
 * @license      http://www.RoboTamer.com/license.html
 * @link         http://www.RoboTamer.com
 **/
class RTCrypt
{
    const streight = '012345679ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
    private $scramble1 = NULL;
    private $scramble2 = NULL;

    public function __construct()
    {
        $this->setScramble1();
    }

    public function __destruct(){}

    public function getStreight()
    {
        return self::streight;
    }

    public function getScramble1()
    {
        return implode($this->scramble1);
    }

    public function getScramble2()
    {
        return implode($this->scramble2);
    }

    /**
     * Set the characters you like to replace
     *
     * @access  private
     * @param   string $str
     */
    private function setScramble1()
    {
        $this->scramble1 = str_split(self::streight);
    }

    /**
     * This is your private key.
     * You can generate a random private key based on scramble1 via
     * the randomizeString($scramble1) function.
     *
     * @access  public
     * @param   string $str
     * @return  bool TRUE
     */
    public function setScramble2($str=NULL)
    {
        if($str===NULL){
            trigger_error('No key, use genKey($str)', E_USER_ERROR );
            die;
        }
        $this->scramble2 = str_split($str);
        return TRUE;
    }

    /**
     * This will encrypt your data
     *
     * @access  public
     * @param   string $str
     * @return  string encrypt data
     */
    public function encrypt($str)
    {
        if($this->scramble2 === NULL) $this->setScramble2();
        $str = base64_encode($str);
        $len = strlen($str);
        $newstr='';
        for($i=0; $i < $len;$i++){
            $r = substr($str, -1);
            $str = substr($str, 0, -1);
            $an = array_search($r,$this->scramble1);
            if($an > 0){
                $newstr .= $this->scramble2[$an];
            }else{
                $newstr .= $r;
            }
        }
        return $newstr;
    }

    /**
     * This will decrypt a Crypted string back to the original data
     *
     * @access  public
     * @param   string $str
     * @return  string
     */
    public function decrypt($str)
    {
        if($this->scramble2 === NULL) $this->setScramble2();
        $len = strlen($str);
        $newstr='';
        for($i=0; $i < $len;$i++){
            $r = substr($str, -1);
            $str = substr($str, 0, -1);
            $an = array_search($r,$this->scramble2);
            if($an > 0){
                $newstr .= $this->scramble1[$an];
            }else{
                $newstr .= $r;
            }
        }
        $str = base64_decode($newstr);
        return $str;
    }

    /**
     * Generates your private key.
     * You would use it to set scramble2
     * Keep it save!
     *
     * @access  public
     * @return  string
     */
    public function genKey()
    {
        $array = str_split(self::streight);
        shuffle($array);
        return implode($array);
    }
}
?>

测试脚本:

define('BR',"\n");
Locale::setDefault('en-US');

include 'RTCrypt.php';

$Crypter = new RTCrypt();
$key = $Crypter->genKey();
echo BR.'Your Key: '.BR.$Crypter->getStreight().BR.$key.BR.BR;
$Crypter->setScramble2($key);

$str = '/**
 * encode, decode and also serialize when nessesery.
 * Works with anything that php can serialize.
 * string, array, etc.
 *
 * @category     RoboTaMeR
 * @package      Strsafe
 * @author       Dennis T Kaplan
 * @copyright    Copyright (c) 2008 - 2011, Dennis T Kaplan
 * @license      http://RoboTamer.com/license.html
 * @link         http://RoboTamer.com
 * @todo         combine this with RTCrypt to one class
 */';
echo 'String before RTCrypt: '.BR.$str.BR.BR;

//echo BR.base64_encode($str).BR.BR;

$str = $Crypter->encrypt($str);
echo 'RTCrpted: '.$str.BR.BR;
echo 'String after RTCrypt: '.BR.$Crypter->decrypt($str);
echo BR.BR;
?>

RTCrypt之前的字符串:

/**
 * encode, decode and also serialize when nessesery.
 * Works with anything that php can serialize.
 * string, array, etc.
 *
 * @category     RoboTaMeR
 * @package      Strsafe
 * @author       Dennis T Kaplan
 * @copyright    Copyright (c) 2008 - 2011, Dennis T Kaplan
 * @license      http://RoboTamer.com/license.html
 * @link         http://RoboTamer.com
 * @todo         combine this with RTCrypt to one class
 */

RTCrypt之后的字符串:

/**
 * encode, decode and also serialize when nessesery.
 * Works wich anyching chac php can serialize.
 * string, array, etc.
 *
 * @category     RoboTaMeR
 * @package      Strsafe
 * @auchor       Dennis T Kaplan
 * @copyrighc    Copyright (c) 2008 - 2011, Dennis T Kaplan
 * @license      hctp://RoboTamer.com/license.html
 * @link         hctp://RoboTamer.com
 * @codo         combine chis with RTCrypt co one class
 */

2 个答案:

答案 0 :(得分:3)

我唯一能想到的是:

if($an > 0){

索引0上可以有一个键。您应该使用:

检查FALSE
if ($an !== FALSE)

答案 1 :(得分:1)

即使修复了这个错误,你的代码也完全不安全。我一眼就看出了三个缺陷:

  1. 这是替代密码。一种非常弱的古老方法。字符频率计数是一种简单的方法来击败它。你使用Base64会使攻击变得复杂,但并不多。 =&GT;被设计破坏。

  2. Base64输出中的多个字符将始终映射到自身。即+/8(看起来你只是忘记了字符串中的这一个)和==的身份映射是可以接受的,因为它只是字符串结束标记,但其他三个是安全漏洞。

  3. 您正在使用shuffle创建私钥。 shuffle不是为加密目的而设计的,因此可能使用弱随机数生成器 如果映射到仅具有32位种子的c RNG,我不会感到惊讶。这意味着只有40亿个不同的密钥,这对于暴力来说是微不足道的。