转自:http://www.smatrix.org/bbs/simple/index.php?t5662.html

//////////////////////////////////////////////////////////////////////////////
目录
1.    PHP的散列函数及其应用
2.    PHP中的对称密码算法及其应用
3.    PHP的公钥密码算法及其应用
///////////////////////////////////////////////////////////////////////////////

2 PHP中的对称密码算法及其应用
前一段时间一直想写完PHP中的密码学算法及其应用的三大部分,但无奈琐事繁多,所以一直拖到现在,希望能够以通俗而非学术化的语言说清楚这部分。
2.1 什么是对称密码算法

前面我们将的HASH函数并非真正的密码算法,而只是一个生成消息摘要的函数。因为一个密码系统需要有五个要素部分组成(密文,明文,加密算法,解密算
法,密钥)。区别对称与非对称密码算法的关键在于解密密钥是否会等于加密密钥,如果相等,那么就是对称的,不相等就是非对称的。像DES,AES都属于对
称密码算法,而RSA,ECC都属于非对称的公钥密码算法。一般而言,对称密码算法加解密速度较快,通常是用来进行数据加密,而非对称的公钥加密算法加解
密速度较慢,通常是用来进行数字签名和构造复杂的密码协议。坊间传说的某某公钥加密算法比某某对称加密算法更好更安全实属荒谬,这就好比讨论你的手和脚那
个更有用。
2.2 什么叫做对称密码算法的加密模式
这个是很多开发人员搞得不太清楚的东西,毕竟大部分PHP开发者未必都接触过密码学方
面的专业培训,因此看到PHP的相关函数感觉望而生畏,不知所措。所谓加密模式就是加密任意长度的消息的使用密码算法的方法。通常对称密码算法都会提供至
少四种基本工作模式,其中两组为块模式(ECB和CBC),两组是流模式(CFB和OFB)。打个通俗的比方,密码算法函数就好像个机器,明文就好像原材
料,机器不可能一次处理所有明文,那么块模式的策略就是把明文进行分组,然后按照一定的规则放入机器做处理,然后得到一组密文。ECB模式就是将消息分成
相互独立的块,每一块都用同一算法和密钥加密(比如使用DES),块与块之间没有关联。而CBC也是将消息分成相互独立块,但是加密的时候,做了点手脚,
使得下一块的密文和上一块的密文有关系,分块加密前与上一块的密文进行异或运算,然后在用同一算法和密钥加密,由于第一块明文没有上一块的密文,所以必须
人工指定一个,称之为初始化向量。而CFB和OFB模式把明文看作是二进制流,实际上也是分块的,它们都需要一个初始化向量,不断地生成伪随机二进制流,
然后与明文分组进行异或运算,而密文是否参与运算是CFB和OFB之间的区别所在。工作模式详情具体不好用文字描述,有兴趣的不妨密码学方面的书籍(安全
矩阵论坛上很多,随便下一本都有)。
2.3 PHP中的对称密码算法函数
PHP的各个版本都提供了相应的对称密码算法函数,所以PHP的
开发者们完全没必要自己山寨一个,请相信这些提供的对称密码算法函数绝对比你自己设计的更强大。目前为止,不绝于耳的是各种颜色的客(还有祖传的)据说能
够几分钟或者秒破一个密码算法,其实这是误解,除了在看雪论坛上看到几个直接针对密钥的暴力破解实例外,偶在网络上很少见过数学上能攻破一个密码算法的
人。之所以系统或软件被破解,是因为密码算法使用不当或者攻击者绕过了密码算法机制。PHP的主要对称密码算法函数来自于Mcrypt函数族。当然这个函
数族是PHP的可选部件,需要下载libmcrypt-x.x.tar.gz并在PHP.INI中进行配置。你可以通过phpinfo()来看看自己配置
的环境是否支持这些函数。

mcrypt support: enabled
Version: 2.5.8
Api No: 20021217
Supported ciphers: cast-128 gost rijndael-128 twofish arcfour cast-256 loki97 rijndael-192 saferplus wake blowfish-compat des rijndael-256 serpent xtea blowfish enigma rc2 tripledes
Supported modes: cbc cfb ctr ecb ncfb nofb ofb stream

Supported

