代码之家  ›  专栏  ›  技术社区  ›  Noctis Skytower

在这个PHP代码中可以改进什么?

  •  2
  • Noctis Skytower  · 技术社区  · 15 年前

    这是一个自定义加密库。我不太了解PHP的标准函数库,我想知道下面的代码是否可以以任何方式得到改进。实现应该产生相同的结果,API应该保持原样,但是要使之更具PHP特性的方法将受到极大的赞赏。

    代码


    <?php
    /***************************************
    Create random major and minor SPICE key.
    ***************************************/
    function crypt_major()
    {
        $all = range("\x00", "\xFF");
        shuffle($all);
        $major_key = implode("", $all);
        return $major_key;
    }
    function crypt_minor()
    {
        $sample = array();
        do
        {
            array_push($sample, 0, 1, 2, 3);
        } while (count($sample) != 256);
        shuffle($sample);
        $list = array();
        for ($index = 0; $index < 64; $index++)
        {
            $b12 = $sample[$index * 4] << 6;
            $b34 = $sample[$index * 4 + 1] << 4;
            $b56 = $sample[$index * 4 + 2] << 2;
            $b78 = $sample[$index * 4 + 3];
            array_push($list, $b12 + $b34 + $b56 + $b78);
        }
        $minor_key = implode("", array_map("chr", $list));
        return $minor_key;
    }
    /***************************************
    Create the SPICE key via the given name.
    ***************************************/
    function named_major($name)
    {
        srand(crc32($name));
        return crypt_major();
    }
    function named_minor($name)
    {
        srand(crc32($name));
        return crypt_minor();
    }
    /***************************************
    Check validity for major and minor keys.
    ***************************************/
    function _check_major($key)
    {
        if (is_string($key) && strlen($key) == 256)
        {
            foreach (range("\x00", "\xFF") as $char)
            {
                if (substr_count($key, $char) == 0)
                {
                    return FALSE;
                }
            }
            return TRUE;
        }
        return FALSE;
    }
    function _check_minor($key)
    {
        if (is_string($key) && strlen($key) == 64)
        {
            $indexs = array();
            foreach (array_map("ord", str_split($key)) as $byte)
            {
                foreach (range(6, 0, 2) as $shift)
                {
                    array_push($indexs, ($byte >> $shift) & 3);
                }
            }
            $dict = array_count_values($indexs);
            foreach (range(0, 3) as $index)
            {
                if ($dict[$index] != 64)
                {
                    return FALSE;
                }
            }
            return TRUE;
        }
        return FALSE;
    }
    /***************************************
    Create encode maps for encode functions.
    ***************************************/
    function _encode_map_1($major)
    {
        return array_map("ord", str_split($major));
    }
    function _encode_map_2($minor)
    {
        $map_2 = array(array(), array(), array(), array());
        $list = array();
        foreach (array_map("ord", str_split($minor)) as $byte)
        {
            foreach (range(6, 0, 2) as $shift)
            {
                array_push($list, ($byte >> $shift) & 3);
            }
        }
        for ($byte = 0; $byte < 256; $byte++)
        {
            array_push($map_2[$list[$byte]], chr($byte));
        }
        return $map_2;
    }
    /***************************************
    Create decode maps for decode functions.
    ***************************************/
    function _decode_map_1($minor)
    {
        $map_1 = array();
        foreach (array_map("ord", str_split($minor)) as $byte)
        {
            foreach (range(6, 0, 2) as $shift)
            {
                array_push($map_1, ($byte >> $shift) & 3);
            }
        }
        return $map_1;
    }function _decode_map_2($major)
    {
        $map_2 = array();
        $temp = array_map("ord", str_split($major));
        for ($byte = 0; $byte < 256; $byte++)
        {
            $map_2[$temp[$byte]] = chr($byte);
        }
        return $map_2;
    }
    /***************************************
    Encrypt or decrypt the string with maps.
    ***************************************/
    function _encode($string, $map_1, $map_2)
    {
        $cache = "";
        foreach (str_split($string) as $char)
        {
            $byte = $map_1[ord($char)];
            foreach (range(6, 0, 2) as $shift)
            {
                $cache .= $map_2[($byte >> $shift) & 3][mt_rand(0, 63)];
            }
        }
        return $cache;
    }
    function _decode($string, $map_1, $map_2)
    {
        $cache = "";
        $temp = str_split($string);
        for ($iter = 0; $iter < strlen($string) / 4; $iter++)
        {
            $b12 = $map_1[ord($temp[$iter * 4])] << 6;
            $b34 = $map_1[ord($temp[$iter * 4 + 1])] << 4;
            $b56 = $map_1[ord($temp[$iter * 4 + 2])] << 2;
            $b78 = $map_1[ord($temp[$iter * 4 + 3])];
            $cache .= $map_2[$b12 + $b34 + $b56 + $b78];
        }
        return $cache;
    }
    /***************************************
    This is the public interface for coding.
    ***************************************/
    function encode_string($string, $major, $minor)
    {
        if (is_string($string))
        {
            if (_check_major($major) && _check_minor($minor))
            {
                $map_1 = _encode_map_1($major);
                $map_2 = _encode_map_2($minor);
                return _encode($string, $map_1, $map_2);
            }
        }
        return FALSE;
    }
    function decode_string($string, $major, $minor)
    {
        if (is_string($string) && strlen($string) % 4 == 0)
        {
            if (_check_major($major) && _check_minor($minor))
            {
                $map_1 = _decode_map_1($minor);
                $map_2 = _decode_map_2($major);
                return _decode($string, $map_1, $map_2);
            }
        }
        return FALSE;
    }
    ?>
    

    这是一个显示如何使用代码的示例。十六进制编辑器可能对输入/输出有帮助。

    例子


    <?php
    # get and process all of the form data
    @ $input     = htmlspecialchars($_POST["input"]);
    @ $majorname = htmlspecialchars($_POST["majorname"]);
    @ $minorname = htmlspecialchars($_POST["minorname"]);
    @ $majorkey  = htmlspecialchars($_POST["majorkey"]);
    @ $minorkey  = htmlspecialchars($_POST["minorkey"]);
    @ $output    = htmlspecialchars($_POST["output"]);
    # process the submissions by operation
    # CREATE
    @ $operation = $_POST["operation"];
    if ($operation == "Create")
    {
        if (strlen($_POST["majorname"]) == 0)
        {
            $majorkey = bin2hex(crypt_major());
        }
        if (strlen($_POST["minorname"]) == 0)
        {
            $minorkey = bin2hex(crypt_minor());
        }
        if (strlen($_POST["majorname"]) != 0)
        {
            $majorkey = bin2hex(named_major($_POST["majorname"]));
        }
        if (strlen($_POST["minorname"]) != 0)
        {
            $minorkey = bin2hex(named_minor($_POST["minorname"]));
        }
    }
    # ENCRYPT or DECRYPT
    function is_hex($char)
    {
        if ($char == "0"):
            return TRUE;
        elseif ($char == "1"):
            return TRUE;
        elseif ($char == "2"):
            return TRUE;
        elseif ($char == "3"):
            return TRUE;
        elseif ($char == "4"):
            return TRUE;
        elseif ($char == "5"):
            return TRUE;
        elseif ($char == "6"):
            return TRUE;
        elseif ($char == "7"):
            return TRUE;
        elseif ($char == "8"):
            return TRUE;
        elseif ($char == "9"):
            return TRUE;
        elseif ($char == "a"):
            return TRUE;
        elseif ($char == "b"):
            return TRUE;
        elseif ($char == "c"):
            return TRUE;
        elseif ($char == "d"):
            return TRUE;
        elseif ($char == "e"):
            return TRUE;
        elseif ($char == "f"):
            return TRUE;
        else:
            return FALSE;
        endif;
    }
    function hex2bin($str)
    {
        if (strlen($str) % 2 == 0):
            $string = strtolower($str);
        else:
            $string = strtolower("0" . $str);
        endif;
        $cache = "";
        $temp = str_split($str);
        for ($index = 0; $index < count($temp) / 2; $index++)
        {
            $h1 = $temp[$index * 2];
            if (is_hex($h1))
            {
                $h2 = $temp[$index * 2 + 1];
                if (is_hex($h2))
                {
                    $cache .= chr(hexdec($h1 . $h2));
                }
                else
                {
                    return FALSE;
                }
            }
            else
            {
                return FALSE;
            }
        }
        return $cache;
    }
    if ($operation == "Encrypt" || $operation == "Decrypt")
    {
        # CHECK FOR ANY ERROR
        $errors = array();
        if (strlen($_POST["input"]) == 0)
        {
            $output = "";
        }
        $binmajor = hex2bin($_POST["majorkey"]);
        if (strlen($_POST["majorkey"]) == 0)
        {
            array_push($errors, "There must be a major key.");
        }
        elseif ($binmajor == FALSE)
        {
            array_push($errors, "The major key must be in hex.");
        }
        elseif (_check_major($binmajor) == FALSE)
        {
            array_push($errors, "The major key is corrupt.");
        }
        $binminor = hex2bin($_POST["minorkey"]);
        if (strlen($_POST["minorkey"]) == 0)
        {
            array_push($errors, "There must be a minor key.");
        }
        elseif ($binminor == FALSE)
        {
            array_push($errors, "The minor key must be in hex.");
        }
        elseif (_check_minor($binminor) == FALSE)
        {
            array_push($errors, "The minor key is corrupt.");
        }
        if ($_POST["operation"] == "Decrypt")
        {
            $bininput = hex2bin(str_replace("\r", "", str_replace("\n", "", $_POST["input"])));
            if ($bininput == FALSE)
            {
                if (strlen($_POST["input"]) != 0)
                {
                    array_push($errors, "The input data must be in hex.");
                }
            }
            elseif (strlen($bininput) % 4 != 0)
            {
                array_push($errors, "The input data is corrupt.");
            }
        }
        if (count($errors) != 0)
        {
            # ERRORS ARE FOUND
            $output = "ERROR:";
            foreach ($errors as $error)
            {
                $output .= "\n" . $error;
            }
        }
        elseif (strlen($_POST["input"]) != 0)
        {
            # CONTINUE WORKING
            if ($_POST["operation"] == "Encrypt")
            {
                # ENCRYPT
                $output = substr(chunk_split(bin2hex(encode_string($_POST["input"], $binmajor, $binminor)), 58), 0, -2);
            }
            else
            {
                # DECRYPT
                $output = htmlspecialchars(decode_string($bininput, $binmajor, $binminor));
            }
        }
    }
    # echo the form with the values filled
    echo "<P><TEXTAREA class=maintextarea name=input rows=25 cols=25>" . $input . "</TEXTAREA></P>\n";
    echo "<P>Major Name:</P>\n";
    echo "<P><INPUT id=textbox1 name=majorname value=\"" . $majorname . "\"></P>\n";
    echo "<P>Minor Name:</P>\n";
    echo "<P><INPUT id=textbox1 name=minorname value=\"" . $minorname . "\"></P>\n";
    echo "<DIV style=\"TEXT-ALIGN: center\"><INPUT class=submit type=submit value=Create name=operation>\n";
    echo "</DIV>\n";
    echo "<P>Major Key:</P>\n";
    echo "<P><INPUT id=textbox1 name=majorkey value=\"" . $majorkey . "\"></P>\n";
    echo "<P>Minor Key:</P>\n";
    echo "<P><INPUT id=textbox1 name=minorkey value=\"" . $minorkey . "\"></P>\n";
    echo "<DIV style=\"TEXT-ALIGN: center\"><INPUT class=submit type=submit value=Encrypt name=operation> \n";
    echo "<INPUT class=submit type=submit value=Decrypt name=operation> </DIV>\n";
    echo "<P>Result:</P>\n";
    echo "<P><TEXTAREA class=maintextarea name=output rows=25 readOnly cols=25>" . $output . "</TEXTAREA></P></DIV></FORM>\n";
    ?>
    

    为了提高内存效率或更快地执行,应该编辑什么?

    1 回复  |  直到 15 年前
        1
  •  3
  •   Jeriko    15 年前

    您可以将ishex函数替换为:

    function isHex($char) {
     return strpos("0123456789ABCDEF",strtoupper($char)) > -1;
    }
    

    你的hex2可能更好:

    function hex2bin($h)
      {
      if (!is_string($h)) return null;
      $r='';
      for ($a=0; $a<strlen($h); $a+=2) { $r.=chr(hexdec($h{$a}.$h{($a+1)})); }
      return $r;
      }
    

    你好像有很多 if..elseif...elseif...elseif 在一个 switch 或者分成不同的方法。

    然而,我更多的是从可维护性和可读性的角度来讨论——尽管它越容易阅读和理解,优化就越容易。如果我把所有的代码都写得更干净,这对你有帮助,那么我会这样做…

    推荐文章