PS:原创文章,如需转载,请注明出处,谢谢!
本文地址: http://flyer0126.iteye.com/blog/ 1753735
PHP的加密函数crypt(), 这一函数完成被称作单向加密的功能,它可以加密一些明码,但不能够将密码转换为原来的明码,这种方式相对来讲比较安全。
<?php // 可用散列允许的最长可用盐值 print "My system salt size is: ". CRYPT_SALT_LENGTH."<br/>"; // 测试串 $str = "flyer0126"; // 执行加密 $salt = substr($str, 0, 2); $pass = crypt($str, $salt); // 将$pass存入数据库,下次使用时可使用相同算法进行验证 ...... echo $pass; // flmnB14trocYs
注:$salt 作为可选的盐值字符串。如果没有提供,算法行为将由不同的算法实现决定,并可能导致不可预料的结果。
相比之下,PHP的扩展Mcrypt功能就强大很多了,它是一个功能强大的加密扩展库。Mcrypt的优点不仅仅在于其提供的加密算法较多,还在于它可以对数据进行加/解密处理。
1. 安装
windows下默认已经打包好所需要的库,这点可以在phpinfo() 中验证是否存在mcrypt 模块。
Linux版的PHP自身不打包该库,需要自行到官方网站下载代码进行编译安装。
2. 介绍
参数:
1). cipher
One of the MCRYPT_ciphername constants, or the name of the algorithm as string.
2). key
The key with which the data will be encrypted. If it's smaller than the required keysize, it is padded with '\0'. It is better not to use ASCII strings for keys. It is recommended to use the mhash functions to create a key from a string.
3). data
The data that will be encrypted with the given cipher and mode. If the size of the data is not n * blocksize, the data will be padded with '\0'. The returned crypttext can be larger than the size of the data that was given by data.
4). mode
One of the MCRYPT_MODE_modename constants, or one of the following strings: "ecb", "cbc", "cfb", "ofb", "nofb" or "stream".
5). iv
Used for the initialization in CBC, CFB, OFB modes, and in some algorithms in STREAM mode. If you do not supply an IV, while it is needed for an algorithm, the function issues a warning and uses an IV with all its bytes set to '\0'.
Mcrypt支持四种块加密模型:
1).MCRYPT_MODE_ECB
(electronic codebook) 适合对小数量随机数据的加密,比如加密用户的登录密码之类的。
2).MCRYPT_MODE_CBC (cipher block chaining) 适合加密安全等级较高的重要文件类型。
3).
MCRYPT_MODE_CFB (
cipher feedback
) 适合于需要对数据流的每一个字节进行加密的场合。
4).MCRYPT_MODE_OFB
(output feedback, in 8bit)
和CFB模式兼容,但比CFB模式更安全。CFB模式会引起加密的错误扩散,如果一个byte出错,则其后续的所有byte都会出错。OFB模式则不会有
此问题。但该模式的安全度不是很高,不建议使用。
5).
MCRYPT_MODE_NOFB (output feedback, in nbit) 和OFB兼容,由于采用了块操作算法,安全度更高。
6).
MCRYPT_MODE_STREAM 是为了WAKE或者RC4等流加密算法提供的额外模型。
NOFB和STREAM仅当mycrypt的版本号大于等于
libmcrypt-2.4.x才有效。
3. 应用
<?php /** * 扩展Mcrypt应用类--加密解密 * @author flyer0126 * @since 2012/12 */ class Mcrypt { // 加密密钥 private $key = ''; // 加密算法 private $cipher = ''; // 加密模式 private $mode = ''; /** * 构造器 * @param [type] $cipher [description] */ function __construct($cipher) { if (!function_exists('mcrypt_module_open')) { return false; } if (empty($cipher)) { return false; } $this->cipher = $cipher; } /** * 设置mode * @param [type] $mode [description] */ function setMode($mode) { if (!strlen($mode)) { return false; } if (!in_array($mode, mcrypt_list_modes())) { return false; } $this->mode = $mode; } /** * 设置mode * @param [type] $key [description] * @return [type] [description] */ function setkey($key) { if (empty($key)) { return false; } $vi_size = $this->get_iv_size(); $key = hash('md5', $key); $this->key = strlen($key)>$vi_size ? substr($key, 0, $vi_size) : $key; } /** * 获取vi_size * @return [type] [description] */ function get_iv_size() { if (empty($this->cipher) || empty($this->mode)) { return false; } return mcrypt_get_iv_size($this->cipher, $this->mode); } /** * 获取iv * @return [type] [description] */ function get_iv() { $vi_size = $this->get_iv_size(); return mcrypt_create_iv($vi_size); } /** * 加密 * @param [type] $data [description] * @return [type] [description] */ function encrypt($data=null) { if (null == $data || empty($this->key)) { var_dump($this);return false; } // CFB和OFB是必须有IV, CBC和EBC则是可选的 $vi = $this->get_iv(); if (in_array($this->mode, array(MCRYPT_MODE_OFB, MCRYPT_MODE_CFB)) && empty($vi)) { exit("Error: vi is empty."); } return mcrypt_encrypt($this->cipher, $this->key, $data, $this->mode, $vi); } /** * 解密 * @param [type] $data [description] * @return [type] [description] */ function decrypt($data = null) { if (null == $data) { return false; } $vi = $this->get_iv(); return mcrypt_decrypt($this->cipher, $this->key, $data, $this->mode, $vi); } }
测试应用如下:
<?php // 测试内容 $data = "这是一段测试内容,by flyer0126 at 2012/12/25"; // 密钥 $key = "key:111"; // 密码类型 $cipher = MCRYPT_DES; // 密码模式 $mode = MCRYPT_MODE_ECB; // 测试Mcrypt的加密解密功能 $mc = new Mcrypt($cipher); $mc->setMode($mode); $mc->setkey($key); $ret = $mc->encrypt($data); $dret = $mc->decrypt($ret); // 输出 echo '$ret:'.$ret."<br/>".'$dret:'.$dret;exit; /** 输出内容(utf-8编码) **/ $ret:�c�qK:~�E']�!%@��#�(���`��0�=�J��1� �o�h0�Yv� $dret:这是一段测试内容,by flyer0126 at 2012/12/25
可能会出现的几个常见问题:
1). Warning: mcrypt_encrypt() [function.mcrypt-encrypt]: Attempt to use an empty IV, which is NOT recommend in ...
原因:需要iv的加密模式加密时没有提供有效的iv,此类模式包括:CBC, CFB, OFB。
2). Warning: mcrypt_encrypt() [function.mcrypt-encrypt() Size of key is too large for this algorithm
原因:key值处理问题,key值经md5加密后,增强安全性,需要根据vi_size的值进行截取,否则输出长度警告。
已有 0 人发表留言,猛击->>这里<<-参与讨论
ITeye推荐
- —软件人才免语言低担保 赴美带薪读研!—
面向过程语言与面向对象语言最大的区别就是,对抽象的支持不一样。两者都可以抽象,只是后者容易多了,它专为抽象而生。
但最重要的是,作为一个使用面向对象语言的程序员,要有这个意识,知道自己使用的这些特性有什么意义,会起到什么作用。只有意识到自己在做什么,才能有针对性地把它做到更好。
很难想象完全没有这种意识的程序员能用好任何面向对象的语言。Unix编程艺术上讲要适度的抽象,但在到达这个层次之前,请先弄清楚面向对象编程的本质含义。
已有 0 人发表留言,猛击->>这里<<-参与讨论
ITeye推荐
- —软件人才免语言低担保 赴美带薪读研!—
POJ2388题意:
【输入】第一行为n,接下来n行分别为一个数;
【输出】这n个数的中位数
样例:
Sample Input
5
2
4
1
3
5
Sample Output
3
分析:好象用多种排序法都可以AC,这里先用堆排序,主要是复习一下堆排序代码。
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in=new Scanner(System.in); int n=in.nextInt(); int[] array =new int[n+1]; // array[0]=100; 不参与,下标从1开始 for(int i=1;i<=n;i++) array[i]=in.nextInt(); heapSort(array);//堆排序 System.out.println(array[n / 2+1 ]); //堆排序的结果 // for(int i=1;i<=n;i++) // System.out.print(array[i]+" "); } //把a,b位置的值互换 public static void swap(int[] array, int a, int b) { //临时存储child位置的值 int temp = array[a]; array[a]=array[b]; array[b]=temp; } /*将数组调整成堆 *根据树的性质建堆,树节点前一半一定是分支节点,即有孩子的,所以我们从这里开始调整出初始堆 */ public static void adjust(int[] array){ for (int i = array.length / 2; i > 0; i--) adjust(array,i, array.length-1); } /** * 调整堆,使其满足堆得定义 * @param i * @param n */ public static void adjust(int[] array,int i, int n) { int child; for (; i <= n / 2; ) { child = i * 2; if(child+1<=n&&array[child]<array[child+1]) child+=1;/*使child指向值较大的孩子*/ if(array[i]< array[child]){ swap(array,i, child); /*交换后,以child为根的子树不一定满足堆定义,所以从child处开始调整*/ i = child; } else break; } } //对一个最大堆heap排序 public static void heapSort(int[] array) { adjust(array);//建堆 for (int i = array.length-1; i > 0; i--) { /*把根节点跟最后一个元素交换位置,调整剩下的n-1个节点,即可排好序*/ swap(array,1, i); adjust(array,1, i - 1); } } }
-
本文附件下载:
- 11138181_AC_1704MS_5260K.zip (1.1 KB)
已有 0 人发表留言,猛击->>这里<<-参与讨论
ITeye推荐
- —软件人才免语言低担保 赴美带薪读研!—