ciphers中列出的就是支持的算法,算法很多,很好很强大,其中rijndael开头的就是AES,所以PHP没有AES实属缪传。接下来我们介绍如
何正确的使用PHP的对称密码算法函数。首先我们看到这个函数mcrypt_module_open,原型是:

resource mcrypt_module_open ( string algorithm, string algorithm_directory, string mode, string mode_directory)


个函数的作用实际上是创建一个使用对称加密算法的工作环境(理解这个很重要,如果你学过windows程序设计,这种思想随处可见),告诉PHP要使用何
种算法(第一个参数),算法路径在哪里(第二个参数),采用何种工作模式(第三个参数),工作模式描述的路径在哪里(第四个参数).实际使用中我们一般不
需要设置第二个参数和第四个参数。现在我们看个例子:

<?php
$key = "security matrix"; //密钥
$input = "mathmatica sounds very terrible!"; //明文 //加密
$td = mcrypt_module_open('rijndael-256', '', 'cbc', ''); //创建加密环境
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND); //由于采用了cbc模式,我们需要一个初始化向量iv。
mcrypt_generic_init($td, $key, $iv); //初始化加密算法,当算法模式是ecb时候,会自动忽略iv
$encrypted_out_data = mcrypt_generic($td, $input); //执行加密
mcrypt_generic_deinit($td); //释放加密算法资源
mcrypt_module_close($td); //关闭加密环境,释放资源
echo "明文是:$input";
echo '<br>';
echo "密钥是:$key";
echo '<br>';
echo "密文是:$encrypted_out_data";
echo '<br>';
//解密,由于$iv没有被清掉,所以我们还可以继续用这个。实际使用中一定要保存起来
$td = mcrypt_module_open('rijndael-256', '', 'cbc', ''); //创建加密环境
mcrypt_generic_init($td, $key, $iv);
$decrypted_out_data=mdecrypt_generic($td, $encrypted_out_data);
mcrypt_generic_deinit($td); //释放加密算法资源
mcrypt_module_close($td); //关闭加密环境,释放资源 echo '<br>';
echo "密钥是:$key";
echo '<br>';
echo "明文是:$decrypted_out_data";


段源代码我添加的注释与PHP手册中的说法略有不同,主要是我为了让大家更明白些。这里有几个函数,第一个是mcrypt_create_iv,这个是用
来创建一个随机的初始化向量IV,四种基本模式中,除了ECB,均要有初始化向量IV。mcrypt_generic_init函数用来初始化密码算法对
象,包括具体算法的句柄,密钥和初始化向量。当算法模式是ECB时,该函数会自动忽略初始化向量IV。接下来利用mcrypt_generic执行加密。
加密完成后利用mcrypt_generic_deinit和mcrypt_module_close来释放环境。这个过程和windows程序设计下面
使用设备资源的过程非常相似。值得注意的是,由于IV生成的时候使用了随机数,所以每次是不一样的,也会导致密文不一样。因此除了ECB模式外,其它三种
模式均要把IV记下了,才能进行解密。解密过程和加密过程是一样的,只是函数mcrypt_generic换成了mdecrypt_generic,请注
意,别眼花,注意他们的书写上的区别,前者是加密,后者是解密。这个过程是PHP中标准的使用对称密码算法的过程。
PHP中有些非常陌生的密码算法,比如gost,除非专业搞密码算法的,一般很少人会知道这个算法的具体内容。我们可以使用以下PHP的算法信息函数来了解一个算法:

mcrypt_enc_get_algorithms_name –获取算法具体名称
mcrypt_enc_get_block_size – 获取算法的分组大小
mcrypt_enc_get_iv_size – 获取算法的IV初始化向量大小
mcrypt_enc_get_key_size – 获取算法支持的最大密钥长度
mcrypt_enc_get_modes_name – 获取算法支持的加密模式
mcrypt_enc_get_supported_key_sizes –返回一个数组,里面有算法支持的各种密钥长度

使用方法如下:

<?php
$td = mcrypt_module_open (MCRYPT_BLOWFISH, '', 'ecb', '');
echo mcrypt_enc_get_algorithms_name($td). "\n";
echo mcrypt_enc_get_block_size($td). "\n";
echo mcrypt_enc_get_iv_size($td). "\n";
echo mcrypt_enc_get_key_size($td). "\n";
echo mcrypt_enc_get_modes_name($td). "\n";
//结果:Blowfish 8 8 56 ECB

