php:仅数字散列?
在php中,有没有一种方法可以从字符串中给出唯一的哈希值,但哈希值仅由数字组成 例如:php:仅数字散列?,php,hash,md5,numbers,short,Php,Hash,Md5,Numbers,Short,在php中,有没有一种方法可以从字符串中给出唯一的哈希值,但哈希值仅由数字组成 例如: return md5(234); // returns 098f6bcd4621d373cade4e832627b4f6 但我需要 return numhash(234); // returns 00978902923102372190 (20 numbers only) 这里的问题是,我希望散列是短的 编辑: 好的,让我在这里解释一下背景故事。 我有一个网站,每个注册的人都有一个ID,我也需要一个ID
return md5(234); // returns 098f6bcd4621d373cade4e832627b4f6
但我需要
return numhash(234); // returns 00978902923102372190
(20 numbers only)
这里的问题是,我希望散列是短的
编辑:
好的,让我在这里解释一下背景故事。
我有一个网站,每个注册的人都有一个ID,我也需要一个ID供该人使用和交换(因此不会太长),到目前为止,ID编号已经是00001、00002、00003等等
首先,md5基本上是折衷的,所以除了非关键散列之外,您不应该使用它。 PHP5具有
hash()
函数,请参阅
将最后一个参数设置为true将为您提供一个二进制数据字符串。或者,您可以将生成的十六进制散列拆分为两个字符的片段,并将它们分别转换为整数,但我认为这要慢得多。PHP中的MD5或SHA1散列返回十六进制数,因此您只需转换基数即可。PHP有一个函数可以为您做到这一点:
$bignum = hexdec( md5("test") );
或
因为您需要一个有限大小的数字,所以可以使用模块化除法将其置于您想要的范围内
$smallnum = $bignum % [put your upper bound here]
编辑
正如Artefactor在评论中指出的那样,使用这种方法将导致数字超出PHP中整数的最大大小,并且模除后的结果将始终为0。但是,获取包含前16个字符的哈希的子字符串不存在此问题。用于计算初始大数的修订版本:
$bignum = hexdec( substr(sha1("test"), 0, 15) );
您可以尝试crc32()
。请参阅以下网址的文档:
话虽如此,
crc
应该只用于验证数据的完整性
有一些很好的答案,但对我来说,这些方法似乎很愚蠢。他们首先强制php创建一个十六进制数,然后将其转换回一个BigInteger(
hexdec
),然后将其缩减为一个字母数。。。这是很多工作
为什么不呢
将哈希读取为二进制:
$binhash = md5('[input value]', true);
然后使用
$numhash = unpack('N2', $binhash); //- or 'V2' for little endian
将其转换为两个INT
s($numhash
是两个元素的数组)。现在,只需使用和
操作即可减少数字中的位数。e、 g:
$result = $numhash[1] & 0x000FFFFF; //- to get numbers between 0 and 1048575
但要注意碰撞减少数量意味着增加两个不同[输入值]具有相同输出的概率
我认为更好的方法是使用带有双射函数的“ID加密”。所以不会发生碰撞!对于最简单的类型,只需使用
最大输入值范围为0到25的示例:
function numcrypt($a)
{
return ($a * 15) % 26;
}
function unnumcrypt($a)
{
return ($a * 7) % 26;
}
输出:
numcrypt(1) : 15
numcrypt(2) : 4
numcrypt(3) : 19
unnumcrypt(15) : 1
unnumcrypt(4) : 2
unnumcrypt(19) : 3
e、 g
$id=unnumcrypt($\u GET('userid');
... 用ID做点什么。。。
回声';
当然,这是不安全的,但是如果没有人知道用于加密的方法,那么就没有安全原因,那么这种方法更快,并且冲突安全。切掉散列的问题是冲突,要避免冲突,请尝试:
return hexdec(crc32("Hello World"));
crc32()
:
生成32位长度的循环冗余校验和多项式
这通常用于验证数据的完整性
正在传送
这给了我们一个32位的整数,在32位安装中是负数,在64位安装中是正数。这个整数可以像数据库中的ID一样存储。使用hexdec()
函数将其转换为十进制后,这不会有冲突问题,因为它适合32位变量。试试。它将数字散列成您可以定义的格式。格式包括有多少个字符以及包含的字符。
示例:
$hashids->encode(1)
是否返回“28630”取决于您的格式,只需使用下面的手动哈希方法即可: 将数字(如6位)除以素数3,5,7 并获取小数点后的前6个值作为要使用的ID。在实际创建ID之前检查唯一性,如果存在冲突,则将最后一位数字增加+1,直到无冲突。
例如,123456给你771428 123457给你780952
123458给你790476 速度不是一个问题,我唯一的问题是num散列是唯一的,长度不是可笑的。如果我将“test”变量限制为一组有限的数字,会怎么样?有没有办法减小散列大小?@YuriKolovsky-最终的散列大小将由第二步中模块除法使用的上限决定。例如,如果希望哈希值都是5位数,那么可以使用
$smallnum=$bignum%99999
。不管初始MD5或SHA1散列中放入了什么,这都会起作用。@YuriKolovsky-当然,使用较小的数字会增加散列中冲突的风险。由您决定避免冲突的重要性。应该补充的是,md5/sha1哈希太长,无法放入php整数中。调用hexdec时,您已经丢失了字节。事实上,我担心由于这个原因,取模会带来麻烦。@YuriKolovsky当然不一定是唯一的。唯一的问题是碰撞的可能性有多大。也就是说,如果您需要,我认为您应该使用mt_rand
,如果发生冲突,请重复。我不知道如何使用您的第二个解决方案来获取数字哈希,您可以详细说明一下吗?它不是哈希,但您可以使用例如河豚来将您的ID覆盖为唯一的“随机”数字。然后,用户无法计算“ID+1”。最后,你可以使用它作为代理方法e:internal你的应用程序使用“ID:1,2,3,…”,但你提供加密的数字给你的用户。许多大公司都这样做
function numcrypt($a)
{
return ($a * 15) % 26;
}
function unnumcrypt($a)
{
return ($a * 7) % 26;
}
numcrypt(1) : 15
numcrypt(2) : 4
numcrypt(3) : 19
unnumcrypt(15) : 1
unnumcrypt(4) : 2
unnumcrypt(19) : 3
$id = unnumcrypt($_GET('userid'));
... do something with the ID ...
echo '<a href="do.php?userid='. numcrypt($id) . '"> go </a>';
return hexdec(crc32("Hello World"));