我有一个脚本可以转换为 base 62 (A-Za-z0-9),但是如何从 MD5 中获取一个数字?
我在很多地方都读过,因为 MD5 中的数字大于 php 可以处理的整数,所以这将是不准确的......因为无论如何我想要一个短 URL 并且不打算使用整个哈希,可能只有 8 个字符其中……
所以我的问题是如何获得 MD5 哈希的部分数量?
另外,只使用部分 MD5 哈希是不是一个坏主意?
我将在这里提出不同的建议。由于您只对使用 md5 散列的十进制块感兴趣,为什么不使用任何其他短数字散列,例如CRC32或Adler?这是一个例子:
$hash = sprintf('%u', crc32('your string here'));
这将生成您的字符串的 8 位哈希。
编辑:我想我误解了你,这里有一些函数提供到和从基数到 62 的转换。
编辑(再次):要使用任意长度的数字,您必须使用 bc_math 或 GMP 扩展名,这是一个使用 bc_math 扩展名的函数,也可以从 base 2 转换为 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
希望能帮助到你。=)
如果可能的话,我建议不要为您的 URL 使用哈希。最终你会遇到冲突......特别是如果你截断哈希。如果您继续实施一个基于 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(不能用gmp
or完成base_convert
),请查看:
http ://snipplr.com/view/22246/base62-encode--decode/
你可以这样做:(不是所有的步骤都在php中,我已经用了很长时间了。)
像这样创建脚本的 md5 哈希:
$hash = md5(脚本, raw_output=true);
将该数字转换为基数 62。
请参阅有关PHP 中任意大小数字的基本转换的问题
将字符串截断为您喜欢的长度。
只使用 md5 的几个位没有风险。所有这些变化都是碰撞的危险。
实际上有一个 Java 实现,您可以提取它。这是一个名为 Pulse 的开源 CMS 解决方案。
在此处查找 和 的toBase62()
代码fromBase62()
。
http://pulse.torweg.org/javadoc/src-html/org/torweg/pulse/util/StringUtils.java.html
唯一的依赖StringUtils
是 LifeCycle 类,它提供了一种方法来获取字符串的加盐哈希,您甚至可以将其全部省略,或者只是将方法复制到您的副本StringUtils
。瞧。
你可以做这样的事情,
$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'])
从 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 。
这是一个将 MD5 字符串转换为 Base62 字符串的开源 Java 库 https://github.com/inder123/base62
Md5ToBase62.toBase62("9e107d9d372bb6826bd81d3542a419d6") ==> cbIKGiMVkLFTeenAa5kgO4
Md5ToBase62.fromBase62("4KfZYA1udiGCjCEFC0l") ==> 0000bdd3bb56865852a632deadbc62fc
转换是双向的,因此如果将其转换回 md5,您将获得原始 md5:
Md5ToBase62.fromBase62(Md5ToBase62.toBase62("9e107d9d372bb6826bd81d3542a419d6")) ==> 9e107d9d372bb6826bd81d3542a419d6
Md5ToBase62.toBase62(Md5ToBase62.fromBase62("cbIKGiMVkLFTeenAa5kgO4")) . ==> cbIKGiMVkLFTeenAa5kgO4
```
您可以尝试使用 base62x 来获得安全且兼容的编码表示。
这是有关 base62x 的更多信息,或者只是-base62x
在-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
您可以使用稍加修改的 Base 64 和-
and_
代替+
and /
:
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);