PHP中除了上述用法之外,还有一种加密解密的用法。依赖于函数mcrypt_encrypt和mcrypt_decrypt,前者用于加密,后者用于解密。其函数原型为:

string mcrypt_encrypt ( string cipher, string key, string data, string mode [, string iv])
string mcrypt_decrypt ( string cipher, string key, string data, string mode [, string iv])

我们很容易发现,两个函数的参数都是完全一样的,实际上也只有一样才能正常的加密和解密。这种用法与前述函数用法的区别在于这两个函数把所有的算法信息当作为自己的参数了,习惯于传统PHP开发的人会觉得这个更加易用。先看个代码:

<?php
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC); //获取该算法在OFB模式下的IV向量大小
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); //创建一个初始化IV向量
$key = "security matrix"; //密钥
$plaintext = "you should arrive here in eight clock"; //明文
$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $plaintext, MCRYPT_MODE_CBC, $iv); //直接执行加密
echo "明文是:$plaintext.<br> 密文是: $ciphertext"; $outtext = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key,$ciphertext, MCRYPT_MODE_CBC, $iv); //执行解密
echo "<br>";
echo "解密后的明文是: $outtext<br>";
//结果:
// 明文是:you should arrive here in eight clock.
//密文是: p 蜉~嵁'mh!Bl廀'Es??{ ?e斤舉* YC¬濤溋C海Rc敻J 偰k躕"蟸v勸
//解密后的明文是: you should arrive here in eight clock

除了上面两种全面的用法,PHP还提供了四种直接指定加密模式的加密函数mcrypt_cfb(), mcrypt_cbc(), mcrypt_ecb()和 mcrypt_ofb(),这四个函数的原型几乎是一样的。以mcrypt_cbc()为例,原型如下:

string mcrypt_cbc ( int cipher, string key, string data, int mode [, string iv])
string mcrypt_cbc ( string cipher, string key, string data, int mode [, string iv])

其中第一个参数指定算法,第二个参数指定密钥,第三个参数指定数据(根据后面的mode决定是明文还是密文),第四个参数mode指定是加密操作还是解密操作,第五个参数是可选的,如果需要IV则一定要IV.还是看个例子,你会发现如此简单:

<?php
$key = "security matrix";
$text = "fleshwound is a farmer,deadly wounded ";//明文 $ctext = mcrypt_ecb (MCRYPT_3DES, $key, $text, MCRYPT_ENCRYPT); //加密
$ptext = mcrypt_ecb (MCRYPT_3DES, $key, $ctext, MCRYPT_DECRYPT); //解密 echo "明文:$text <br> 密文:$ctext <br>解密后明文:$ptext"
//结果:
//明文:fleshwound is a farmer,deadly wounded
//密文:皚剢GsXe?+ ?v?3佉:?缟2 拉哣 磀毄+?
//解密后明文:fleshwound is a farmer,deadly wounded


了,写了几个小时,总算把PHP中对称密码算法介绍完了,其实大家会发现使用还是非常简单的,不会比写一个分页函数难,如果能够在自己项目中得当地使用,
将会使得系统安全性大大提高。而且聪明的童鞋可以从这里找到对PHP源代码自加密自解密的代码生成方法(比ZEND的更具有灵活性),当然也可以用来做坏
事,实现网页级的变形免杀木马,具体方法我不介绍了。下一个专题是PHP中的公钥密码算法,我会尽量将PHP的密码学应用用通俗的方法逐步的引向深入。

