PHP-密码学算法及其应用-散列函数

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

//////////////////////////////////////////////////////////////////////////////
目录
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 />\n";//结果是:The hash ise6cfee2c4530b72d7f8f4b010fa80a00
    $hash = mhash(MHASH_MD5, $input, "smatrix");
    echo "The hmac is " . bin2hex($hash) . "<br />\n";//结果是:The hmac is d3e7983ba7bdb7c7d0150e056d2c5017
     echo mhash_count()."<br />\n";
     $hash = MHASH_RIPEMD160;
     echo mhash_get_hash_name($hash)."<br />\n"; //获取算法名称,为RIPEMD160
     echo mhash_get_hash_name(24)."<br />\n"; //让我们看看它提供的24号算法模式是什么,获取算法名称,为RIPEMD256
     echo mhash_get_block_size(24)."<br />\n"; //获取24号算法模式产生的散列值长度,结果为32,32*8=256,一个字符占8位


中mhash_keygen_s2k是个特别好的东西,建议PHP开发者能够用它取代传统的MD5来处理用户口令,至少让网上的这些MD5碰撞检索站点失
效。mhash_keygen_s2k()函数以指定参数1-hash算法模式,指定的参数3-随机的盐,对原始口令参数2产生bytes长度(参数4)
产生一个伪随机腌制的口令。所谓盐,就是在信息中添加噪声干扰,破坏其部分语义特征。 这个函数的原型是:

string mhash_keygen_s2k ( int hash, string password, string salt, int bytes )

下面,我们看下具体的用法:

<?php
    $password = "security matrix";
    $salt = "f34iffffffffj4";
    $hash = MHASH_RIPEMD160;
    $bytes=160;
    echo mhash_keygen_s2k ( $hash, $password, $salt, $bytes ); //产生长度160的腌制后口令
    //结果:
    //毉v9銑B??韔?幢a 镝X K藎ù壥Vd磌?目 ?┕ ?潿(j  Iゎ忲" ? ¬潥护窯1〧//蠊得牶熔.跆]?欭:躎?  3浹か戠3-がJ篮9&?v1懏^?縋3 鄡 鳖-?鎿轐p`xxJ;?
    //恏 

值得注意的是,实际使用中,最好不同的用户口令使用不同的盐,相同的盐总是让人不是很放心,一般情况下,我们没必要自带一个盐库,随机产生一个又需要保留,否则到时候用户口令比较时候会出错。这里我可以给一个可行的方案,使得盐和用户口令内相关,免去记忆盐的烦恼,如下:

<?php
    $password = "security matrix";
    $salt = md5($password);
    $hash = MHASH_RIPEMD160;
    $bytes=160;
    echo mhash_keygen_s2k ( $hash, $password, $salt, $bytes ); //产生长度160的腌制后口令

现在我们介绍最后一个单向散列函数crypt,这个很多人会误认是对称加密函数,其实不是,下一章我会专门论述PHP的对称加密算法。现在我们看看这个函数的原型:

string crypt ( string str [, string salt])


个函数使用了参数,其中第一个是我们需要求散列值的字符串,后面一个可选参数是盐。如果你自己不填,它会使用默认的盐。不过我不建议使用默认的,默认的可
能会出现一些应用中的特殊问题。比如由于盐的改变导致用户口令腌制时最后的散列值不同,导致验证用户失败。这个函数如果你看PHP手册,可能会有点晕,发
现该函数不知道在何处定义其散列算法。实际上认真分析会发现,它是根据盐的长度和格式来决定使用何种算法的,这是个非常古怪的方法。我们还是看看例子。

<?php
if (CRYPT_STD_DES == 1) {
    echo ‘Standard DES: ‘ . crypt(‘www.smatrix.org‘, ‘rl‘) . "<br>\n";
}//当盐是两个字符的时候,内置的散列算法使用了标准的DES构造,也就是CRYPT_STD_DES模式

if (CRYPT_EXT_DES == 1) {
    echo ‘Extended DES: ‘ . crypt(‘www.smatrix.org‘, ‘_J9..rasm‘) . "<br>\n";
}//当盐是九个字符的时候,内置的散列算法使用了扩展的DES构造,也就是CRYPT_EXT_DES模式

if (CRYPT_MD5 == 1) {
    echo ‘MD5:          ‘ . crypt(‘www.smatrix.org‘, ‘$1$rasmusle$‘) . "<br>\n";
}//当盐采用$1$开头,且12个字符时,内置的散列算法使用了MD5,也就是CRYPT_MD5模式

if (CRYPT_BLOWFISH == 1) {
    echo ‘Blowfish:     ‘ . crypt(‘www.smatrix.org‘, ‘$2a$07$rasmuslerd...........$‘) . "<br>\n";
}//当盐采用$2a$或者$2$开头,且16个字符时,内置的散列算法使用了BLOWFISH构造,也就是CRYPT_BLOWFISH 模式
//结果:
//Standard DES: rls0yK8/sarN6
//Extended DES: _J9..rasm6cqPLViS6Po
//MD5: $1$rasmusle$Z4lIslfbi/Oo4nyaxR4eB/
//Blowfish: $2a$07$rasmuslerd............wnbDKPDtWJSnGforY7iyGVP8XWLrCni

PHP
中关于散列算法基本已经讲完了,从上面的论述看,MHASH函数体系使用灵活而且安全性更好一些。CRYPT比较古怪,一般很少有人会使用。基本散列函数
使用最方便,但是问题也较多,容易穷举。当然,并不是每个IDC都会在其PHP模块中加载MHASH,我们开发应用时一定要搞清楚服务器环境。一般可以通
过phpinfo函数中信息看出来:
mhash
MHASH support     Enabled
MHASH API Version     Emulated Support
就写到这里,下一节是PHP的对称密码算法及其应用。希望大家能在开发时多使用成熟的密码学解决方案,而不是自己创新山寨一个。

