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

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

例如:

return md5(234); // returns 098f6bcd4621d373cade4e832627b4f6
但我需要

return numhash(234); // returns 00978902923102372190 
(20 numbers only)
这里的问题是,我希望散列是短的

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

  • 这让一些人看起来更重要
  • 这将显示我不想显示的应用程序信息
  • 要修复点1和2,我需要“隐藏”数字,同时保持其唯一性

    编辑+解决方案: 基于代码的数字哈希函数


    首先,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"));