PHP-密码学算法及其应用-对称密码算法的更多相关文章

  1. 算法:Astar寻路算法改进,双向A*寻路算法

    早前写了一篇关于A*算法的文章:<算法:Astar寻路算法改进> 最近在写个js的UI框架,顺便实现了一个js版本的A*算法,与之前不同的是,该A*算法是个双向A*. 双向A*有什么好处呢 ...

  2. Atitit.软件中见算法 程序设计五大种类算法

    Atitit.软件中见算法 程序设计五大种类算法 1. 算法的定义1 2. 算法的复杂度1 2.1. Algo cate2 3. 分治法2 4. 动态规划法2 5. 贪心算法3 6. 回溯法3 7. ...

  3. JVM内存管理------GC算法精解(复制算法与标记/整理算法)

    本次LZ和各位分享GC最后两种算法,复制算法以及标记/整理算法.上一章在讲解标记/清除算法时已经提到过,这两种算法都是在此基础上演化而来的,究竟这两种算法优化了之前标记/清除算法的哪些问题呢? 复制算 ...

  4. 缓存算法(页面置换算法)-FIFO、LFU、LRU

    在前一篇文章中通过leetcode的一道题目了解了LRU算法的具体设计思路,下面继续来探讨一下另外两种常见的Cache算法:FIFO.LFU 1.FIFO算法 FIFO(First in First ...

  5. opencv3中的机器学习算法之:EM算法

    不同于其它的机器学习模型,EM算法是一种非监督的学习算法,它的输入数据事先不需要进行标注.相反,该算法从给定的样本集中,能计算出高斯混和参数的最大似然估计.也能得到每个样本对应的标注值,类似于kmea ...

  6. Floyd-Warshall算法,简称Floyd算法

    Floyd-Warshall算法,简称Floyd算法,用于求解任意两点间的最短距离,时间复杂度为O(n^3). 使用条件&范围通常可以在任何图中使用,包括有向图.带负权边的图. Floyd-W ...

  7. 8皇后以及N皇后算法探究,回溯算法的JAVA实现,非递归,循环控制及其优化

    上两篇博客 8皇后以及N皇后算法探究,回溯算法的JAVA实现,递归方案 8皇后以及N皇后算法探究,回溯算法的JAVA实现,非递归,数据结构“栈”实现 研究了递归方法实现回溯,解决N皇后问题,下面我们来 ...

  8. 最短路径算法之二——Dijkstra算法

    Dijkstra算法 Dijkstra算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止. 注意该算法要求图中不存在负权边. 首先我们来定义一个二维数组Edge[MAXN][MAXN]来存储 ...

  9. 页面置换算法(最佳置换算法、FIFO置换算法、LRU置换算法、LFU置换算法)

    页面置换产生的原因是:分页请求式存储管理(它是实现虚拟存储管理的方法之一,其中一个特性是多次性-->多次将页面换入或换出内存) 效果最好的页面置换算法:最佳置换算法 比较常用的页面置换算法有:F ...

随机推荐

  1. Ext.form.ComboBox常用属性详解

    Ext.form.ComboBox常用属性详解 标签: Extjs js combo js 代码 var combo = new Ext.form.ComboBox({ store : new Ext ...

  2. Current-sense monitor and MOSFET boost output current

    A previous Design Idea describes a programmable current source that used a three-terminal National S ...

  3. 适配高分辨率的图片High DPI Images for Variable Pixel Densities

    用最高的效率与性能提供最好的图片质量. 本文内容来至http://www.html5rocks.com/en/mobile/high-dpi/.是在这篇文章的翻译的基础上进行了总结和说明. 眼下面临的 ...

  4. myeclipse8.6首次运行maven项目的问题解决

    myeclipse8.6导入maven项目后识别为普通java项目,即项目图标上没有小M的标识.这时是无法直接运行的. 解决方法:1,打开Window --> perferences,找到mye ...

  5. Guava的使用

    package guava; import java.io.File; import java.io.IOException; import java.util.ArrayList; import j ...

  6. Video Tag Test

    --> Video Tag Test Your browser does not support the audio element.

  7. make&&gcc/g++ 生成 map file

    map file 对于嵌入式开发是非常有用的,尤其是当你开发的module引起了 kernel panic 的时候. 仅写作Mark用 make: $vim makefile (add  " ...

  8. go语言基础之复数类型

    1.复数类型 示例1: package main //必须有一个main包 import "fmt" func main() { var t complex128 //声明 t = ...

  9. SQL VM上磁盘延迟高, 但Host和Storage Array上的延迟却很低的问题

    按照下面的步骤, 问题解决. =========================== Per Microsoft DDK, Microsoft storport.sys maintains a dev ...

  10. 阿里云 Ubuntu 14.04 安装mysql 5.6

    1. 升级apt-get apt-get update 如果出现 : 说明没有你不是root用户,则需要用sudo命令 sudo apt-get update 下面出现权限问题都可以参照这个方法. 2 ...