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

时间:2010-04-14 16:41:50

标签: php encryption

这是一个自定义加密库。我不太了解PHP的标准函数库,并想知道以下代码是否可以以任何方式得到改进。实现应该产生相同的结果,API应保持原样,但是制作方法更多PHP-ish将非常感激。

代码


<?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 个答案:

答案 0 :(得分:3)

你可以用以下代码替换你的isHex函数:

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

你的hex2bin可能会更好:

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...elseifswitch中更加清晰,或者分成不同的方法。

但是,我从可维护性和可读性的角度来看更多 - 尽管阅读和理解越容易,但优化起来越容易。如果我通过所有代码并以更清洁的方式编写它会对你有所帮助,那么我会这样做......