PHP-密码学算法及其应用-散列函数

时间: 2024-10-10 19:17:52

PHP-密码学算法及其应用-散列函数的相关文章

基于双线性配对的密码学算法

1.数据加密原理 我们将构建一个高效无证书签密方案.因为转换不能识别的范式加密和签名方案成组合证书协议,我们采用扩展传统的签密法的做法用无证书密钥验证机制,以基于身份的技术来配对验证关联的公共密钥. 传统的密码系统按照用户选择自己的私钥范式,计算对应的公钥,并提交给认证机构,其验证他们的身份,并颁发证书连接这些身份和公共密钥.此在创建一个认证的基础设施需要数字证书管理(也被称为公钥基础结构,或PKI)可能被证明繁琐的维护.沙米尔引入的基于身份的(IB)密码学的概念在试图减轻PKI的负担.在IB加

Java密码学原型算法实现——第二部分:单钥加密算法

题注 本部分为单钥加密算法的实现.单钥加密体制是密码学加密中的核心密码学原型之一,很早很早前人类就已经开始了单钥密码学体制的研究.本部分的所有实现基于Bouncy Castle库,其地址详见我上一篇博客<Java密码学原型算法实现--第一部分:标准Hash算法>. 不得不说,相比Java JDK的API,Bouncy Castle提供的库函数封装更为科学,实现更为方便.实际上,Bouncy Castle根据单钥体制的不同算法以及不同工作模式进行了不同的封装,只要实现了一种模式或者一种加密算法,

MD5算法介绍及jdk自带实现方式

MD5算法,已经被人们熟知,作为一名资深或者入门级的开发者,都号称"MD5啊,知道知道".前几天程序略有小问题,原因是有的地方加密了,有的地方没加密.有个同事很得意的说,MD5就是个hash算法,很容易被解密的.当时我是无言以对了.因为俺记得MD5是不可逆的,既然不可逆,又哪里来的"解密"呢.于是我们在网上搜索"MD5解密",哇kao,竟然真的有结果,然则,事实并非那么简单,我们把MD5的一串序列放到"在线MD5解密"中去解密

PHP-密码学算法及其应用-对称密码算法

转自:http://www.smatrix.org/bbs/simple/index.php?t5662.html //////////////////////////////////////////////////////////////////////////////目录1.    PHP的散列函数及其应用2.    PHP中的对称密码算法及其应用3.    PHP的公钥密码算法及其应用/////////////////////////////////////////////////////

统治世界的十大算法

转自 http://geek.csdn.net/news/detail/32456 软件正在统治世界.而软件的核心则是算法.算法千千万万,又有哪些算法属于“皇冠上的珍珠”呢?Marcos Otero给出了他的看法. 什么是算法? 通俗而言,算法是一个定义明确的计算过程,可以一些值或一组值作为输入并产生一些值或一组值作为输出.因此算法就是将输入转为输出的一系列计算步骤. —Thomas H. Cormen,Chales E. Leiserson,算法入门第三版 简而言之,算法就是可完成特定任务的一

Memcache技术分享:介绍、使用、存储、算法、优化、命中率

原文地址:http://zhihuzeye.com/archives/2361 1.memcached 介绍 1.1 memcached 是什么? memcached 是以LiveJournal旗下Danga Interactive 公司的Brad Fitzpatric 为首开发的一款软件.现在已成为mixi.hatena.Facebook.Vox.LiveJournal 等众多服务中提高Web应用扩展性的重要因素.许多Web 应用都将数据保存到RDBMS 中,应用服务器从中读取数据并在浏览器中

javascript实现playfair和hill密码算法

时至期末,补习信息安全概论作业.恰巧遇古典密码学算法中的playfair算法和hill算法,用javascript语言实现起来是在有趣,边查百度边编码,顺便好好补习一下javascript基础. playfair Playfair密码(英文:Playfair cipher 或 Playfair square)是一种替换密码.依据一个5*5的正方形组成的密码表来编写,表中排列有25个字母.对于英语中的26个字母,去掉最常用的Z,构成密码表. 实现思路: 1,编制密码表 密钥是一个单词或词组,密码表

密码学相关概念

摘要算法 摘要算法是一种能产生特殊输出格式的算法,这种算法的特点是:无论用户输入什么长度的原始数据,经过计算后输出的密文都是固定长度的,这种算法的原理是根据一定的运算规则对原数据进行某种形式的提取,这种提取就是摘要,被摘要的数据内容与原数据有密切联系,只要原数据稍有改变,输出的"摘要"便完全不同,因此,基于这种原理的算法便能对数据完整性提供较为健全的保障.但是,由于输出的密文是提取原数据经过处理的定长值,所以它已经不能还原为原数据,即消息摘要算法是不可逆的,理论上无法通过反向运算取得原

Memcahce(MC)系列(一)Memcache介绍、使用、存储、算法、优化

关于memcache的安装,有兴趣的朋友请参考这篇文章:http://blog.csdn.net/xifeijian/article/details/22000173 1.memcached 介绍 1.1 memcached 是什么? memcached 是以LiveJournal旗下Danga Interactive 公司的Brad Fitzpatric 为首开发的一款软件.现在已成为mixi.hatena.Facebook.Vox.LiveJournal 等众多服务中提高Web 应用扩展性的