将进行加密的字母移动任意位,达到加密的目的。
由于字母表位置循序及移动位数可以自定义,在没有对应的字母表的情况下,即使猜测到加密方法也无法得到准确信息。每刷新一次加密值都会变化。
可以对中英文、数字进行加密,主要用于、session的信息加密。实际应用中为防止他人拦截、session进行破解,需要更改字母表、数字表的字符顺序及移动位数。
简单加密的PHP实现
http://localhost/easyencode.php
代码:
<?php
< http-equiv="Content-Type" content="text\html; charset=utf-8" />
<?php
header("Content-type: text/html; charset=utf-8");
// 存储配置信息的数组
$code_ini = array( 'numeric_list'=>null , 'character_list'=>null , 'type_list'=>null , 'movebit'=> 6 , 'pot'=>',' );
en5code( $str , $code_ini=null ){ // $movebit = 6 , $numeric_list=null , $character_list=null ,$type=null
!$code_ini && $code_ini = array(
'type_list'=> 'abcdefghijklmnopqrstuvwxyz' , // 默认标记类型的表。作为类型识别标记,一般可以不修改。
'numeric_list'=> 'abcdefghijklmnopqrstuvwxyz' , // 数字表,任意不重复字符,数目最少9个。
'character_list'=> 'abcdefghijklmnopqrstuvwxyz' , // 字串表,可在26个字母基础上添加其它字符。如-+.;:'"?*&^%$等等。
'movebit'=> 6 , // 自定义字串表的移动偏移量。如5,则字母a处理后是f (LOC[a]+5)。
'pot'=>',' , // 小数点或者英文点号的表示方式,默认是逗号。
);
!isset( $type ) && $type = $code_ini['type_list'];
!isset( $numeric_list ) && $numeric_list = $code_ini['numeric_list'];
!isset( $character_list ) && $character_list = $code_ini['character_list'];
!isset( $movebit ) && $movebit= $code_ini['movebit'];
!isset( $pot ) && $pot = $code_ini['pot'];
$s_len = strlen( $str ); // 输入字串长度
$t_len = strlen( $type ); // 类型长度
$n_len = strlen( $numeric_list ); // 数字表长度
$c_len = strlen( $character_list ); // 字符表长度
// ------------------------- 处理输入的内容(加密) -------------------------
$i = 0;
$out = '';
while( $i < $s_len ){
// 输入的每一个字符作为右边值。(第1位在左边是一个标记码,第2位在右边,2者重新构成一个字符。如aa对应数字0)
$right = $str[$i];
// 每次生成类型的随机位置
$randkey = mt_rand( 0, $t_len -1 );
$randkey % 2 == 1 && $randkey += 1; // 产生偶数位的随机数(从0开始数起,偶数位即是奇数)
$randkey = $randkey < $n_len ? $randkey : ($n_len -2) ; // 防止超过最大下标的溢出。
$is_chn = ord( $right );// 以ascii特定值判断中文
// 处理小数点点号。用单字节逗号,表示点号
if( $right == '.' ){
// 合成奇数
$out .= $pot.$type[$randkey];
}
// 匹配数字
elseif( is_numeric( $right ) ){ // 0123456789及小数点. ($n % 10)
// 取右边值
$right = $numeric_list[$right];
// 左边取奇数值
$left = $type[$randkey];
// 2位组合成一个字符
$out .= $left.$right;
}
// 是否中文
elseif( $is_chn >= 160 && $is_chn <= 254 ){ // gbk中文的ascii值范围是160~254(160+0~94)
// 向后取3字节组成一个中文字符,再取其ascii码。
// 普通4位中文区位码。前2数字为区码,后2数字为位码
$right = $str[$i].$str[$i+1].$str[$i+2];
$right = iconv( 'UTF-8', 'gbk', $right );
$right0 = abs( ( ord($right[0]) - 160) );
if( $right0 < 10 ) $right0 = '0'.$right0; // 给少于2位的补0
$right1 = abs( ( ord($right[1]) -160 ) );
if( $right1 < 10 ) $right1 = '0'.$right1;
// 连接区码和位码
$right = $right0.$right1;
// 数字转为字母
$right0 = '';
for( $j =0; $j<=3;++$j ){
$right0 .= $character_list[ (int)( $right[$j] + $movebit ) ];
} //var_dump( $right0 );
// 使用随机的1-9数字标记中文,对中文加入标记
$left = mt_rand( 0, 9 );
$out .= $left.$right0;
$i = $i+2;
}
// 普通字符串。字母、符号等。
else{
// 依据位置移动movebit位,取相应的值
$right = strpos( $character_list , $right )+$movebit;
$right = ($right < $c_len) ? $right : ($right-$c_len); // 5 26
$right = $character_list[$right];
// 合成偶数标记码
$left = ($randkey-1 > 0) ? $randkey-1 : 0 ;
$left = $type[$left];
// 2位重构成一个字符
$out .= $left.$right;
}
// 指针后移,处理下一个
++$i;
}
return $out;
}
de5code( $str , $code_ini=null ){
!$code_ini && $code_ini = array(
'type_list'=> 'abcdefghijklmnopqrstuvwxyz' , // 默认标记类型的表。作为类型识别标记,一般可以不修改。
'numeric_list'=> 'abcdefghijklmnopqrstuvwxyz' , // 数字表,任意不重复字符,数目最少9个。
'character_list'=> 'abcdefghijklmnopqrstuvwxyz' , // 字串表,可在26个字母基础上添加其它字符。如-+.;:'"?*&^%$等等。
'movebit'=> 6 , // 自定义字串表的移动偏移量。如5,则字母a处理后是f (LOC[a]+5)。
'pot'=>',' , // 小数点或者英文点号的表示方式,默认是逗号。
);
!isset( $type ) && $type = $code_ini['type_list'];
!isset( $numeric_list ) && $numeric_list = $code_ini['numeric_list'];
!isset( $character_list ) && $character_list = $code_ini['character_list'];
!isset( $movebit ) && $movebit= $code_ini['movebit'];
!isset( $pot ) && $pot = $code_ini['pot'];
$c_len = strlen( $character_list );// 对于固定的字符表,可以直接赋值长度,如26个字母表。
$s_len = strlen( $str )-1;
echo '<br /><strong>输入字串:</strong> '.$str.' <br />长度'.$s_len.'<br />';
// -------- 说明: 每2个字节组构成一个字符。第1位为类型标记记码,第2位为字符的值 -------------
$i = 0;
$output = '';
while( $i < $s_len ){
// 确定第1位的类型
$left = strpos( $type , $str[$i] );
// 取第2位的值
$right = $str[$i+1];
// 对类型分别处理
// 匹配.号
if( $str[$i] == $pot ){
$output .= '.';
}
// 匹配中文。中文规则:1个中文字符5位字节,第1位是数字的标记码,2-5位是4个字母(由ascii数字转化成)
elseif( is_numeric($str[$i]) ){
$right = $str[$i+1].$str[$i+2].$str[$i+3].$str[$i+4]; // 向后取4位
// 字母转化为区位码
$right_temp = '';
for( $j=0; $j<=3; ++$j ){
$pos = strpos( $character_list , $right[$j] );
$diff = ( $pos - $movebit );
if( $pos>=$movebit ) $pos = $diff;
else $pos = $c_len + $diff;
$right_temp .= $pos;
}
// 区位码转为中文
$right = chr( (int)($right_temp[0].$right_temp[1]) + 160 ).chr( (int)($right_temp[2].$right_temp[3]) + 160 );
$right = iconv( 'gbk' , 'UTF-8' , $right );
// 输出
$output .= $right;
// 跳动指针到下一个标记
$i = $i + 3; // 这里指针+3,后面再+2,一共向后移动5字节。
}
elseif( $left !== 0 && $left % 2 == 0 ){ //奇数位字母表示数字
$right = strpos( $numeric_list , $right ); // 第2位在数字表中的位置
if( $right === false ) return '解码错误,输入了解码表的数字部分中不存在的字符';
$output .= $right;
}
else{
$right = strpos( $character_list , $right ); // 第2位在字母表中的位置
$diff = ( $right - $movebit ); // 差值,有正有负
// 定位未加密前的字符,在字母表中的位置
$right = ( $right >= $movebit ) ? $diff : ( $c_len + $diff );
// 解码后得到的位置,对应在字母表中的值
$output .= $character_list[$right];
}
// 将指针后移2个位置
$i = $i+2;
}
return $output;
}
echo '<hr /><center><font color=red><strong><数字、中英文>简易加密</strong></font></center>';
$str2 = 'ajjw业务19.88y总金fks额foeo';
$t1 = microtime( true );
echo '<br />';
$s2code = en5code( $str2 );
echo '<strong>输入字串:</strong>'.$str2.' <br /><br /><br /><strong>加密后:</strong>'.$s2code;
$t = microtime( true );
echo '<br /><br />消耗机器时间:',$t-$t1;
echo '<br /><br /><div style=" width:620px;font-size:13px;border:1px dotted green; padding:5px 10px;"><br /><strong>简介</strong>:<br />算法时间复杂度:加密解密过程都各使用2次循环,其中1次循环用于处理4字节的中文<br />输入输出编码:UTF-8<br />编码转换过程:加密解密过程各使用一次iconv()函数转gbk。(如果知道utf8的中文ascii码,这一过程就可以去掉,待改进)
<br /> 其中处理中文多耗了10倍以上时间<br />主要使用函数:strlen、strpos、mt_rand、ord</div>';
echo '<hr /><br /><center><font color=red><strong>解密:</strong></font></center>';
$t1 =microtime( true );
echo '<br /><br /><strong>解码值:</strong>'.de5code( $s2code );//vgjplprc6lgih1kmohabaj,kciyife7llmg6ipoghljqry9iinovljubkdu
$t =microtime( true );
echo '<br /><br />消耗机器时间:',$t-$t1;
echo '<hr />';
$t1 =microtime( true );
echo '<br /><br /><strong>md5值:</strong>'.md5( $str2 );
$t =microtime( true );
echo '<br /><br />消耗机器时间:',$t-$t1;
echo '<hr />';
$t1 =microtime( true );
echo '<br /><br /><strong>1次strlen值:</strong>'.strlen( $str2 );
$t =microtime( true );
echo '<br /><br />消耗机器时间:',$t-$t1;
?>
END