通过PHP的内置函数,通过DES算法对数据加密和解密


Posted in PHP onJune 21, 2012

由于项目的需要,要写一个能生成“授权码”的类(授权码主要包含项目使用的到期时间),生成的授权码将会写入到一个文件当中,每当项目运行的时候,会自动读取出文件中的密文,然后使用唯一的“密钥”来调用某个函数,对密文进行解密,从中解读出项目的使用到期时间。
之前,自己有先试着写了下,主要是base64+md5+反转字符串。算法太过简单,很容易被破解,而且也没有能过做到“密钥”在加解密中的重要性,故而舍之。
后来,查找了相关资料,发现,原来PHP中内置了一个功能强大的函数库,即Mcrypt。
其实,mcrypt本身就提供了强大的加密解密方法,并且支持很多流行的公开的加密算法,如DES, TripleDES, Blowfish (默认), 3-WAY, SAFER-SK64, SAFER-SK128, TWOFISH, TEA, RC2 and GOST in CBC, OFB, CFB and ECB。

这里简单的引用下百度百科关于“加密算法”的解释:

数据加密的基本过程就是对原来为明文的文件或数据按某种算法进行处理,使其成为不可读的一段代码,通常称为“密文”,使其只能在输入相应的密钥之后才能显示出本来内容,通过这样的途径来达到保护数据不被非法人窃取、阅读的目的。 该过程的逆过程为解密,即将该编码信息转化为其原来数据的过程。

加密技术通常分为两大类:“对称式”和“非对称式”。

对称式加密就是加密和解密使用同一个密钥,通常称之为“Session Key ”这种加密技术目前被广泛采用,如美国政府所采用的DES加密标准就是一种典型的“对称式”加密法,它的Session Key长度为56Bits。

非对称式加密就是加密和解密所使用的不是同一个密钥,通常有两个密钥,称为“公钥”和“私钥”,它们两个必需配对使用,否则不能打开加密文件。这里的“公钥”是指可以对外公布的,“私钥”则不能,只能由持有人一个人知道。它的优越性就在这里,因为对称式的加密方法如果是在网络上传输加密文件就很难把密钥告诉对方,不管用什么方法都有可能被别窃听到。而非对称式的加密方法有两个密钥,且其中的“公钥”是可以公开的,也就不怕别人知道,收件人解密时只要用自己的私钥即可以,这样就很好地避免了密钥的传输安全性问题。

前面提到过,mcrypt支持多种国际公开的算法,我在这次的项目中使用的是DES算法,DES(Data Encryption Standard),这是一个对称算法,速度较快,适用于加密大量数据的场合。
接下来我简要的说明下加密类中会使用到的几个函数。

--------------------------------------------------------------------------------
resource mcrypt_module_open ( string $algorithm , string $algorithm_directory , string $mode , string $mode_directory )
参数$algorithm:要使用的算法,可以通过函数mcrypt_list_algorithms()来查看所有支持的算法名称
参数$ mode:要使用哪种模式,同样,可以内置函数mcrypt_list_algorithms()来查看所有支持的模式

--------------------------------------------------------------------------------
int mcrypt_enc_get_iv_size ( resource $td )
该函数将返回使用的算法的初始化向量(IV)的大小(看着有点抽象),如果IV在算法中被忽略的话讲返回0。
参数$td就是使用mcrypt_module_open函数的返回值。

--------------------------------------------------------------------------------
string mcrypt_create_iv ( int $size [, int $source = MCRYPT_DEV_RANDOM ] )
该函数会创建一个初始化向量(IV)
参数:
$source可以使MCRYPT_RAND,MCRYPT_DEV_RANDOM,
MCRYPT_DEV_URANDOM
注意:PHP5.3.0以上的版本,只支持MCRYPT_RAND
返回值:
成功,则返回一个字符串型的初始向量,失败,则返回False

--------------------------------------------------------------------------------
int mcrypt_enc_get_key_size ( resource $td )
该函数能够取得当前算法所支持的最大的密钥长度(以字节计算)
int mcrypt_generic_init ( resource $td , string $key , string $iv )
调用mcrypt_generic() or mdecrypt_generic()之前,首先需要调用该函数,该函数能够帮我们初始化缓冲区,用以存放加密数据。
参数$key:密钥长度,记住,当前$key的值,要比函数mcrypt_enc_get_key_size()返回的值小
问题:$key的值,越大越好吗?有同学会的,帮忙解答下。

--------------------------------------------------------------------------------
string mcrypt_generic ( resource $td , string $data )
完成了前面的工作之后,就可以调用该函数用以加密数据了。
参数$data:要加密的数据内容
返回值:返回加密后的密文

--------------------------------------------------------------------------------
bool mcrypt_generic_deinit ( resource $td )
该函数能够帮我们卸载当前使用的加密模块。
返回值
成功时返回 TRUE, 或者在失败时返回 FALSE.

