通过PHP的内置函数,通过DES算法对数据加密和解密
2015-01-24信息快讯网
数据加密的基本过程就是对原来为明文的文件或数据按某种算法进行处理,使其成为不可读的一段代码,通常称为密文,使其只能在输入相应的密钥之后才能显示出本来内容,通过这样的途径来达到保护数据不被非法人窃取、阅读的目的
由于项目的需要,要写一个能生成“授权码”的类(授权码主要包含项目使用的到期时间),生成的授权码将会写入到一个文件当中,每当项目运行的时候,会自动读取出文件中的密文,然后使用唯一的“密钥”来调用某个函数,对密文进行解密,从中解读出项目的使用到期时间。之前,自己有先试着写了下,主要是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 screw加密php源代码
php_screw 1.5:php加密: 安装与使用详解
php连接Access数据库错误及解决方法
PHP连接Access数据库的方法小结
解析smarty 截取字符串函数 truncate的用法介绍
探讨Smarty中如何获取数组的长度以及smarty调用php函数的详解
解析PHP中数组元素升序、降序以及重新排序的函数
解析php中的fopen()函数用打开文件模式说明
php Xdebug的安装与使用详解
解析phpstorm + xdebug 远程断点调试
php常用Output和ptions/Info函数集介绍
Android ProgressBar进度条和ProgressDialog进度框的展示DEMO
具有时效性的php加密解密函数代码
一个简单的php加密解密函数(动态加密)
深入PHP数据加密详解
解析CodeIgniter自定义配置文件
解析php中static,const与define的使用区别
解析htaccess伪静态的规则
Session服务器配置指南与使用经验的深入解析
php数据结构与算法(PHP描述) 查找与二分法查找
php数据结构与算法(PHP描述) 快速排序 quick sort
SESSION信息保存在哪个文件目录下以及能够用来保存什么类型的数据
PHP的加密方式及原理
header中Content-Disposition的作用与使用方法
MySQL 日期时间函数常用总结
PHP简洁函数(PHP简单明了函数语法)
PHP 年龄计算函数(精确到天)
PHP序列号生成函数和字符串替换函数代码
PHP 将逗号、空格、回车分隔的字符串转换为数组的函数
php中json_decode()和json_encode()的使用方法
PHP通过session id 实现session共享和登录验证的代码
php注销代码(session注销)
php提示undefined index的几种解决方法
php提示Call-time pass-by-reference has been deprecated in的解决方法[已测]
php实现rc4加密算法代码
php 的加密函数 md5,crypt,base64_encode 等使用介绍
PHP中SESSION使用中的一点经验总结
php addslashes及其他清除空格的方法是不安全的
php中可能用来加密字符串的函数[base64_encode、urlencode、sha1]
支持中文的php加密解密类代码