PHP中的密码学算法及其应用
Security Matrix(http://www.smatrix.org),转载请注明出处!
//////////////////////////////////////////////////////////////////////////////
目录
1. PHP的散列函数及其应用
2. PHP中的对称密码算法及其应用
3. PHP的公钥密码算法及其应用
///////////////////////////////////////////////////////////////////////////////
序: 这么几年一直在潜心修炼内功,没有在网上写点东西,安全矩阵作为一个国内少有的以密码学和信息安全理论研究为特色的学术技术研究组织,在国内推广密码学应用是我们的责任,虽然这个道路比较艰辛和漫长,但总是需要人来做的。我计划对几大主流的脚本语言分别进行阐述,系统总结,力图做到普通的脚本开发者和网友能够看懂。这是第一篇关于PHP的,以下假设读者已经具有PHP的基本知识。
1. PHP的散列函数及其应用
1.1 什么是散列函数
散列函数又被称为hash函数(哈希函数),也称杂凑函数,就是把任意长的输入消息串变化成固定长的输出串的一种函数。这个输出串就叫做该消息的哈希值(或称为杂凑值)。一般用于产生消息摘要,进行数据消息的完整性检验。严格意义上来讲,散列函数并不是密码算法,因为它是单向不可逆的。一个散列函数有以下特点:(1)输入长度是任意的,而输出长度是固定的,长度应该足够的长,以便抵抗生日攻击(关于生日攻击请百度)。(2)对每一个给定的输入,正向计算输出即散列值是很容易的,但逆向寻找碰撞时困难的。
Hash函数主要用于完整性校验和提高数字签名的有效性,在密码协议中有着非常重要的应用,目前已有很多成熟的方案。关于具体的密码学方面的知识可以到安全矩阵上去下载一些书来看。
常见散列函数(Hash函数)有两种:
(1)、MD5(Message Digest Algorithm 5):是RSA数据安全公司开发的一种单向散列算法,MD5被广泛使用,可以用来把不同长度的数据块进行暗码运算成一个128位的数值;
(2、SHA(Secure Hash Algorithm)这是一种较新的散列算法,可以对任意长度的数据运算生成一个160位的数值。
目前在理论上MD5和SHA已经被破解,但是在实际应用中并非那么简单,只要合理应用总是可行的。另外以下这些也被认为具有散列函数的功能。
(1)、MAC(Message Authentication Code):消息认证代码,是一种使用密钥的单向函数,可以用它们在系统上或用户之间认证文件或消息。HMAC(用于消息认证的密钥散列法)就是这种函数的一个例子。
(2)、CRC(Cyclic Redundancy Check):循环冗余校验码,CRC校验由于实现简单,检错能力强,被广泛使用在各种数据校验应用中。
(3)、自产山寨版和基于一些对称加密算法的散列函数。
1.2 PHP中散列函数及其应用
Php中的最常用的散列函数有这么几个:
md5(),md5_file(), sha1(),sha1_file().
其实还有更为强悍和灵活的crypt和mhash系列。首先我们从简单常用的开始,先看一个列子: 复制内容到剪贴板
代码:
<?php
$str="security matrix is a website about cryptograhy.";
$hashmd5=md5($str);
$hashsha1=sha1($str);
echo "md5 hash value is:".$hashmd5;
echo <br>;
echo "sha1 hash value is:$hashsha1";
//最后的结果是:
//md5 hash value is:c4558a37e61eb1db03f7270d4f674ae6
//sha1 hash value is:d10155e45624bf84b4d1fdf4e6e47e067b7a4e1a
?>很显然,我们的字符串经过这两个函数后得到一系列没有规律的16进制序列。注意到SHA1产生的序列比MD5多了8个字符,总共SHA1这是因为SHA1是160位的散列,而MD5是128位的散列。密码学中所说的位是指二进制的位数,一个16进制占4个二进制位,所以SHA1是16进制40位,MD5是16进制32位。这两个函数的原型是: 复制内容到剪贴板
代码:
string md5 ( string str [, bool raw_output] )
string sha1 ( string str [, bool raw_output] )其中有个可选参数raw_output是布尔类型的,默认是false,如果此处写1或者true等能够保证这个值为真的表达式。则输出时真实的消息摘要。看同样的例子: 复制内容到剪贴板
代码:
<?php
$str="security matrix is a website about cryptograhy.";
$hashmd5=md5($str,1);
$hashsha1=sha1($str,1);
echo "md5 hash value is:".$hashmd5;
echo <br>;
echo "sha1 hash value is:$hashsha1";
//最后的结果是:
//md5 hash value is:腢??臂 ? OgJ鎈
//sha1 hash value is:?U銿$縿囱驿~ {zN
?>很显然,这有点像火星文,在MYSQL存储时这个消息摘要,有时候因为字符易做图出现难以解释的人品问题。一般我们只用默认的,以16进制的形式输出的,存储方便。一般,MD5和SHA1用得最多的场合就是验证用户密码的场合。通常将用户的口令用MD5或者SHA1处理后放入数据库中,以减少万一被SQL注入攻击或者获得数据表后的暴露真实口令信息的风险。但是,由于使用标准的MD5算法,常用的口令的散列值可以很容易穷举,所以实际上寻找一个碰撞可能就比较容易了。网上有很多这样的MD5散列碰撞的查询站点。为了对付这种穷举,我们在使用时可以采用些变形或者带有salt的MAC,而且最好使用SHA1。以下给个例子: 复制内容到剪贴板
代码:
<?php
$passwd="13455564432";
$salt="dfdasafgr4vtrgrrgf";
$str=$passwd.$salt;
$hashmd5=md5(md5($str).$salt);
echo $hashmd5; //结果:bc052554e38b588df52594176a148b8b
?>现在我们来谈谈md5_file(), sha1_file().很显然,这个是用来计算给定文件名的散列值的。函数原型如下: 复制内容到剪贴板
代码:
string md5_file ( string filename [, bool raw_output])
string sha1_file ( string filename [, bool raw_output])其中参数的意义和用法跟前面md5(), sha1()是一样的。我们可以来看个例子: 复制内容到剪贴板
代码:
<?php
$filename = 1.txt;
$hash = md5_file($filename);
echo $hash; //结果e0a7a59e58c7b138e850b8055fba27da
?>这两个函数可以用来判断自己的程序文件是否被篡改过,比如是否嵌入了木马。DISCUZ论坛源码有个代码检查功能,就用这个实现。除此之外,还可以用来构造复杂的数学验证算法,防止别人破解需要授权的PHP程序。因为只要修改了程序,其文件的散列值基本上都要改变的。对脚本代码加壳当然这对于一般的程序员有一定的难度。一般应用中有这几个基本上也够用了,这是PHP默认就支持的。接下来我们来看看MAC和CRC。
其中主要的函数是mhash(),通俗的说,就是带有一个密钥的哈希函数。为什么要带个密钥呢,其实这种改进主要是为了防止散列函数的在线暴力破解和提高抗碰撞能力。函数原型如下: 复制内容到剪贴板
代码:
string mhash ( int hash, string data [, string key])因为这个属于扩展模块,所以要使用mhash(),需要在编译PHP的时候增加一项配置,在PHP的配置时,添加--with-mhash[=DIR]。如果没有,就会出现“Fatal error: Call to undefined function…”,这个函数的第一项参数是我们要使用的哈希算法模式,由一些预定义算法模式构成,每种算法模式得到的散列值是不一样的,其中最常用的如下: 复制内容到剪贴板
代码:
MHASH_MD5
MHASH_SHA1
MHASH_HAVAL256 //HAVAL系列算法支持多种输出长度,从128-256
MHASH_HAVAL192
MHASH_HAVAL160
MHASH_HAVAL128
MHASH_RIPEMD160 //RIPEMD系列算法也支持多种输出长度,从128-256
MHASH_GOST
MHASH_TIGER
MHASH_CRC32
MHASH_CRC32B 第二项参数是我们要计算哈希值的字符串,第三项参数是密钥。除此之外,HMAC体系还有其他的一些函数,如下所示: 复制内容到剪贴板
代码:
mhash_count --获取最多能够支持的HASH函数算法模式的个数
mhash_get_block_size --获取特定预定义算法模式的散列值长度
mhash_get_hash_name --获取预定义算法名称
mhash_keygen_s2k --产生一个安全的密码散列值,完全可以取代MD5对用户输入口令的处理
mhash --计算散列值为了说明他们的用法,我们来看看例子: 复制内容到剪贴板
代码:
<?php
$input = "security matrix";
$hash = mhash(MHASH_MD5, $input);
echo "The hash is " . bin2hex($hash) . "<br />
";//结果是:The hash is e6cfee2c4530b72d7f8f4b010fa80a00
$hash = mhash(MHASH_MD5, $input, "smatrix");
echo "The hmac is " . bin2hex($hash) . "<br />
";//结果是:The hmac is d3e7983ba7bdb7c7d0150e056d2c5017
echo mhash_count()."<br />
";
$hash = MHASH_RIPEMD160;
echo mhash_get_hash_name($hash)."<br />
"; //获取算法名称,为RIPEMD160
echo mhash_get_hash_name(24)."<br />
"; //让我们看看它提供的24号算法模式是什么,获取算法名称,为RIPEMD256
echo mhash_get_block_size(24)."<br />
"; //获取24号算法模式产生的散列值长度,结果为32,32*8=256,
一个字符占8位
?>
其中mhash_keygen_s2k是个特别好的东西,建议PHP开发者能够用它取代传统的MD5来处理用户口令,至少让网上的这些MD5碰撞检索站点失效。mhash_keygen_s2k()函数以指定参数1-hash算法模式,指定的参数3-随机的盐,对原始口令参数2产生bytes长度(参数4)产生一个伪随机腌制的口令。所谓盐,就是在信息中添加噪声干扰,破
补充:综合编程 , 安全编程 ,