--------------------------------------------------------------------------------
string mdecrypt_generic ( resource $td , string $data )
该函数能够用来解密数据。
注意:解密后的数据可能比实际上的更长,可能会有后续的\0,需去掉

--------------------------------------------------------------------------------
bool mcrypt_module_close ( resource $td )
关闭指定的加密模块资源句柄
返回值
成功时返回 TRUE, 或者在失败时返回 FALSE.

--------------------------------------------------------------------------------
贴上代码:

<?php 
class authCode { 
public $ttl;//到期时间 时间格式:20120101(年月日) 
public $key_1;//密钥1 
public $key_2;//密钥2 
public $td; 
public $ks;//密钥的长度 
public $iv;//初始向量 
public $salt;//盐值(某个特定的字符串) 
public $encode;//加密后的信息 
public $return_array = array(); // 返回带有MAC地址的字串数组 
public $mac_addr;//mac地址 
public $filepath;//保存密文的文件路径 
public function __construct(){ 
//获取物理地址 
$this->mac_addr=$this->getmac(PHP_OS); 
$this->filepath="./licence.txt"; 
$this->ttl="20120619";//到期时间 
$this->salt="~!@#$";//盐值,用以提高密文的安全性 
// echo "<pre>".print_r(mcrypt_list_algorithms ())."</pre>"; 
// echo "<pre>".print_r(mcrypt_list_modes())."</pre>"; 
} 
/** 
* 对明文信息进行加密 
* @param $key 密钥 
*/ 
public function encode($key) { 
$this->td = mcrypt_module_open(MCRYPT_DES,'','ecb',''); //使用MCRYPT_DES算法,ecb模式 
$size=mcrypt_enc_get_iv_size($this->td);//设置初始向量的大小 
$this->iv = mcrypt_create_iv($size, MCRYPT_RAND);//创建初始向量 
$this->ks = mcrypt_enc_get_key_size($this->td);//返回所支持的最大的密钥长度(以字节计算) 
$this->key_1 = substr(md5(md5($key).$this->salt),0,$this->ks); 
mcrypt_generic_init($this->td, $this->key_1, $this->iv); //初始处理 
//要保存到明文 
$con=$this->mac_addr.$this->ttl; 
//加密 
$this->encode = mcrypt_generic($this->td, $con); 
//结束处理 
mcrypt_generic_deinit($this->td); 
//将密文保存到文件中 
$this->savetofile(); 
} 
/** 
* 对密文进行解密 
* @param $key 密钥 
*/ 
public function decode($key) { 
try { 
if (!file_exists($this->filepath)){ 
throw new Exception("授权文件不存在"); 
}else{//如果授权文件存在的话,则读取授权文件中的密文 
$fp=fopen($this->filepath,'r'); 
$secret=fread($fp,filesize($this->filepath)); 
$this->key_2 = substr(md5(md5($key).$this->salt),0,$this->ks); 
//初始解密处理 
mcrypt_generic_init($this->td, $this->key_2, $this->iv); 
//解密 
$decrypted = mdecrypt_generic($this->td, $secret); 
//解密后,可能会有后续的\0,需去掉 
$decrypted=trim($decrypted) . "\n"; 
//结束 
mcrypt_generic_deinit($this->td); 
mcrypt_module_close($this->td); 
return $decrypted; 
} 
}catch (Exception $e){ 
echo $e->getMessage(); 
} 
} 
/** 
* 将密文保存到文件中 
*/ 
public function savetofile(){ 
try { 
$fp=fopen($this->filepath,'w+'); 
if (!$fp){ 
throw new Exception("文件操作失败"); 
} 
fwrite($fp,$this->encode); 
fclose($fp); 
}catch (Exception $e){ 
echo $e->getMessage(); 
} 
} 
/** 
* 取得服务器的MAC地址 
*/ 
public function getmac($os_type){ 
switch ( strtolower($os_type) ){ 
case "linux": 
$this->forLinux(); 
break; 
case "solaris": 
break; 
case "unix": 
break; 
case "aix": 
break; 
default: 
$this->forWindows(); 
break; 
} 
$temp_array = array(); 
foreach( $this->return_array as $value ){ 
if (preg_match("/[0-9a-f][0-9a-f][:-]"."[0-9a-f][0-9a-f][:-]"."[0-9a-f][0-9a-f][:-]"."[0-9a-f][0-9a-f][:-]"."[0-9a-f][0-9a-f][:-]"."[0-9a-f][0-9a-f]/i",$value,$temp_array )){ 
$mac_addr = $temp_array[0]; 
break; 
} 
} 
unset($temp_array); 
return $mac_addr; 
} 
/** 
* windows服务器下执行ipconfig命令 
*/ 
public function forWindows(){ 
@exec("ipconfig /all", $this->return_array); 
if ( $this->return_array ) 
return $this->return_array; 
else{ 
$ipconfig = $_SERVER["WINDIR"]."\system32\ipconfig.exe"; 
if ( is_file($ipconfig) ) 
@exec($ipconfig." /all", $this->return_array); 
else 
@exec($_SERVER["WINDIR"]."\system\ipconfig.exe /all", $this->return_array); 
return $this->return_array; 
} 
} 
/** 
* Linux服务器下执行ifconfig命令 
*/ 
public function forLinux(){ 
@exec("ifconfig -a", $this->return_array); 
return $this->return_array; 
} 
} 
$code=new authCode(); 
//加密 
$code->encode("~!@#$%^"); 
//解密 
echo $code->decode("~!@#$%^"); 
?>

