PHP代码片断之:短HASH

有的时候需要用HASH来对数据标注,PHP下无疑就是Md5了,不过呢如果这个哈希是给用户看的呢?总之试图实现4chan的tripcode(绊码)功能时候发现:32位长的MD5显然不够雅观。在这里就给出一个短小、有几分不靠谱的基于MD5的HASH方法。使用这个可能会稍微增大冲撞出现的几率,但是并不会显著增大。

/*********
* CHash provides users with a fairly strong but short hash for identification
* Based on MD5
**********/
class stdHash{
	var $hashIn = '';
	function __construct($hashIn=''){
		$this->hashIn = $hashIn;
	}
	function hash($string){
		$cherryTable = Array('0'=>0,'1'=>1,'2'=>2,'3'=>3,'4'=>4,'5'=>5,'6'=>6,'7'=>7,'8'=>8,'9'=>9,'A'=>10,'B'=>11,'C'=>12,'D'=>13,'E'=>14,'F'=>15);
		$md = md5($string.$this->hashIn);$m="";
		for($i=0;$i<16;$i++){
			$m.=chr($cherryTable[$md[$i*2]]*16 + $cherryTable[$md[$i*2+1]]);
		}
		return preg_replace('~[N=]~','',str_rot13(base64_encode($m)));
	}
}


首先MD5缩小为全Byte的16位数值(长度变为1/2,无损耗准确度)然后经过Base64编码(大小变为原3/4),然后由于定长度,去除Base64后面=号(减小2位,至此还是准确的),根据一些测试觉得N出现概率很高,于是去除所有N(这时增大冲撞的出现概率,如 aNbNNcd和aNNbNcd一样被缩减为abcd,不过在很多情况下还是没有冲撞的…比如这些数据:

Hashes "Hello World":
CHash: DDDODRSOjxOjOD (14 Chars)
MD5: b10a8db164e0754105b7a99be72e3fe5

Hashes "Hello World1":
CHash: HOtLVDZODQ (10 Chars)
MD5: 5e750da6c65851db5bb0d37f453ca33f

Hashes "This is a longer string":
CHash: OjRSjWROt (9 Chars)
MD5: 0deb8c14aa2d13b16563cc996ec1c016

Hashes "Foobar":
CHash: PDHQHODTt (9 Chars)
MD5: 89d5739baabbbe65be35cbe61c88e06d

基本上短Hash可以比较简单的缩减MD5到原长度的一半。当然有更好的方式么?或许不使用base64可能有,不过希望简单的人们不妨测试一下CHash。

让我回想起了基因组鸟枪法的…种种无法测定长度啊。

One Comment

发表回复

您的电子邮箱地址不会被公开。