转自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-密码学算法及其应用-散列函数的更多相关文章

  1. Java 密码学算法

    Java 密码学算法 候捷老师在< 深入浅出MFC 2e(电子版)>中引用林语堂先生的一句话: 只用一样东西,不明白它的道理,实在不高明 只知道How,不知道Why,出了一点小问题时就无能 ...

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

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

  3. 从NLP任务中文本向量的降维问题,引出LSH(Locality Sensitive Hash 局部敏感哈希)算法及其思想的讨论

    1. 引言 - 近似近邻搜索被提出所在的时代背景和挑战 0x1:从NN(Neighbor Search)说起 ANN的前身技术是NN(Neighbor Search),简单地说,最近邻检索就是根据数据 ...

  4. 什么是哈希Hash(散列函数)

    Hash(散列函数) Hash,一般翻译做散列.杂凑,或音译为哈希,是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映射,也就 ...

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

    1.memcached 介绍 1.1 memcached 是什么? memcached 是以LiveJournal旗下Danga Interactive 公司的Brad Fitzpatric 为首开发 ...

  6. 怎样的 Hash 算法能对抗硬件破解

    前言 用过暴力破解工具 hashcat 的都知道,这款软件的强大之处在于它能充分利用 GPU 计算,比起 CPU 要快很多.所以在破解诸如 WiFi 握手包.数据库中的口令 Hash 值时,能大幅提高 ...

  7. 数据结构与算法JS实现

      行解算法题,没错,就是这么方便. 当然也可以使用 Node.js 环境来执行,具体参考Node.js官方文档即可. 二 对象和面向对象编程 js中5种数据类型,并没有定义更多的数据类型,但是运用j ...

  8. Java数据结构和算法(一)散列表

    Java数据结构和算法(一)散列表 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 散列表(Hash table) 也叫哈希表 ...

  9. javascript实现playfair和hill密码算法

    时至期末,补习信息安全概论作业.恰巧遇古典密码学算法中的playfair算法和hill算法,用javascript语言实现起来是在有趣,边查百度边编码,顺便好好补习一下javascript基础. pl ...

随机推荐

  1. Codeforces Round #202 (Div. 1) D. Turtles DP

    D. Turtles Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/547/problem/B ...

  2. linux基础命令学习 (七)压缩解压

    一.tar tar主要用来压缩和解压文件 语法: tar [主选项+辅选项] 文件或者目录 主选项: c 创建新的档案文件.如果用户想备份一个目录或是一些文件,就要选择这个选项.相当于打包. x 从档 ...

  3. Hiho----微软笔试题《Combination Lock》

    Combination Lock 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 Finally, you come to the interview room. You ...

  4. C# winform 禁止窗体移动

    #region 禁止窗体移动 public const int WM_SYSCOMMAND = 0x112; public const int SC_MOVE = 0xF012; protected ...

  5. 【redis】redis五大类 用法 【转载:https://www.cnblogs.com/yanan7890/p/6617305.html】

    转载地址:https://www.cnblogs.com/yanan7890/p/6617305.html

  6. 【GISER && Painter】矢量切片(Vector tile)番外一:Proj4js

    说明:番外篇是对正篇矢量切片(Vector tile)中提到的一些值得继续延伸的关注点继续进行探索和学习,所涉及的内容以解决实际问题为主要导向. 一.新的需求? 在完成了矢量切片的工作后,新的需求出现 ...

  7. python的单元测试框架

    1.unittest是Python内置的标准类库.它的API跟Java的JUnit..net的NUnit,C++的CppUnit很相似.   通过继承unittest.TestCase来创建一个测试用 ...

  8. FreeBSD与Linux十个本质上的区别

    Linux的标志是一只十分可爱的小企鹅,而FreeBSD的标志是一个拿着叉子的小恶魔.你是否经常会听到人们把 Linux及 BSD 系统混为一谈?是的,我有时会经常听到一些新手,甚至于媒体都这么说.当 ...

  9. 使用apache-cxf-2.2.10来制作一个极简版WebService程序

    原想拿最新版cxf来制作的,无奈Apache的zip包总下不下来,国内的apache-cxf-2.2.10却一蹴而就,也就用了这个版本.下载地址是:http://pan.baidu.com/s/1td ...

  10. C#应用视频教程3.2 Halcon软件测试

    Halcon是图像处理比较牛逼的一个软件(德国人的东西,做的非常强大,里面集成的算法很多,可能你一辈子研究这个也做不过他),然而牛逼归牛逼,康耐视,基恩士也很牛逼,但是日本人的东西一般太过封闭,屌丝用 ...