php:数字只有哈希?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3379471/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
php: number only hash?
提问by Timo Huovinen
In php is there a way to give a unique hash from a string, but that the hash was made up from numbers only?
在 php 中,有没有办法从字符串中给出唯一的散列,但散列仅由数字组成?
example:
例子:
return md5(234); // returns 098f6bcd4621d373cade4e832627b4f6
but I need
但是我需要
return numhash(234); // returns 00978902923102372190
(20 numbers only)
the problem here is that I want the hashing to be short.
这里的问题是我希望散列很短。
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...
编辑:好的,让我在这里解释一下背景故事。我有一个网站,每个注册人都有一个 ID,我还需要一个 ID 供该人使用和交换(因此不能太长),到目前为止 ID 编号为 00001、00002、00003 等。 ..
- this makes some people look more important
- this reveals application info that I don't want to reveal.
- 这让一些人看起来更重要
- 这会显示我不想透露的应用程序信息。
To fix point 1 and 2 I need to "hide" the number while keeping it unique.
要修复第 1 点和第 2 点,我需要“隐藏”数字,同时保持它的唯一性。
Edit + SOLUTION:
编辑+解决方案:
Numeric hash function based on the code by https://stackoverflow.com/a/23679870/175071
基于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
采纳答案by Thomas
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!
有一些很好的答案,但对我来说这些方法似乎很愚蠢。
他们首先强制 php 创建一个十六进制数,然后将其转换回 ( hexdec) 在 BigInteger 中,然后将其缩减为多个字母......这是很多工作!
Instead why not
相反为什么不
Read the hash as binary:
将哈希读取为二进制:
$binhash = md5('[input value]', true);
then using
然后使用
$numhash = unpack('N2', $binhash); //- or 'V2' for little endian
to cast this as two INTs ($numhashis an array of two elements). Now you can reduce the number of bits in the number simply using an ANDoperation. e.g:
将其转换为两个INTs($numhash是一个包含两个元素的数组)。现在您只需使用一个AND操作就可以减少数字中的位数。例如:
$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.
但要注意碰撞!减少数字意味着增加两个不同[输入值]具有相同输出的概率。
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
我认为更好的方法是使用带有 Bijectiv 函数的“ID-Crypting”。所以不会发生碰撞!对于最简单的类型,只需使用Affine_cipher
Example with max input value range from 0 to 25:
最大输入值范围从 0 到 25 的示例:
function numcrypt($a)
{
return ($a * 15) % 26;
}
function unnumcrypt($a)
{
return ($a * 7) % 26;
}
Output:
输出:
numcrypt(1) : 15
numcrypt(2) : 4
numcrypt(3) : 19
unnumcrypt(15) : 1
unnumcrypt(4) : 2
unnumcrypt(19) : 3
e.g.
例如
$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.
当然这并不安全,但是如果没有人知道用于加密的方法,那么就没有安全原因,那么这种方式更快且碰撞安全。
回答by derekerdmann
An MD5 or SHA1 hash in PHP returns a hexadecimal number, so all you need to do is convert bases. PHP has a function that can do this for you:
PHP 中的 MD5 或 SHA1 哈希返回一个十六进制数,因此您需要做的就是转换基数。PHP 有一个函数可以为您执行此操作:
$bignum = hexdec( md5("test") );
or
或者
$bignum = hexdec( sha1("test") );
Since you want a limited size number, you could then use modular division to put it in a range you want.
由于您想要一个有限的大小数字,因此您可以使用模块化划分将其放在您想要的范围内。
$smallnum = $bignum % [put your upper bound here]
EDIT
编辑
As noted by Artefacto in the comments, using this approach will result in a number beyond the maximum size of an Integer in PHP, and the result after modular division will always be 0. However, taking a substring of the hash that contains the first 16 characters doesn't have this problem. Revised version for calculating the initial large number:
正如 Artefacto 在评论中所指出的,使用这种方法会导致一个数字超出 PHP 中 Integer 的最大大小,并且模除后的结果将始终为 0。但是,取包含前 16 个的哈希子字符串字符没有这个问题。计算初始大数的修订版:
$bignum = hexdec( substr(sha1("test"), 0, 15) );
回答by David Titarenco
You can try crc32(). See the documentation at: http://php.net/manual/en/function.crc32.php
你可以试试crc32()。请参阅以下文档:http: //php.net/manual/en/function.crc32.php
$checksum = crc32("The quick brown fox jumped over the lazy dog.");
printf("%u\n", $checksum); // prints 2191738434
With that said, crcshould onlybe used to validate the integrity of data.
话虽如此,crc应该只用于validate the integrity of data.
回答by Reynel Fals de Pedro
The problem of cut off the hash are the collisions, to avoid it try:
切断散列的问题是冲突,为了避免它,请尝试:
return hexdec(crc32("Hello World"));
The crc32():
的crc32():
Generates the cyclic redundancy checksum polynomial of 32-bit lengths of the str. This is usually used to validate the integrity of data being transmitted.
生成 str 的 32 位长度的循环冗余校验和多项式。这通常用于验证正在传输的数据的完整性。
That give us an integer of 32 bit, negative in 32 bits installation, or positive in the 64 bits. This integer could be store like an ID in a database. This don′t have collision problems, because it fits into 32bits variable, once you convert it to decimal with the hexdec()function.
这给了我们一个 32 位的整数,在 32 位安装中为负数,或在 64 位中为正数。这个整数可以像一个 ID 一样存储在数据库中。这不会有冲突问题,因为它适合 32 位变量,一旦您使用hexdec()函数将其转换为十进制。
回答by tdammers
First of all, md5 is basically compromised, so you shouldn't be using it for anything but non-critical hashing.
PHP5 has the hash()function, see http://www.php.net/manual/en/function.hash.php.
首先,md5 基本上已被破坏,因此除了非关键散列之外,您不应将其用于任何其他用途。PHP5有这个hash()功能,见http://www.php.net/manual/en/function.hash.php。
Setting the last parameter to true will give you a string of binary data. Alternatively, you could split the resulting hexadecimal hash into pieces of 2 characters and convert them to integers individually, but I'd expect that to be much slower.
将最后一个参数设置为 true 将为您提供一串二进制数据。或者,您可以将生成的十六进制散列拆分为 2 个字符的部分,并将它们单独转换为整数,但我希望这会慢得多。
回答by Irfandi D. Vendy
回答by Ben
Just use my manual hash method below:
只需使用我下面的手动哈希方法:
Divide the number (e.g. 6 digit) by prime values, 3,5,7.
将数字(例如 6 位数字)除以质数,3,5,7。
And get the first 6 values that are in the decimal places as the ID to be used. Do a check on uniqueness before actual creation of the ID, if a collision exists, increase the last digit by +1 until a non collision.
E.g. 123456 gives you 771428
123457 gives you 780952
123458 gives you 790476.
并获取小数位中的前 6 个值作为要使用的 ID。在实际创建 ID 之前检查唯一性,如果存在冲突,则将最后一位数字增加 +1,直到不发生冲突。
例如 123456 给你 771428 123457 给你 780952 123458 给你 790476。

