php文件怎么php代码加密软件不影响运行?

PHP代码的加密和解密
现在常见的对PHP代码进行加密的方式主要分为两大类:
不需要加载php扩展的;
需要加载php扩展的
第一种方式使用方便,不需要对php服务器进行配置,或加载其他模块,因此可以方便地部署在租用空间的服务器上。对文件进行加密也很简单,只需要把php文件上传到加密网站,就可以生成加密之后的文件,替换原来的php文件之后就可以正常运行了。
第二种方式使用起来相对复杂一些, php服务器上需要加载额外的模块。对于租用空间,没有管理员权限的用户来说,这是一个问题。
无论哪种方式,要分析它的加解密过程,我们都需要简单了解一下php文件的执行过程。
下面的分析都是基于PHP5.4.15的代码,运行在Apache2.4之上。
PHP的执行过程
简单来说,PHP文件大致按照下图的流程进行执行:
php文件作为参数传入Zend\zend.c文件中第1283行的zend_execute_scripts函数,这个函数会首先调用Zend\zend_language_scanner.c文件中第720行的compile_string函数,把文件的内容编译成一个zend_op_array对象,这个对象记录了php文件编译之后生成的中间代码。然后,zend_op_array会被作为参数传入Zend\zend_vm_execute.h文件中第342行的execute函数进行执行。
需要说明的几点:
zend_execute_scripts中实际调用的是zend_compile_string函数,而不是compile_string函数。是在Zend\zend.c文件中第640行的zend_startup函数中进行初始化时,把compile_string的函数指针赋值给了zend_compile_string。
同样的,zend_execute_scripts实际调用的是zend_execute,是在zend_startup中,把execute的函数指针赋值给了zend_execute。
execute函数按照zend_op_array进行执行,各个op实际对应的处理函数(handler)是在Zend\zend_vm_execute.h的第36481行的zend_init_opcodes_handlers函数中初始化变量zend_opcode_handlers时设定的。
不需要加载php扩展的加解密方式的分析
通过分析,我们得出以下显而易见的一些结论:
因为没有加载php扩展,因此加密之后的文件的执行过程仍然完全遵循图1中的流程。因此,加密之后的文件本身应该是一个完全符合php语法要求的,可以被php编译器正确解析,并可以被php vm正确执行的文件。
那么,解密的过程只能是在这个加密之后的文件的执行过程中进行的,也就是说,这个加密之后的php文件是一个可以自解密的php文件,这个文件中包含了所有解密过程中需要用到的信息。因此,拥有了这个加密之后的文件,其实也同时拥有了解密所需的所有信息:解密的方法、和解密过程中所需的数据。
无论解密过程如何,最后一定是解密出原来的明文内容,然后进行执行的,否则就不符合图1的执行流程了。
现在,我们可以思考如何进行解密了:
一种方式,模拟执行这个加密的php文件,因为这个文件是自解密的,因此,最后一定可以得到明文。
这种方式是最容易想到的,但比较难于执行,并且这个文件中可能包含多个执行陷阱,扰乱模拟执行的过程。
另一种方式,直接在PHP环境中真实地执行这个加密的php文件,在php的内部得到解密之后的明文。
在php中,把一段文本作为代码进行执行,我知道的有以下几种方式:
把文本保存到另一个文件,include这个文件进行。
使用eval函数,直接执行这段文本。
参考这个eval的处理函数,Zend\zend_vm_execute.h中2529行的ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER函数,和Zend\zend_execute_API.c中第1156行的zend_eval_string1函数。
使用包含执行功能的其它函数。
比如,preg_replace函数,在pattern中指定e(PREG_REPLACE_EVAL)作为参数,就会先执行参数中的文本,然后执行替换(这个参数在php5.5将不再支持)。参考preg_replace函数的处理函数,ext\pcre\php-pcre.c中第1003行的php_pcre_replace_impl函数,和第897行preg_do_eval函数。
为了看起来更安全,很多进行加密的都不会选择include方式,而会选择后两种。其实三种方式的安全性是一样的,没有任何差别。因为无论哪种方式,都遵循图1中的执行流程。
那么,我们在图1中的Zend\zend_language_scanner.c中的compile_string函数中增加一个输出,把所有需要编译文本输出出来,其中一定有解密之后的明文。
一些问题:
为什么不使用include/require?
因为使用include方式,需要生成一个包含明文的文件,可能加密厂商认为这样不安全,怕别人找到这个文件,所以大部分不使用这种方式。
为什么不拆分明文?
我几乎没有看到先拆分明文,再分别进行加密的。具体原因不太清楚,我猜测的原因是,php不是一个强制格式化的语言,因此php文件内的格式是很复杂的,如果简单的按照文本分割,很容易导致其中的某一部分无法正确运行。
如果按照语句来分割,首先必须对文件进行词法、语法的分析,这个比较复杂和麻烦,并且还可能需要重新组织文件结构(比如一个很大的函数,怎么分割),有点得不偿失,所以加密厂商没有先拆分。
为什么无法混淆明文中的变量名、函数名?
与拆分明文那个问题相似,要对原始明文中的变量名、函数名进行混淆,就必须对文件进行词法、语法的分析,在此基础上还要进行语义分析,建立变量表和函数表,这个复杂度更高。
另外,如果是跨几个文件的变量,或者被其它文件中调用的函数,要混淆变量名、函数名,就必须和其它文件一起分析,一起加密。这样既增加复杂度,也使加密的使用上更加麻烦,不能像现在这样,一个一个文件单独加密了。
为什么加密之后的文本是乱码?
如果使用文本编辑器打开加密之后的文件,会看到一些文本字符,而同时还有大量的无法正常显示的乱码,这是为什么呢?这些乱码主要包括两部分:
故意使用的在纯英文和中文环境下无法正确显示字符,比如,一些常量的名字,变量的名字等。
PHP在解析一个文件时,是完全按照单字节码读取的,不会去分析双字节码,而我们的文本编辑器则会按照双字节码进行分析和显示。比如,如下用16进制表示的字符串:
27 B9 33 36 8C 27
这个对于PHP来说,就是一个用单引号(0x27)括起来的字符串。而B9和8C如果按照双字节码分析,应该和后边的另一个双字节码组成一个字符,而它们的后边那个字节并不是一个双字节码,因此无法正确显示出来。尽管无法显示,但对于PHP来说,就是一个普通的字符串。
加密之后的内容不是可以显示的字符。
为什么看不到解密过程中的用到的函数名?
为了掩盖运行中自我解密的过程,大部分加密厂商都通过某种方式对解密过程中需要用得函数名进行了编码或加密,有一些只是简单的使用base64进行了编码,有些则使用了复杂些的算法。
从解密的角度看,复杂度没有变化。
需要加载PHP扩展的加解密
这种方式的具体实现机制差别很大,因为PHP扩展给了解密很大的自由度,也就给了加密很大的可能性。但简单划分的话,也可以分为两类:
使用Zend\zend_language_scanner.c中的compile_string函数进行编译php文件的;
和不使用这个函数进行编译的
对于仍然使用Zend\zend_language_scanner.c中的compile_string函数进行编译的,基本分析方法与不需要加载php扩展的加解密方式相似,就不多说了。
对于不使用compile_string这个函数的这种方式,我们以Zend Guard为例来分析加解密的机制。
准确来说,Zend
Guard并没有对PHP代码进行加密,它只是对php代码进行了编译、优化和混淆。它的加密过程执行了以下操作:
首先对php明文文件进行编译,生成zend_op_array对象。这一步操作类似于Zend\zend_language_scanner.c中的compile_string函数的功能。
对代码进行优化。
因为进行了编译,生成了变量表和函数表,因此,可以简单的对变量名、函数名进行混淆。
把处理之后的zend_op_array对象序列化到一个文件,这就是加密之后的文件。
需要说明的是,如果多个文件之间有函数调用、公共变量,这些文件必须一起用Zend Guard进行加密。
在执行的时候,需要把Zend
Loader作为php扩展进行加载。这些加密之后的文件的执行流程与图1中的流程基本一致,唯一的差别就是,Zend\zend.c中的zend_execute_scripts调用的不再是Zend\zend_language_scanner.c中的compile_string函数,而是Zend Loader中的一个函数。这个函数从加密之后的文件中反序列化zend_op_array,然后返回这个zend_op_array给zend_execute_scripts,继续下边的执行。
因此,解密Zend
Guard,其实就是按照zend_op_array生成代码的过程。这个过程很复杂吗?不太确定。不同的中间代码设计思路不同,由中间代码生成源代码的难度差别也很大。如果我们把机器码也作为中间代码来看待,由机器码生成源代码难度最大;Java、.NET的中间代码相对来说接近机器码,但比机器码更加接近逻辑结构,因此难度相对较小,但仍有较大难度。
Php的中间码我没有仔细分析,无法评估难度大小。有兴趣的可以参考Zend\zend_compile.h中255行的_zend_op_array结构,以及相关的其它结构体。
PHP代码的编译
要进行PHP代码的解密,掌握PHP代码的编译方法是必须的,我是在Windows7下进行的编译,参考的是中介绍的步骤。
因为我是用XAMPP
1.8.1搭建的环境,这个里边的PHP加载了所有模块,所以自己编译的时候,也必须加载所有模块,否则或者xampp运行不起来,或者就需要自己修改配制文件。我使用的build步骤如下:
windows sdk 6.1
setenv /x86 /xp
cd c:\php-sdk\
bin\phpsdk_setvars.bat
bin\phpsdk_buildtree.bat
C:\php-sdk\php5.4.15\vc9\x86\php-5.4.15-src
--enable-pdo
这样生成的是thread-safety的build。如果要加载Zend Loader,必须使用non-thread-safety的build,所以configure改成如下:
configure --enable-pdo
--disable-zts
遇到的一些问题
在apache2.4上无法加载Zend Loader6.0
这是一个比较绕的问题,Zend
Loader要求PHP必须是non-thread-safety的,而apache2.4 module必须是thread-safety才能编译。因此,如果要加载Zend Loader,PHP就不能以apache module模式运行,而只能是CGI模式。
这个模式的切换是在C:\xampp\apache\conf\extra\httpd-xampp.conf文件中配制的。打开这个文件,注释掉类似于LoadModule php5_module的这一行,以及上下相关几行。把PHP-CGI setup里边的那几行的注释去掉就可以了。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。怎样给PHP源代码加密?PHP二进制加密与解密的解决办法
转载 & & 作者:
本篇文章小编为大家介绍,怎样给PHP源代码加密?PHP二进制加密与解密的解决办法。需要的朋友参考下
分享2种PHP的源码加密方式,此加密方法支持任意PHP版。注意,加密后的PHP代码无需第三方工具解密,像往常一样,直接运行即可。 代码如下:&?php& &function encode_file_contents($filename) {& &&&& $type=strtolower(substr(strrchr($filename,'.'),1));& &&&& if ('php' == $type && is_file($filename) && is_writable($filename)) { // 如果是PHP文件 并且可写 则进行压缩编码& &&&&&&&& $contents = file_get_contents($filename); // 判断文件是否已经被编码处理& &&&&&&&& $contents = php_strip_whitespace($filename);&& &&&&&&&& // 去除PHP头部和尾部标识& &&&&&&&& $headerPos = strpos($contents,'&?php');& &&&&&&&& $footerPos = strrpos($contents,'?&');& &&&&&&&& $contents = substr($contents, $headerPos + 5, $footerPos - $headerPos);& &&&&&&&& $encode = base64_encode(gzdeflate($contents)); // 开始编码& &&&&&&&& $encode = '&?php'."\n eval(gzinflate(base64_decode("."'".$encode."'".")));\n\n?&";&& &&&&&&&& return file_put_contents($filename, $encode);& &&&& }& &&&&& &}&& &//调用函数& &$filename = 'dam.php';& &encode_file_contents($filename);& &echo "OK,加密完成!" &?& 加密方式2: 代码如下:&?php& &function RandAbc($length = "") { // 返回随机字符串& &&&& $str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";& &&&& return str_shuffle($str);& &}&& &$filename = 'index.php'; //要加密的文件& &$T_k1 = RandAbc(); //随机密匙1& &$T_k2 = RandAbc(); //随机密匙2& &$vstr = file_get_contents($filename);& &$v1 = base64_encode($vstr);& &$c = strtr($v1, $T_k1, $T_k2); //根据密匙替换对应字符。& &$c = $T_k1.$T_k2.$c;& &$q1 = "O00O0O";& &$q2 = "O0O000";& &$q3 = "O0OO00";& &$q4 = "OO0O00";& &$q5 = "OO0000";& &$q6 = "O00OO0";& &$s = '$'.$q6.'=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");$'.$q1.'=$'.$q6.'{3}.$'.$q6.'{6}.$'.$q6.'{33}.$'.$q6.'{30};$'.$q3.'=$'.$q6.'{33}.$'.$q6.'{10}.$'.$q6.'{24}.$'.$q6.'{10}.$'.$q6.'{24};$'.$q4.'=$'.$q3.'{0}.$'.$q6.'{18}.$'.$q6.'{3}.$'.$q3.'{0}.$'.$q3.'{1}.$'.$q6.'{24};$'.$q5.'=$'.$q6.'{7}.$'.$q6.'{13};$'.$q1.'.=$'.$q6.'{22}.$'.$q6.'{36}.$'.$q6.'{29}.$'.$q6.'{26}.$'.$q6.'{30}.$'.$q6.'{32}.$'.$q6.'{35}.$'.$q6.'{26}.$'.$q6.'{30};eval($'.$q1.'("'.base64_encode('$'.$q2.'="'.$c.'";eval(\'?&\'.$'.$q1.'($'.$q3.'($'.$q4.'($'.$q2.',$'.$q5.'*2),$'.$q4.'($'.$q2.',$'.$q5.',$'.$q5.'),$'.$q4.'($'.$q2.',0,$'.$q5.'))));').'"));';& &$s = '&?php '."\n".$s."\n".' ?&';& &//echo $s;& &// 生成 加密后的PHP文件& &$fpp1 = fopen('temp_'.$filename, 'w');& &fwrite($fpp1, $s) or die('写文件错误');& &?& 其实,PHP加密源码方式有很多,譬如,免费的微盾PHP加密,还有 www.phpjm.net 搞的在线加密,只是phpjm更复杂点而已。+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++另外,分享一个 PHP类,它能对 文本的内容进行 二进制加密 与 解密,代码如下: 代码如下:&?php& &class text_auth& &{& &&&& var $n_& &&&& function text_auth()& &&&& {& &&&&&&&& $this-&setIter(32);& &&&& }& &&&& function setIter($n_iter)& &&&& {& &&&&&&&& $this-&n_iter = $n_& &&&& }& &&&& function getIter()& &&&& {& &&&&&&&& return $this-&n_& &&&& }& &&&& function encrypt($data, $key)& &&&& {& &&&&&&&& $n = $this-&_resize($data, 4);& &&&&&&&& $data_long[0]&& = $n;& &&&&&&&& $n_data_long&&& = $this-&_str2long(1, $data, $data_long);& &&&&&&&& $n = count($data_long);& &&&&&&&& if (($n & 1) == 1) {& &&&&&&&&&&&& $data_long[$n] = chr(0);& &&&&&&&&&&&& $n_data_long++;& &&&&&&&& }& &&&&&&&& $this-&_resize($key, 16, true);& &&&&&&&& if ( '' == $key )& &&&&&&&&&&&& $key = '0000';& &&&&&&&& $n_key_long = $this-&_str2long(0, $key, $key_long);& &&&&&&&& $enc_data&& = '';& &&&&&&&& $w&&&&&&&&& = array(0, 0);& &&&&&&&& $j&&&&&&&&& = 0;& &&&&&&&& $k&&&&&&&&& = array(0, 0, 0, 0);& &&&&&&&& for ($i = 0; $i & $n_data_ ++$i) {& &&&&&&&&&&&& if ($j + 4 &= $n_key_long) {& &&&&&&&&&&&&&&&& $k[0] = $key_long[$j];& &&&&&&&&&&&&&&&& $k[1] = $key_long[$j + 1];& &&&&&&&&&&&&&&&& $k[2] = $key_long[$j + 2];& &&&&&&&&&&&&&&&& $k[3] = $key_long[$j + 3];& &&&&&&&&&&&& } else {& &&&&&&&&&&&&&&&& $k[0] = $key_long[$j % $n_key_long];& &&&&&&&&&&&&&&&& $k[1] = $key_long[($j + 1) % $n_key_long];& &&&&&&&&&&&&&&&& $k[2] = $key_long[($j + 2) % $n_key_long];& &&&&&&&&&&&&&&&& $k[3] = $key_long[($j + 3) % $n_key_long];& &&&&&&&&&&&& }& &&&&&&&&&&&& $j = ($j + 4) % $n_key_& &&&&&&&&&&&& $this-&_encipherLong($data_long[$i], $data_long[++$i], $w, $k);& &&&&&&&&&&&& $enc_data .= $this-&_long2str($w[0]);& &&&&&&&&&&&& $enc_data .= $this-&_long2str($w[1]);& &&&&&&&& }& &&&&&&&& return $enc_& &&&& }& &&&& function decrypt($enc_data, $key)& &&&& {& &&&&&&&& $n_enc_data_long = $this-&_str2long(0, $enc_data, $enc_data_long);& &&&&&&&& $this-&_resize($key, 16, true);& &&&&&&&& if ( '' == $key )& &&&&&&&&&&&& $key = '0000';& &&&&&&&& $n_key_long = $this-&_str2long(0, $key, $key_long);& &&&&&&&& $data&& = '';& &&&&&&&& $w&&&&& = array(0, 0);& &&&&&&&& $j&&&&& = 0;& &&&&&&&& $len&&& = 0;& &&&&&&&& $k&&&&& = array(0, 0, 0, 0);& &&&&&&&& $pos&&& = 0;& &&&&&&&& for ($i = 0; $i & $n_enc_data_ $i += 2) {& &&&&&&&&&&&& if ($j + 4 &= $n_key_long) {& &&&&&&&&&&&&&&&& $k[0] = $key_long[$j];& &&&&&&&&&&&&&&&& $k[1] = $key_long[$j + 1];& &&&&&&&&&&&&&&&& $k[2] = $key_long[$j + 2];& &&&&&&&&&&&&&&&& $k[3] = $key_long[$j + 3];& &&&&&&&&&&&& } else {& &&&&&&&&&&&&&&&& $k[0] = $key_long[$j % $n_key_long];& &&&&&&&&&&&&&&&& $k[1] = $key_long[($j + 1) % $n_key_long];& &&&&&&&&&&&&&&&& $k[2] = $key_long[($j + 2) % $n_key_long];& &&&&&&&&&&&&&&&& $k[3] = $key_long[($j + 3) % $n_key_long];& &&&&&&&&&&&& }& &&&&&&&&&&&& $j = ($j + 4) % $n_key_& &&&&&&&&&&&& $this-&_decipherLong($enc_data_long[$i], $enc_data_long[$i + 1], $w, $k);& &&&&&&&&&&&& if (0 == $i) {& &&&&&&&&&&&&&&&& $len = $w[0];& &&&&&&&&&&&&&&&& if (4 &= $len) {& &&&&&&&&&&&&&&&&&&&& $data .= $this-&_long2str($w[1]);& &&&&&&&&&&&&&&&& } else {& &&&&&&&&&&&&&&&&&&&& $data .= substr($this-&_long2str($w[1]), 0, $len % 4);& &&&&&&&&&&&&&&&& }& &&&&&&&&&&&& } else {& &&&&&&&&&&&&&&&& $pos = ($i - 1) * 4;& &&&&&&&&&&&&&&&& if ($pos + 4 &= $len) {& &&&&&&&&&&&&&&&&&&&& $data .= $this-&_long2str($w[0]);& &&&&&&&&&&&&&&&&&&&& if ($pos + 8 &= $len) {& &&&&&&&&&&&&&&&&&&&&&&&& $data .= $this-&_long2str($w[1]);& &&&&&&&&&&&&&&&&&&&& } elseif ($pos + 4 & $len) {& &&&&&&&&&&&&&&&&&&&&&&&& $data .= substr($this-&_long2str($w[1]), 0, $len % 4);& &&&&&&&&&&&&&&&&&&&& }& &&&&&&&&&&&&&&&& } else {& &&&&&&&&&&&&&&&&&&&& $data .= substr($this-&_long2str($w[0]), 0, $len % 4);& &&&&&&&&&&&&&&&& }& &&&&&&&&&&&& }& &&&&&&&& }& &&&&&&&& return $& &&&& }& &&&& function _encipherLong($y, $z, &$w, &$k)& &&&& {& &&&&&&&& $sum&&& = (integer) 0;& &&&&&&&& $delta& = 0x9E3779B9;& &&&&&&&& $n&&&&& = (integer) $this-&n_& &&&&&&&& while ($n-- & 0) {& &&&&&&&&&&&& $y&&&&& = $this-&_add($y,& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& $this-&_add($z && 4 ^ $this-&_rshift($z, 5), $z) ^& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& $this-&_add($sum, $k[$sum & 3]));& &&&&&&&&&&&& $sum&&& = $this-&_add($sum, $delta);& &&&&&&&&&&&& $z&&&&& = $this-&_add($z,& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& $this-&_add($y && 4 ^ $this-&_rshift($y, 5), $y) ^& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& $this-&_add($sum, $k[$this-&_rshift($sum, 11) & 3]));& &&&&&&&& }& &&&&&&&& $w[0] = $y;& &&&&&&&& $w[1] = $z;& &&&& }& &&&& function _decipherLong($y, $z, &$w, &$k)& &&&& {& &&&&&&&& $sum&&& = 0xC6EF3720;& &&&&&&&& $delta& = 0x9E3779B9;& &&&&&&&& $n&&&&& = (integer) $this-&n_& &&&&&&&& while ($n-- & 0) {& &&&&&&&&&&&& $z&&&&& = $this-&_add($z,& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -($this-&_add($y && 4 ^ $this-&_rshift($y, 5), $y) ^& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& $this-&_add($sum, $k[$this-&_rshift($sum, 11) & 3])));& &&&&&&&&&&&& $sum&&& = $this-&_add($sum, -$delta);& &&&&&&&&&&&& $y&&&&& = $this-&_add($y,& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -($this-&_add($z && 4 ^ $this-&_rshift($z, 5), $z) ^& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& $this-&_add($sum, $k[$sum & 3])));& &&&&&&&& }& &&&&&&&& $w[0] = $y;& &&&&&&&& $w[1] = $z;& &&&& }& &&&& function _resize(&$data, $size, $nonull = false)& &&&& {& &&&&&&&& $n&&&&& = strlen($data);& &&&&&&&& $nmod&& = $n % $& &&&&&&&& if ( 0 == $nmod )& &&&&&&&&&&&& $nmod = $& &&&&&&&& if ($nmod & 0) {& &&&&&&&&&&&& if ($nonull) {& &&&&&&&&&&&&&&&& for ($i = $n; $i & $n - $nmod + $ ++$i) {& &&&&&&&&&&&&&&&&&&&& $data[$i] = $data[$i % $n];& &&&&&&&&&&&&&&&& }& &&&&&&&&&&&& } else {& &&&&&&&&&&&&&&&& for ($i = $n; $i & $n - $nmod + $ ++$i) {& &&&&&&&&&&&&&&&&&&&& $data[$i] = chr(0);& &&&&&&&&&&&&&&&& }& &&&&&&&&&&&& }& &&&&&&&& }& &&&&&&&& return $n;& &&&& }& &&&& function _hex2bin($str)& &&&& {& &&&&&&&& $len = strlen($str);& &&&&&&&& return pack('H' . $len, $str);& &&&& }& &&&& function _str2long($start, &$data, &$data_long)& &&&& {& &&&&&&&& $n = strlen($data);& &&&&&&&& $tmp&&& = unpack('N*', $data);& &&&&&&&& $j&&&&& = $& &&&&&&&& foreach ($tmp as $value)& &&&&&&&&&&&& $data_long[$j++] = $& &&&&&&&& return $j;& &&&& }& &&&& function _long2str($l)& &&&& {& &&&&&&&& return pack('N', $l);& &&&& }& &&&& function _rshift($integer, $n)& &&&& {& &&&&&&&& if (0xffffffff & $integer || -0xffffffff & $integer) {& &&&&&&&&&&&& $integer = fmod($integer, 0xffffffff + 1);& &&&&&&&& }& &&&&&&&& if (0x7fffffff & $integer) {& &&&&&&&&&&&& $integer -= 0xffffffff + 1.0;& &&&&&&&& } elseif (-0x & $integer) {& &&&&&&&&&&&& $integer += 0xffffffff + 1.0;& &&&&&&&& }& &&&&&&&& if (0 & $integer) {& &&&&&&&&&&&& $integer &= 0x7& &&&&&&&&&&&& $integer &&= $n;& &&&&&&&&&&&& $integer |= 1 && (31 - $n);& &&&&&&&& } else {& &&&&&&&&&&&& $integer &&= $n;& &&&&&&&& }& &&&&&&&& return $& &&&& }& &&&& function _add($i1, $i2)& &&&& {& &&&&&&&& $result = 0.0;& &&&&&&&& foreach (func_get_args() as $value) {& &&&&&&&&&&&& if (0.0 & $value) {& &&&&&&&&&&&&&&&& $value -= 1.0 + 0& &&&&&&&&&&&& }& &&&&&&&&&&&& $result += $& &&&&&&&& }& &&&&&&&& if (0xffffffff & $result || -0xffffffff & $result) {& &&&&&&&&&&&& $result = fmod($result, 0xffffffff + 1);& &&&&&&&& }& &&&&&&&& if (0x7fffffff & $result) {& &&&&&&&&&&&& $result -= 0xffffffff + 1.0;& &&&&&&&& } elseif (-0x & $result) {& &&&&&&&&&&&& $result += 0xffffffff + 1.0;& &&&&&&&& }& &&&&&&&& return $& &&&& }& &}& &?& 使用方法参考如下:// 加密过程view sourceprint?&$text_file = S_ROOT . './456.php';& &$str = @file_get_contents($text_file);& &require_once S_ROOT . "./text_auth.php";& &$text_auth = new text_auth(64);& &$str = $text_auth-&encrypt($str, "qianyunlai.com");& &$filename = S_ROOT . './789.php'; // 加密后的文本为二进制,普通的文本编辑器无法正常查看& &file_put_contents($filename, $str); // 解密过程view sourceprint?01 $text_file = S_ROOT . './789.php';& &$str = @file_get_contents($text_file);& &require_once S_ROOT . "./text_auth.php";& &$text_auth = new text_auth(64);& &$str = $text_auth-&decrypt($str, "qianyunlai.com");& &$filename = S_ROOT . './456.php';& &file_put_contents($filename, $str);
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具三种方法实现php源代码加密_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
三种方法实现php源代码加密
&&如何通过PHP的自定义函数来加密我们的PHP源代码呢?下面分享三个方法给大家,该方法可以对文本的内容进行 二进制加密 与 解密。
阅读已结束,下载本文需要
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,同时保存到云知识,更方便管理
还剩6页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢查看:2115|回复:3
中级工程师
在这个日渐虚拟的互联网世界中,您必须小心保护自已的数据。本文将介绍编码和加密一些重要信息(比如密码、信用卡号、甚至整个消息)的基础知识。并通过使用 PHP 的内置功能,了解加密和解密信息的意义,并且将了解一些涉及密码和其他数据的实际示例。
了解当今现实世界与 20 年前的现实世界的不同。在 20 世纪 80 年代,加密是一种特工人员的行为 —— 是您在 Tom Clancy 的侦探小说中才可以读到的情节。如果某人想保持少量私有信息,那么他必须使用密码、密码短语或其他基本方法对数据进行加密。
而现在,加密遍布各个领域。密码也被加密保存在数据库中。电脑空间中的加密的通道可能是通过 SSL、SSH 和其他技术加密的 —— 更不必说拟虚专用网络。人们平常可以而且一定能够使用 Pretty Good Privacy (PGP) 来保护敏感的文件和电子邮件。
作为一名 PHP 开发人员,您应该知道,强有力的安全做法并不是只将安全保护用于独特的应用程序 —— 还可以将其用于您当前从事的项目。用户要树立从一般加密方法(例如,在登录页上的密码字段中不显示明文)过渡到各种高级加密方法(如 DES、MD5、SHA1 和 Blowfish)的意识。
因时间和篇幅所限,这里无法讨论加密的各个方面,但是您将从这里了解涵盖适用于您的多数情况的基本内容。我们通过使用 PHP 内置功能先了解加密和解密信息的意义,进而了解涉及密码和其他数据的一些实际示例。在本文中,加密是在更大的安全上下文中进行讨论的。最后,将介绍其他 PHP 扩展和插件。
加密技术的初级读本
作为希腊的词根资产,加密技术是一种 “神秘编写” 艺术。凯撒密码 是最古老的一种密码,形式也最为简单。它采用明文消息,将字母移动 n 个位置,从而产生暗文。例如:
明文:Veni Vidi Vici
暗文:Xgpk Xkfk Xkek
通过检查暗文并借助一些启发式的技巧,您可以知道,明文实际上是移动了两个字符。凯撒密码很容易破解。例如:检查上述信息,可知 X 重复了多次,且 k 也是如此。这就变成猜迷,确定多少个四字母的词有那样多的元音。知道了这些带元音的词后,您就知道了移动其余字的方法。它还可以帮助您判断明文是否为拉丁文,让您对其有大致的了解。
现代加密技术的功能非常强大,使用了超越统一移动字母和符号的算法。本文不打算详细介绍这些算法,仅介绍一些 PHP 安装,它包括您需要适度(或特别)保持数据安全的所有内容。
不存在 100% 不受攻击的绝对完整的加密方法。大概每隔一个月,一些黑客及其朋友就会集合 1,000 台计算机,在最初的几天里强力进行计算破坏,从而使最新的加密方法崩溃。不过,您可以密封您的系统和数据,不让黑客干扰和非法闯入。他们将在其他地方寻找可乘之机。
了解这些内容之后,让我们转而了解那些受简单登录形式保护的示例 PHP 应用程序。
没有安全保障或加密的 PHP 形式处理
假定您是一位新的 Web 应用程序开发人员,没有更多的机会使用安全功能。您创建了您的第一个应用程序,它可以在专用用户表中存储用户名和密码,但是,您没有对这些密码进行加密。这些密码以一眼就看明白的形式存在,任何人都可以使用它们访问数据库。您可以构建一个如下所示的登录页面。
清单 1. 简单的登录页面
以下为引用的内容:
<form action=&verify.php& method=&post&>
<p><label for='username'>Username</label>
<input type='text' name='username' id='username'/>
<p><label for='password'>Password</label>
<input type='text' name='password' id='password'/>
<p><input type=&submit& name=&submit& value=&log in&/>
此 HTML 标记存在什么问题?为密码字段选择的输入类型为 text,这意味着用户键入该字段的任何内容都会以明文形式显示在屏幕上。
您可以方便地将该类型更改为 password,并将该字段中的用户输入替换为一串星号。可靠吗?绝对可靠。不过,这一步骤在很多应用程序中会被忽略。事情虽小,但在安全方面会使人们感到不安。您愿意将钱存入休息大厅的窗口被严重毁坏的银行吗?也许您会。但是您可能更期望银行是完好无损的。对于应用程序来说,道理相同。
让我们继续介绍处理表单提交的 verify.php 文件。
清单 2. 简单的 PHP 登录验证
以下为引用的内容:
$user = $_POST['user'];
$pw = $_POST['password'];
$sql = &select user,password from users
where user='$user'
and password='$pw'
$result = mysql_query($sql);
if (mysql_num_rows($result)){
//we have a match!
//no match
读阅到此,您会露出满意的微笑。等待阅读本文加密部分的部分读者可能变得不耐烦了,但是加密仅为安全问题的一部分。您还必须聪明地处理引入的用户数据。developerWorks 教程 “锁定您的 PHP 应用程序”(请参阅参考资料)讨论了 SQL 注射:将不正常的数据发送到数据库可导致有害或无根据的访问。无论您使用多少个加密,公开弱点没有一点好处。
您应遵循下面的传统安全原则:“不信任用户提供的数据” 和 “深层防御”;清除传入数据并通过转义传入的字符串保护数据库(参见清单 3)。深层防御是将多余的安全方法都妥善保管 —— 不仅包括加密,还包括用户所提供数据的智能处理。
清单 3. 保护 PHP 形式解析免受用户数据操作的影响
以下为引用的内容:
$user = strip_tags(substr($_POST['user'],0,32));
$pw = strip_tags(substr($_POST['password'],0,32));
$sql = &select user,password from users
where user='&. mysql_real_escape_string($user).&'
and password='&. mysql_real_escape_string($pw).&'
$result = mysql_query($sql);
if (mysql_num_rows($result)){
//we have a match!
//no match
通过合理使用 strip_tags()、substr() 和 mysql_real_escape_string(),可以删除任何潜在的有害命令,将字符串减少到 32 个字符,并去掉所有特殊字符,数据库可能将这些字符解释为非预期命令字符串的一部分。
在这一过程结束时,数据库中仍有一个明文密码。您不能显示它。最容易的修复方法是使用 PHP 的内置 crypt() 功能。
使用 crypt()
PHP 的内置 crypt() 功能可实现单向加密 或单向散列。它只所以是单向的,是因为在对某内容进行加密后,您永远不能将其反转为明文。乍一看,此想法似乎很荒谬。使用加密主要是保护信息,随后能够使用该信息,后者通常意味着能够对它进行解密。
不要绝望。单向加密方案和 crypt() 特别受欢迎。可以使保护信息的方法更安全。如果您的用户密码列表落入不法之徒之手,他们实际上没有将密码解密为明文的方法。
让我们返回到密码示例。注释 (notational) PHP 应用程序可能包括让系统管理员创建、编辑和删除用户的模块。例如,在将用户记录存储到用户表之前,PHP 脚本可以使用 crypt() 对密码加密。
清单 4. 使用 crypt() 加密密码
以下为引用的内容:
$user = strip_tags(substr($_POST['user'],0,32));
$pw = strip_tags(substr($_POST['password'],0,32));
$cleanpw = crypt($pw);
$sql = &insert into users (username,password)
values('&.mysql_real_escape_string($user).&',
'&.mysql_real_escape_string($cleanpw).&')&;
//.....etc....
crypt() 将一串明文作为它的第一个参数字,对它应用 salt 会影响加密算法的随机性,并生成输入明文的单向暗文。如果不提供 salt,则 PHP 通常默认其系统 salt,它可以是以下值和长度之一:
以下为引用的内容:
CRYPT_STD_DES 2 个字符(默认)
CRYPT_EXT_DES 9 个字符
CRYPT_MD5 12 个字符,以 $1$开头
CRYPT_BLOWFISH 16 个字符,以 $2$开头
许多现代 PHP 安装使用 MD5 或更高的 salt,它们使用强大的 12 个字符的 salt,但是,不要对任何事情想当然。您最好知道系统正在使用哪一个值。您可以使用以下 PHP 代码片段检查服务器的设置:
以下为引用的内容:
<?php echo &System salt size: &. CRYPT_SALT_LENGTH; ?>
返回的答案将是 2、9、12 或 16,它告诉您系统正在使用的值。要使用 MD5 或更高版本的 salt,您可以显式调用明文和 salt 参数中的 crypt() 函数以及 md5() 函数,以获取随机暗文(参见清单 5)。md5() 函数可以散列反馈的任何字符串,并将其转变为固定长度为 32 个字符的字符串。您可能更喜欢其他方法,具体的使用取决于安全需求和个人爱好。
清单 5. 使用 crypt() 和 md5() 加密密码
以下为引用的内容:
$user = strip_tags(substr($_POST['user'],0,32));
$pw = strip_tags(substr($_POST['password'],0,32));
$cleanpw = crypt(md5($pw),md5($user));
$sql = &insert into users (username,password)
values('&.mysql_real_escape_string($user).&',
'&.mysql_real_escape_string($cleanpw).&')&;
//.....etc....
现在数据库中已经拥有一个已加密的密码,但是没有对其进行解密的方法。如何使之有用?一个比较容易的方法是:对用户提供的任何传入密码都使用相同的加密方法,并将结果与您存储的密码比较。
清单 6. 重访 verify.php
以下为引用的内容:
$user = strip_tags(substr($_POST['user'],0,32));
$pw = strip_tags(substr($_POST['password'],0,32));
$cleanpw = crypt(md5($pw),md5($user));
$sql = &select user,password from users
where user='&. mysql_real_escape_string($user).&'
and password='&. mysql_real_escape_string($cleanpw).&'
$result = mysql_query($sql);
if (mysql_num_rows($result)){
//we have a match!
//no match
例如,如果存储的加密密码是 i83Uw28jKzBrZF,则加密存储传入的密码,并将它与存储的密码进行比较。攻击者破坏加密的惟一方法是将一个非常长的字符串列表与您的加密密码进行比较,每次比较一个,直到找到匹配项。这也称为字典攻击,因此您的密码最好不应该是密码 或 Star Trek 字符名,甚至您的呢称。因为在加密 Fido 后,它会变成一堆乱语,但这并不表明它对于此种攻击是安全的。确保您的密码具有某一长度(八个或更多字符),并包含大写字母、数字和特定的字符,如 ! 和 $,这样猜测您的数据会更加困难。在短语中,f1D0! 是一个较好的密码,它胜于 GandalftheGray 之类的长密码,由于后者使用小写字母,并且是 “Lord of the Rings” 的字符名称。
使用 crypt() 的一种不太好的方法
还有使用 crypt() 的另一种方法,这种方法不太好:将明文的前 n 个字符用作 salt。
清单 7. 将明文字符用于 salt
以下为引用的内容:
$user = strip_tags(substr($_POST['user'],0,32));
$pw = strip_tags(substr($_POST['password'],0,32));
$cleanpw =crypt($pw, substr($user,0,2));
$sql = &select user,password from users
where user='&. mysql_real_escape_string($user).&'
and password='&. mysql_real_escape_string($cleanpw).&'
$result = mysql_query($sql);
if (mysql_num_rows($result)){
//we have a match!
//no match
如果您的用户名是 tmyer,则 salt 预置为 tm,它会使某人很容易推断 salt 的内容。这不是一个好方法。
使用 PHP 进行加密和解密
本文的大部分篇幅讨论了使用 crypt() 的单向加密。但是,如果您要将消息发送给某人,并提供对该消息解密的方法,又该如何办呢?请使用 PHP 支持的公钥加密技术。
使用公钥加密的用户拥有一个私钥和一个公钥,并且他们与其他用户共享公钥。如果您要将一封私有短信发送给您的朋友 John Doe,您可以使用 John Doe 的公钥(您已经将其存储在自已的 keyring 中)加密该消息。John Doe 收到该消息后,只有他可以使用他的私钥对其解密。任何给定用户的公钥和私钥在数学上是不能相关的。对于 PGP 和其他公钥加密方法,不存在从公钥推断某人私钥的方法。
PGP 的附加特性是:私钥的密码实际上不是密码,它是一个密码短语。它可以是整句话,包括标点符号、空格和所有字符样式。
使用基于 PGP 的公钥加密的一种方法是使用 GNU Privacy Guard (GPG)。使用 GPG 加密的任何消息都可以使用 GPG、PGP 或支持任一程序的任何数量的电子邮件客户机插件来解密。在示例中,联机表接受用户输入(包括消息);使用 GPG 为特定的接收方加密消息;然后发送消息。
清单 8. 使用 GPG
以下为引用的内容:
//set up users
$from = &&;
//cut the message down to size, remove HTML tags
$messagebody = strip_tags(substr($_POST['msg'],0,5000));
$message_body = escapeshellarg($messagebody);
$gpg_path = '/usr/local/bin/gpg';
$home_dir = '/htdocs/www';
$user_env = 'web';
$cmd = &echo $message_body   HOME=$home_dir USER=$user_env $gpg_path& .
&--quiet --no-secmem-warning --encrypt --sign --armor & .
&--recipient $to --local-user $from&;
$message_body = `$cmd`;
mail($to,'Message from Web Form', $message_body,&From:$from\r\n&);
在此示例中,PHP 调用 /usr/local/bin/gpg(此位置因服务器而异),以便使用发送方的私钥和接收方的公钥加密消息。结果,只有接收方可以解密该消息,并且知道来自发送方的消息。此外,还可以设置 HOME 和 USER 环境变量,以通知 GPG 在何处查找存储这些密钥的 keyring。其他标志的功能如下:
--quiet 和 --no-secmem-warning 抑制来自 GPG 的警告。
--encrypt 执行加密。
--sign 添加签名,以验证发送方的身份。
--armor 产生非二进制的 ASCII 输出,这样,易于通过电子邮件将其发送。
正常情况下,正如前面提到的,机密密钥受密码短语的保护。本特定实例没有使用密码短语,因为在每次表单提交时它都需要手工输入。当然,在下列情况下您还可以选择其他选项:在单独文件中提供短语,或使用它自已的身份验证方案防止表单公用(例如,如果它是一个只能由公司销售代表访问的表单)。
另请注意,除非您正在对允许用户输入电子邮件消息的表使用 SSL,否则键入的任何内容都是明文形式的。换句话说,客户机和服务器之间的任何人都可以看见它。不过,这是另一个主题。
我们对安全性、加密技术,甚至公钥加密技术介绍了很多,目的是帮助您成功开发下一个 PHP 项目。使用加密和其他加密方法的要点不是创建 100% 可靠的无缝系统。关闭的计算机才是不可攻击的系统,但是也不能完全保证,因为某人可能会走上前走,打开它,然后攻击它。加密的要点是使获取敏感数据变得非常困难,以致黑客不再尝试攻击,或尝试攻击失败后离去。
所有安全性考虑必须兼顾方便和保护。使用强大的算法密钥将所有数据都进行单向加密意味着您的数据非常安全,但是使用时很不方便。这带来的相应缺陷也很严重,如同使用非加密的内容一样,为您带来的任何方便也为其他人获取数据带来了可怕的方便。通过加密重要的机密数据(如密码、信用卡号和秘密消息)和添加好的安全措施(如深层防御、过滤用户提供的数据和传统的一般常识)可以达到最佳平衡。
曾经沧海难为水
过来了接下:
学习了,收藏慢慢看
:loveliness: :time: :call:& && && && &:P ;P :@ :( :L :handshake& && && && && && && &&&;P

我要回帖

更多关于 运行php程序 的文章

 

随机推荐