<?php
/**
* 公钥加密
*
* @param string 明文
* @param string 证书文件(.crt)
* @return string 密文(base64编码)
*/
function publickey_encodeing($sourcestr, $fileName)
{
$key_content = file_get_contents($fileName);
$pubkeyid = openssl_get_publickey($key_content);
if (openssl_public_encrypt($sourcestr, $crypttext, $pubkeyid))
{
return base64_encode(“”.$crypttext);
}
}
/**
* 私钥解密
*
* @param string 密文(二进制格式且base64编码)
* @param string 密钥文件(.pem / .key)
* @param string 密文是否来源于JS的RSA加密
* @return string 明文
*/
function privatekey_decodeing($crypttext, $fileName, $fromjs = FALSE)
{
$key_content = file_get_contents($fileName);
$prikeyid = openssl_get_privatekey($key_content);
$crypttext = base64_decode($crypttext);
$padding = $fromjs ? OPENSSL_NO_PADDING : OPENSSL_PKCS1_PADDING;
if (openssl_private_decrypt($crypttext, $sourcestr, $prikeyid, $padding))
{
return $fromjs ? rtrim(strrev($sourcestr), “/0”) : “”.$sourcestr;
}
return ;
}
//JS->PHP 测试
$txt_en = $_POST[‘password’];
$txt_en = base64_encode(pack(“H*”, $txt_en));
$file = ‘ssl/server.pem’;
$txt_de = privatekey_decodeing($txt_en, $file, TRUE);
var_dump($txt_de);
//PHP->PHP 测试
$data = “汉字:1a2b3c”;
$config = Core::getInstance()->config;
$file1 = ‘ssl/server.crt’;
$file2 = ‘ssl/server.pem’;
$a = publickey_encodeing($data, $file1);
$b = privatekey_decodeing($a, $file2);
var_dump($b);
?>
php是脚本语言,发布后源码容易暴露,尤其是在使用虚拟主机的时候,如果用Zend Encoder加密后,相当于在源码上加了一层保护,而且据说还加快了程序的运行速度,我们为什么不使用它呢,呵呵.
安装软件时,在选择安将目录后会有一个对话框让你选择许可证的地址,这里我们选择下面的在本地磁盘查找,然后在接下的的对话框中输入我们下载到的许可证文件“zend_encoder.dat”的路径(压缩包的“crack”文件夹里)。
软件的使用方法非常的简单,首先选择“File->NewProject”新建一个项目,然后在该项目下添加你要加密的文件或文件夹。在右边的“Target Directory”选项里输入保存加密PHP文件的路径。然后点“Encode”按钮就可以对当前项目中的PHP文件进行加密了。你还可以将当前项目保存起来,以便你的PHP文件更新后重新加密。PHP文件加密后,文件大小也变得小多了,以前一个30K的文件加密后只有14K。
技巧:在“Tools->Settings”对话框的“Extensions to Encoder”文本框中你可以对要加密的文件扩展名进行指定(多个扩展名用空格分隔),使Zend Encoder只对这些文件进行加密。
PHP Zend 解密
第一种方式使用方便,不需要对php服务器进行配置,或加载其他模块,因此可以方便地部署在租用空间的服务器上。对文件进行加密也很简单,只需要把php文件上传到加密网站,就可以生成加密之后的文件,替换原来的php文件之后就可以正常运行了。
第二种方式使用起来相对复杂一些, php服务器上需要加载额外的模块。对于租用空间,没有管理员权限的用户来说,这是一个问题。
通过分析,我们得出以下显而易见的一些结论:
l 因为没有加载php扩展,因此加密之后的文件的执行过程仍然完全遵循图1中的流程。因此,加密之后的文件本身应该是一个完全符合php语法要求的,可以被php编译器正确解析,并可以被php vm正确执行的文件。
l 那么,解密的过程只能是在这个加密之后的文件的执行过程中进行的,也就是说,这个加密之后的php文件是一个可以自解密的php文件,这个文件中包含了所有解密过程中需要用到的信息。因此,拥有了这个加密之后的文件,其实也同时拥有了解密所需的所有信息:解密的方法、和解密过程中所需的数据。
l 无论解密过程如何,最后一定是解密出原来的明文内容,然后进行执行的,否则就不符合图1的执行流程了。
现在,我们可以思考如何进行解密了:
l 一种方式,模拟执行这个加密的php文件,因为这个文件是自解密的,因此,最后一定可以得到明文。
这种方式是最容易想到的,但比较难于执行,并且这个文件中可能包含多个执行陷阱,扰乱模拟执行的过程。
l 另一种方式,直接在PHP环境中真实地执行这个加密的php文件,在php的内部得到解密之后的明文。
在php中,把一段文本作为代码进行执行,我知道的有以下几种方式:
u 把文本保存到另一个文件,include这个文件进行。
u 使用eval函数,直接执行这段文本。
参考这个eval的处理函数,Zend\zend_vm_execute.h中2529行的ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER函数,和Zend\zend_execute_API.c中第1156行的zend_eval_string1函数。
u 使用包含执行功能的其它函数。
比如,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函数中增加一个输出,把所有需要编译文本输出出来,其中一定有解密之后的明文。
一些问题:
l 为什么不使用include/require?
因为使用include方式,需要生成一个包含明文的文件,可能加密厂商认为这样不安全,怕别人找到这个文件,所以大部分不使用这种方式。