将MD5哈希表示为整数

时间:2009-09-14 16:54:34

标签: php string hash integer md5

在我的用户数据库表中,我将用户电子邮件地址的MD5哈希值作为id。

示例:email(example@example.org) = id(d41d8cd98f00b204e9800998ecf8427e)

不幸的是,我现在必须将id表示为整数值 - 以便能够使用其中id只能是整数的API。

现在我正在寻找一种方法将id编码为一个整数,以便在接收时再次发送解码。我怎么能这样做?

到目前为止我的想法:

    MDL哈希
  1. convert_uuencode()convert_uudecode()
  2. 用其ord()
  3. 替换MD5哈希的每个字符

    哪种方法更好?你知道更好的方法吗?

    我希望你能帮助我。非常感谢你提前!

8 个答案:

答案 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。