php:仅数字哈希?
在 php 中有没有办法从字符串中给出唯一的散列,但散列仅由数字组成?
In php is there a way to give a unique hash from a string, but that the hash was made up from numbers only?
示例:
return md5(234); // returns 098f6bcd4621d373cade4e832627b4f6
但我需要
return numhash(234); // returns 00978902923102372190
(20 numbers only)
这里的问题是我希望散列很短.
the problem here is that I want the hashing to be short.
好的,让我在这里解释一下背景故事.我有一个网站,每个注册人都有一个 ID,我还需要一个 ID 供该人使用和交换(因此不能太长),到目前为止 ID 编号为 00001、00002、00003 等...
edit: OK let me explain the back story here. I have a site that has a ID for every registered person, also I need a ID for the person to use and exchange (hence it can't be too long), so far the ID numbering has been 00001, 00002, 00003 etc...
- 这会让一些人看起来更重要
- 这会显示我不想透露的应用程序信息.
要修复第 1 点和第 2 点,我需要隐藏"该数字,同时保持其唯一性.
To fix point 1 and 2 I need to "hide" the number while keeping it unique.
基于https://stackoverflow.com/a/23679870/175071的代码的数字哈希函数p>
Numeric hash function based on the code by https://stackoverflow.com/a/23679870/175071
/**
* Return a number only hash
* https://stackoverflow.com/a/23679870/175071
* @param $str
* @param null $len
* @return number
*/
public function numHash($str, $len=null)
{
$binhash = md5($str, true);
$numhash = unpack('N2', $binhash);
$hash = $numhash[1] . $numhash[2];
if($len && is_int($len)) {
$hash = substr($hash, 0, $len);
}
return $hash;
}
// Usage
numHash(234, 20); // always returns 6814430791721596451
推荐答案
有一些很好的答案,但对我来说,这些方法似乎很愚蠢.
他们首先强制 php 创建一个 Hex 数字,然后将其转换回 (hexdec
) 在 BigInteger 中,然后将其缩减为多个字母......这是很多工作!
There are some good answers but for me the approaches seem silly.
They first force php to create a Hex number, then convert this back (hexdec
) in a BigInteger and then cut it down to a number of letters... this is much work!
为什么不呢
将哈希读取为二进制:
$binhash = md5('[input value]', true);
然后使用
$numhash = unpack('N2', $binhash); //- or 'V2' for little endian
将其转换为两个 INT
($numhash
是两个元素的数组).现在您可以简单地使用 AND
操作来减少数字中的位数.例如:
to cast this as two INT
s ($numhash
is an array of two elements). Now you can reduce the number of bits in the number simply using an AND
operation. e.g:
$result = $numhash[1] & 0x000FFFFF; //- to get numbers between 0 and 1048575
但要注意碰撞!减少数字意味着增加两个不同[输入值]具有相同输出的概率.
But be warned of collisions! Reducing the number means increasing the probability of two different [input value] with the same output.
我认为更好的方法是使用带有 Bijectiv 函数的ID-Crypting".所以不会发生碰撞!对于最简单的类型,只需使用 Affine_cipher
I think that the much better way would be the use of "ID-Crypting" with a Bijectiv function. So no collisions could happen! For the simplest kind just use an Affine_cipher
最大输入值范围为 0 到 25 的示例:
Example with max input value range from 0 to 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
例如
$id = unnumcrypt($_GET('userid'));
... do something with the ID ...
echo '<a href="do.php?userid='. numcrypt($id) . '"> go </a>';
当然这是不安全的,但如果没有人知道用于加密的方法,那么就没有安全原因,那么这种方式更快且碰撞安全.
of course this is not secure, but if no one knows the method used for your encryption then there are no security reasons then this way is faster and collision safe.
相关文章