我有一个脚本要转换为base 62(A-Za-z0-9),但如何从MD5中获取数字?
我在很多地方都读到,因为MD5中的数字大于php可以处理的整数,所以它将是不准确的...因为我想要一个简短的URL而不是计划使用整个哈希,也许只有8个字符......
所以我的问题是如何获得MD5哈希值的一部分?
仅使用部分MD5哈希是一个坏主意吗?
答案 0 :(得分:6)
我将在这里建议一个不同的东西..因为你只对使用md5哈希的十进制块感兴趣,为什么不使用任何其他短数字哈希,如CRC32或{{3 }}?这是一个例子:
$hash = sprintf('%u', crc32('your string here'));
这将产生字符串的8位哈希值。
编辑:我想我误解了你,Adler。
编辑(再次):要使用任意长度的数字,您必须使用bc_math或GMP扩展名here are some functions that provide conversions to and from bases up to 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
希望它有所帮助。 =)
答案 1 :(得分:3)
如果可能的话,我建议不要为您的网址使用哈希值。最终你会遇到冲突......特别是如果你正在截断哈希。如果你继续实施一个基于身份的系统,其中每个项目都有一个唯一的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重新设置为基数为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));
希望这有帮助!
如果您真的想要基础62(无法使用gmp
或base_convert
完成),请查看以下内容:
http://snipplr.com/view/22246/base62-encode--decode/
答案 2 :(得分:1)
你可以这样做:(并非所有步骤都在php中,我用了很长时间了。)
创建脚本的md5哈希,如下所示:
$ hash = md5(script,raw_output = true);
将该号码转换为62号。
将字符串截断为您喜欢的长度。
仅使用md5的几个位没有风险。所有这些变化都是碰撞的危险。
答案 3 :(得分:1)
实际上有一个Java实现可以提取。它是一个名为Pulse的开源CMS解决方案。
点击此处查看toBase62()
和fromBase62()
的代码。
http://pulse.torweg.org/javadoc/src-html/org/torweg/pulse/util/StringUtils.java.html
StringUtils
中唯一的依赖项是LifeCycle类,它提供了一种获取字符串的盐渍哈希的方法,您甚至可以将其全部省略,或者只是将方法复制到您的副本StringUtils
。瞧。
答案 4 :(得分:0)
您可以使用略有修改的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);
答案 5 :(得分:0)
你可以这样做,
$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 :(得分:0)
从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 :(得分:0)
您可以尝试使用base62x来获得安全且兼容的编码表示。
Here is for more information about 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
答案 8 :(得分:0)
这是一个开源Java库,可将MD5字符串转换为Base62字符串 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
```