原创文章:WEB开发_小飞
PHP 相关文章推荐
第六节 访问属性和方法 [6]
Oct 09 PHP
在Windows下编译适用于PHP 5.2.12及5.2.13的eAccelerator.dll(附下载)
May 04 PHP
使用PHP curl模拟浏览器抓取网站信息
Oct 28 PHP
php实现图形显示Ip地址的代码及注释
Jan 20 PHP
ThinkPHP单字母函数(快捷方法)使用总结
Jul 23 PHP
php中 $$str 中 &quot;$$&quot; 的详解
Jul 06 PHP
ZF框架实现发送邮件的方法
Dec 03 PHP
yii2.0整合阿里云oss删除单个文件的方法
Sep 19 PHP
Thinkphp5 微信公众号token验证不成功的原因及解决方法
Nov 12 PHP
php成功操作redis cluster集群的实例教程
Jan 13 PHP
PHP基于array_unique实现二维数组去重
Jul 14 PHP
PHP ob缓存以及ob函数原理实例解析
Nov 13 PHP
php数据结构与算法(PHP描述) 快速排序 quick sort
Jun 21 #PHP
SESSION信息保存在哪个文件目录下以及能够用来保存什么类型的数据
Jun 17 #PHP
PHP Warning: PHP Startup: Unable to load dynamic library \ D:/php5/ext/php_mysqli.dll\
Jun 17 #PHP
php后退一页表单内容保存实现方法
Jun 17 #PHP
php中使用接口实现工厂设计模式的代码
Jun 17 #PHP
php中jQuery插件autocomplate的简单使用笔记
Jun 14 #PHP
PHP的加密方式及原理
Jun 14 #PHP
You might like
解析PHP SPL标准库的用法(遍历目录,查找固定条件的文件)
2013/06/18 PHP
php中url函数介绍及使用示例
2014/02/13 PHP
PHP往XML中添加节点的方法
2015/03/12 PHP
详解PHP发送邮件知识点
2018/05/06 PHP
PHP sdk实现在线打包代码示例
2020/12/09 PHP
北京奥运官方网站幻灯切换效果flash版打包下载
2008/01/30 Javascript
JavaScript 在线压缩和格式化收藏
2009/01/16 Javascript
ko knockoutjs动态属性绑定技巧应用
2012/11/14 Javascript
密码强度检测效果实现原理与代码
2013/01/04 Javascript
使用JSLint提高JS代码质量方法分享
2013/12/16 Javascript
使用jQuery异步加载 JavaScript脚本解决方案
2014/04/20 Javascript
jQuery插件cxSelect多级联动下拉菜单实例解析
2016/06/24 Javascript
js实现可旋转的立方体模型
2016/10/16 Javascript
js使用i18n实现页面国际化的方法
2017/05/09 Javascript
ES6中箭头函数的定义与调用方式详解
2017/06/02 Javascript
基于 Vue.js 2.0 酷炫自适应背景视频登录页面实现方式
2018/01/17 Javascript
详解vuex结合localstorage动态监听storage的变化
2018/05/03 Javascript
使用iView Upload 组件实现手动上传图片的示例代码
2018/10/01 Javascript
[01:19:23]2018DOTA2亚洲邀请赛 4.5 淘汰赛 Mineski vs VG 第二场
2018/04/06 DOTA
Python爬虫框架Scrapy实战之批量抓取招聘信息
2015/08/07 Python
python爬虫入门教程--优雅的HTTP库requests(二)
2017/05/25 Python
Python中动态检测编码chardet的使用教程
2017/07/06 Python
Django网络框架之HelloDjango项目创建教程
2019/06/06 Python
python生成特定分布数的实例
2019/12/05 Python
Groupon荷兰官方网站:高达70%的折扣
2019/11/01 全球购物
国际贸易个人求职信范文
2014/01/04 职场文书
寒假实习自荐信
2014/01/26 职场文书
文明村创建实施方案
2014/03/27 职场文书
廉洁校园实施方案
2014/05/25 职场文书
幼儿教师师德师风演讲稿
2014/08/22 职场文书
党员对照检查材料
2014/09/22 职场文书
遗嘱继承权公证书
2015/01/26 职场文书
三好学生主要事迹材料
2015/11/03 职场文书
用Python编写简单的gRPC服务的详细过程
2021/07/04 Python
Nginx+Tomcat负载均衡集群的实现示例
2021/10/24 Servers
django中websocket的具体使用
2022/01/22 Python