在我的用户数据库表中,我将用户电子邮件地址的MD5哈希值作为id。
示例:email(example@example.org) = id(d41d8cd98f00b204e9800998ecf8427e)
不幸的是,我现在必须将id表示为整数值 - 以便能够使用其中id只能是整数的API。
现在我正在寻找一种方法将id编码为一个整数,以便在接收时再次发送解码。我怎么能这样做?
到目前为止我的想法:
convert_uuencode()
和convert_uudecode()
ord()
值哪种方法更好?你知道更好的方法吗?
我希望你能帮助我。非常感谢你提前!
答案 0 :(得分:17)
小心点。将MD5转换为整数将需要支持大(128位)整数。有可能你正在使用的API只支持32位整数 - 或者更糟糕的是,可能正在处理浮点数。无论哪种方式,你的身份证都会受到影响。如果是这种情况,只需任意分配第二个ID就可以比处理将MD5转换为整数更好的处理方式。
但是,如果您确定 API可以毫无问题地处理任意大整数,则可以将MD5从十六进制转换为整数。 PHP很可能不支持这种内置,因为它会尝试将其表示为32位整数或浮点数;你可能需要使用PHP GMP library来获取它。
答案 1 :(得分:10)
其他人说,有充分的理由以不同的方式做到这一点。
但是如果你想要做的是将md5哈希转换为字符串 十进制数字(这是我认为你真正的意思 “由整数表示”,因为md5已经是字符串形式的整数), 并将其转换回相同的md5字符串:
function md5_hex_to_dec($hex_str)
{
$arr = str_split($hex_str, 4);
foreach ($arr as $grp) {
$dec[] = str_pad(hexdec($grp), 5, '0', STR_PAD_LEFT);
}
return implode('', $dec);
}
function md5_dec_to_hex($dec_str)
{
$arr = str_split($dec_str, 5);
foreach ($arr as $grp) {
$hex[] = str_pad(dechex($grp), 4, '0', STR_PAD_LEFT);
}
return implode('', $hex);
}
演示:
$md5 = md5('example@example.com');
echo $md5 . '<br />'; // 23463b99b62a72f26ed677cc556c44e8
$dec = md5_hex_to_dec($md5);
echo $dec . '<br />'; // 0903015257466342942628374306682186817640
$hex = md5_dec_to_hex($dec);
echo $hex; // 23463b99b62a72f26ed677cc556c44e8
当然,您必须小心使用任一字符串,例如确保仅将它们用作字符串类型以避免丢失前导零,确保字符串是正确的长度等。
答案 2 :(得分:7)
对于32位压缩,可以通过选择MD5哈希的4个十六进制对(8个字符)来实现一个简单的解决方案,其中每对代表一个字节,然后用intval()
转换它。
对于无符号的32位Int:
$inthash = intval(substr(md5($str), 0, 8), 16);
仅对有符号的32位Int:
的正值$inthash = intval(substr(md5($str), 0, 8), 16) >> 1;
对于大多数现代系统,这可能仅适用于最多64位(8字节或16个字符)的值,如文档中所述。
在一个可以容纳64位Ints的系统上,一个将整个128位MD5哈希消耗为2 Ints的分裂策略可能如下所示:
$hash = md5($str);
$inthash1 = intval(substr($hash, 0, 16), 16);
$inthash2 = intval(substr($hash, 16, 16), 16);
答案 3 :(得分:1)
您可以使用hexdec来解析十六进制字符串并将该数字存储在数据库中。
答案 4 :(得分:1)
难道你不能只添加另一个自动增量int字段吗?
答案 5 :(得分:1)
为什么选择ord()? md5产生正常的16字节值,以十六进制显示,以提高可读性。因此,您无法将16字节值转换为4或8字节整数而不会丢失。您必须更改算法的某些部分才能将其用作id。
答案 6 :(得分:1)
怎么样:
$ float = hexdec(md5('string'));
或
$ int =(整数)(substr(hexdec(md5('string')),0,9)* 100000000);
肯定会有更大的碰撞机会但是仍然可以在DB中使用而不是哈希?
欢呼声,
/马尔钦
答案 7 :(得分:0)
使用电子邮件地址作为共享文件夹中空白临时文件的文件名,例如/var/myprocess/example@example.org
然后,在文件名上调用ftok。 ftok将返回唯一的整数ID。
但它不会保证是独一无二的,但它可能足以满足您的API。