【问题标题】:Convert MD5 to base62 for URL将 URL 的 MD5 转换为 base62
【发布时间】:2009-12-10 10:49:35
【问题描述】:

我有一个脚本可以转换为 base 62 (A-Za-z0-9),但是如何从 MD5 中获取数字?

我在很多地方都读到过,因为 MD5 中的数字大于 php 可以处理的整数,所以这将是不准确的...因为无论如何我想要一个短 URL 并且不打算使用整个哈希,也许只有 8 个字符....

所以我的问题是如何获得一个 MD5 哈希的部分数字?

另外,只使用部分 MD5 哈希值是不是一个坏主意?

【问题讨论】:

  • md5 哈希不是数字,那么“部分数字”是什么意思?
  • md5 是我认为以 base36 编码表示的数字...
  • 你说对了一半,md5 哈希是一个以 16 为底的十六进制数字 (a-f0-9)。
  • 一个 md5 散列一个 128 位的数字。通常的表示是十六进制的,但这不是必需的。
  • 好的,那么如何将十六进制转换为数字?我知道这个数字对于 php 来说太大了,所以我应该使用 substr 和 hexdec 吗?

标签: php md5 base62


【解决方案1】:

我将在这里提出不同的建议。由于您只对使用 md5 哈希的十进制块感兴趣,为什么不使用任何其他短数字哈希,例如 CRC32Adler?这是一个例子:

$hash = sprintf('%u', crc32('your string here'));

这将产生一个 8 位数的字符串哈希。

编辑:我想我误解了你,here are some functions that provide conversions to and from bases up to 62

编辑(再次):要使用任意长度的数字,您必须使用 bc_math 或 GMP 扩展,here is a function that uses the bc_math extension and can also convert from base 2 up to base 62。你应该这样使用它:

echo bc_base_convert(md5('your url here'), 16, 62); // public base 62 hash

反之:

echo bc_base_convert('base 62 encoded value here', 62, 16); // private md5 hash

希望对您有所帮助。 =)

【讨论】:

  • 是否可以计算出散列中的内容?只是我在想,如果我只显示哈希的一部分,它一定会使它更难计算它是如何生成的......对吗?
  • 是的,但它不会是真正意义上的哈希,而且更可能发生冲突。
【解决方案2】:

如果可能的话,我建议不要对您的网址使用哈希。最终你会遇到冲突......特别是如果你截断哈希。如果您继续实施一个基于 id 的系统,其中每个项目都有一个唯一的 ID,那么麻烦就会少得多。第一项将是1,第二项将是2,等等---如果您使用的是MySQL,只需输入一个自动增量列。

制作一个简短的 id:

//the basic example
$sid = base_convert($id, 10, 36);

//if you're going to be needing 64 bit numbers converted 
//on a 32 bit machine, use this instead
$sid = gmp_strval(gmp_init($id, 10), 36);

将短 id 转换为 base-10 id:

//the basic example
$id = base_convert($id, 36, 10);

//if you're going to be needing 64 bit numbers
//on a 32 bit machine, use this instead
$id = gmp_strval(gmp_init($shortid, 36));

希望这会有所帮助!

如果你真的想要 base 62(这不能用 gmpbase_convert 完成),请查看: http://snipplr.com/view/22246/base62-encode--decode/

【讨论】:

  • 对不起,也许我没有让自己足够清楚,md5 没有起到 id 的作用......只是作为阻止用户猜测下一个 url 的一种方式......所以 url 是 id =1&md5=dsf213sfe.还是谢谢你
【解决方案3】:

你可以这样:(不是所有的步骤都在php中,我用了很久了。)

只使用 md5 的几个位没有风险。所有这些变化都是碰撞的危险。

【讨论】:

    【解决方案4】:

    实际上有一个您可以提取的 Java 实现。这是一个名为 Pulse 的开源 CMS 解决方案。

    在此处查找toBase62()fromBase62() 的代码。

    http://pulse.torweg.org/javadoc/src-html/org/torweg/pulse/util/StringUtils.java.html

    StringUtils 中的唯一依赖项是 LifeCycle 类,它提供了一种方法来获取字符串的加盐哈希,您甚至可以将其全部省略或将方法复制到您的副本 StringUtils。瞧。

    【讨论】:

      【解决方案5】:

      你可以这样做,

      $hash = md5("The data to be hashed", true);
      $ints = unpack("L*num", $hash);
      
      $hash_str = base62($ints['num1']) . base62($ints['num2']) . base62($ints['num3']) . base62($ints['num4'])
      

      【讨论】:

        【解决方案6】:

        从 PHP 5.3.2 开始,GMP 支持最多 62 个基数(以前只有 36 个),所以 brianreavis 的建议非常接近。我认为您的问题的最简单答案是:

        function base62hash($source, $chars = 22) {
          return substr(gmp_strval(gmp_init(md5($source), 16), 62), 0, $chars);
        }
        

        从 base-16 转换为 base-62 显然具有空间优势。一个普通的 128 位 MD5 哈希是 32 个十六进制字符,但在 base-62 中只有 22 个。如果您将哈希存储在数据库中,您可以将它们转换为原始二进制文件并节省更多空间(16 个字节用于MD5)。

        由于生成的哈希只是一个字符串表示,如果你只想要它的一点,你可以只使用 substr(就像函数一样)。

        【讨论】:

          【解决方案7】:

          您可以尝试 base62x 以获得安全且兼容的编码表示。

          Here is for more information about base62x,或者只是-base62x in -NatureDNS

          shell> ./base62x -n 16 -enc 16AF 
          1Ql
          shell> ./base62x -n 16 -dec 1Ql 
          16AF
          
          shell> ./base62x 
          Usage: ./base62x [-v] [-n <2|8|10|16|32>] <-enc|dec> string 
          Version: 0.60 
          

          【讨论】:

            【解决方案8】:

            这是一个将 MD5 字符串转换为 Base62 字符串的开源 Java 库 https://github.com/inder123/base62

            Md5ToBase62.toBase62("9e107d9d372bb6826bd81d3542a419d6") ==&gt; cbIKGiMVkLFTeenAa5kgO4

            Md5ToBase62.fromBase62("4KfZYA1udiGCjCEFC0l") ==&gt; 0000bdd3bb56865852a632deadbc62fc

            转换是双向的,所以如果你把它转换回md5,你会得到原来的md5:

            Md5ToBase62.fromBase62(Md5ToBase62.toBase62("9e107d9d372bb6826bd81d3542a419d6")) ==&gt; 9e107d9d372bb6826bd81d3542a419d6

            Md5ToBase62.toBase62(Md5ToBase62.fromBase62("cbIKGiMVkLFTeenAa5kgO4")) . ==&gt; cbIKGiMVkLFTeenAa5kgO4

            ```

            【讨论】:

              【解决方案9】:

              您可以使用带有-_ 的略微修改的Base 64,而不是+/

              function base64_url_encode($str) {
                  return strtr(base64_encode($str), array('+'=>'-', '/'=>'_'));
              }
              function base64_url_decode($str) {
                  return base64_decode(strtr($str, array('-'=>'+', '_'=>'/')));
              }
              

              此外,您可以删除尾随填充 = 字符。

              若要获取原始 MD5 值(二进制字符串),请将第二个参数(手册中名为 $raw_output)设置为 true

              $raw_md5 = md5($str, true);
              
              猜你喜欢
              • 2023-04-08
              • 2013-08-04
              • 2012-03-28
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多