php:仅数字哈希?

发布于 2024-09-12 03:37:25 字数 1142 浏览 10 评论 0原文

在 php 中,有没有一种方法可以从字符串中给出唯一的哈希值,但该哈希值仅由数字组成?

示例:

return md5(234); // returns 098f6bcd4621d373cade4e832627b4f6

但我需要的

return numhash(234); // returns 00978902923102372190 
(20 numbers only)

问题是我希望哈希值较短。

编辑: 好吧,让我解释一下这里的背景故事。 我有一个网站,每个注册者都有一个ID,我也需要一个ID供该人使用和交换(因此不能太长),到目前为止ID编号是00001、00002、00003等。 ..

  1. 这让一些人看起来更重要,
  2. 这揭示了我不想透露的应用程序信息。

为了修复第 1 点和第 2 点,我需要“隐藏”该数字,同时保持其唯一性。

编辑+解决方案:

基于 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

In php is there a way to give a unique hash from a string, but that the hash was made up from numbers only?

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...

  1. this makes some people look more important
  2. 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.

Edit + SOLUTION:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

国产ˉ祖宗 2024-09-19 03:37:33

只需使用下面我的手动哈希方法:

将数字(例如 6 位数字)除以素数 3、5、7。

并获取小数点后的前 6 个值作为要使用的 ID。在实际创建ID之前检查唯一性,如果存在冲突,则将最后一位数字增加+1,直到不冲突。
例如 123456 给你 771428
123457 给你 780952
123458 给你 790476。

Just use my manual hash method below:

Divide the number (e.g. 6 digit) by prime values, 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.

栀子花开つ 2024-09-19 03:37:32

首先,md5 基本上已被泄露,因此除了非关键哈希之外,您不应该将其用于任何其他用途。
PHP5有hash()函数,参见http: //www.php.net/manual/en/function.hash.php

将最后一个参数设置为 true 将为您提供一串二进制数据。或者,您可以将生成的十六进制散列拆分为 2 个字符的片段,并将它们分别转换为整数,但我预计这会慢得多。

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.

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.

冰葑 2024-09-19 03:37:32

尝试 hashid
它将数字哈希为您可以定义的格式。格式包括有多少个字符,以及包含哪些字符。
示例:
$hashids->编码(1);
将返回“28630”取决于您的格式,

Try hashid.
It hash a number into format you can define. The formats include how many character, and what character included.
Example:
$hashids->encode(1);
Will return "28630" depends on your format,

寒冷纷飞旳雪 2024-09-19 03:37:31

有一些很好的答案,但对我来说这些方法似乎很愚蠢。
他们首先强制 php 创建一个十六进制数字,然后将其转换回 BigInteger(hexdec),然后将其缩减为多个字母......这是一项艰巨的工作!

相反,为什么不将

哈希读取为二进制:

$binhash = md5('[input value]', true);

然后使用

$numhash = unpack('N2', $binhash); //- or 'V2' for little endian

将其转换为两个 INT$numhash 是两个元素的数组)。现在,您只需使用 AND 运算即可减少数字中的位数。例如:

$result = $numhash[1] & 0x000FFFFF; //- to get numbers between 0 and 1048575

但要注意碰撞!减少数量意味着增加两个不同[输入值]具有相同输出的概率。

我认为更好的方法是将“ID-Crypting”与 Bijectiv 函数一起使用。所以不会发生碰撞!对于最简单的类型,只需使用 Affine_cipher

示例,最大输入值范围为 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

例如

$id = unnumcrypt($_GET('userid'));

... do something with the ID ...

echo '<a href="do.php?userid='. numcrypt($id) . '"> go </a>';

,当然这不安全,但如果没有人知道您的加密所使用的方法,那么就没有安全原因,那么这种方式更快并且碰撞安全。

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!

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 ($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.

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

Example with max input value range from 0 to 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.

何以笙箫默 2024-09-19 03:37:31

切断哈希的问题是冲突,为了避免它尝试:

return  hexdec(crc32("Hello World"));

crc32()

生成 32 位长度的循环冗余校验和多项式
海峡的这通常用于验证数据的完整性
正在传输。

这给了我们一个 32 位整数,在 32 位安装中为负数,在 64 位安装中为正数。该整数可以像 ID 一样存储在数据库中。这不会有冲突问题,因为一旦您使用 hexdec() 函数将其转换为十进制,它就适合 32 位变量。

The problem of cut off the hash are the collisions, to avoid it try:

return  hexdec(crc32("Hello World"));

The 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.

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.

小ぇ时光︴ 2024-09-19 03:37:30

您可以尝试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 

话虽如此,crc 应该用于验证数据的完整性

You can try crc32(). See the documentation at: 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, crc should only be used to validate the integrity of data.

红墙和绿瓦 2024-09-19 03:37:29

PHP 中的 MD5 或 SHA1 哈希值返回一个十六进制数,因此您需要做的就是转换基数。 PHP 有一个函数可以为您执行此操作:

$bignum = hexdec( md5("test") );

$bignum = hexdec( sha1("test") );

进制手册

PHP十六 如果您想要一个有限的大小数字,则可以使用模除法将其放入您想要的范围内。

$smallnum = $bignum % [put your upper bound here]

编辑

正如Artefacto在评论中指出的,使用这种方法将导致数字超出PHP中整数的最大大小,并且模除后的结果将始终为0。但是,取子字符串包含前 16 个字符的哈希值不存在此问题。用于计算初始大数的修订版本:

$bignum = hexdec( substr(sha1("test"), 0, 15) );

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:

$bignum = hexdec( md5("test") );

or

$bignum = hexdec( sha1("test") );

PHP Manual for hexdec

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:

$bignum = hexdec( substr(sha1("test"), 0, 15) );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文