2009-09-14 218 views
14

在我的用户数据库表中,我将用户的电子邮件地址的MD5散列作为id。将MD5散列表示为整数

实施例:email([email protected]) = id(d41d8cd98f00b204e9800998ecf8427e)

不幸的是,我要表示的ID作为整数值现在 - 为了能够使用的API,其中ID只能是整数。

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

我的想法而已:

  1. 的MD5哈希
  2. 替换MD5哈希值的每一个字符convert_uuencode()convert_uudecode()ord()

哪种方法更好?你知道更好的方法来做到这一点吗?

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

+1

你有没有其他的,可能是实习生,值识别您的用户?那么,你的用户表至少应该有一个PK。 – Malax 2009-09-14 17:10:57

+0

@Malax:是的,主键是包含MD5哈希的id字段。这是一个不好的解决方案? – caw 2009-09-14 17:24:16

+3

使用MD5散列作为用户表的主键通常不是一个好主意。自动递增/串行整数ID是4-8字节。一个md5散列是32个字节。整数值比较(例如每次加入该表或从中选择一行)将比比较32字节字符串快许多倍,并且整数值将需要较少的存储空间。真的...如果你想使用字符串值,为什么不使用电子邮件地址本身?在大多数情况下,这将是32个字节或更少。 – 2009-09-14 17:50:16

回答

16

要小心。将MD5转换为整数将需要支持大(128位)整数。机会是你使用的API只支持32位整数 - 或者更糟的是,可能是在处理浮点数。无论哪种方式,您的身份证将会消失。如果是这种情况,只是任意分配第二个ID是处理事情的好方法,而不是试图将MD5转换为整数。

但是,如果你是肯定该API可以处理任意大的整数没有麻烦,你可以将MD5从十六进制转换为整数。然而,PHP很可能不支持这种内置,因为它会尝试将其表示为32位整数或浮点;您可能需要使用PHP GMP library

+3

+1,暗示即使将整个字节作为整数使用,结果值对于API来说可能太大。你应该为你的“电子邮件地址到整数”问题找到另一个解决方案。 – Malax 2009-09-14 17:09:07

+0

非常感谢!这会比我的两个想法更好吗? $ id_integer = base_convert($ id_string,16,10); – caw 2009-09-14 17:26:36

+0

阅读base_convert文档中的警告(http://www.php.net/manual/en/function.base-convert.php) - 它不适合大数目。而MD5是非常大的数字。您必须使用bigint库,并且您访问的API也必须这样做 - 但我怀疑它确实如此。只需添加另一列,并为每个用户分配任意的ID,就会容易得多。 – bdonlan 2009-09-14 22:02:29

1

您可以使用hexdec解析十六进制字符串并将该数字存储在数据库中。

+1

这是否可以处理160位整数而不需要进行调整? – bdonlan 2009-09-14 16:59:11

+2

答案:不,它会转换为浮动,根据文档。因此,您将丢失大约120位数据,并且以后将无法恢复原始MD5。 – bdonlan 2009-09-14 16:59:43

+2

你说得对,MD5总和太大,无​​法存储为32位整数。忽略我的答案。 ;-) – Malax 2009-09-14 17:03:17

1

难道你只是添加另一个字段是一个自动增量int字段?

1

为什么ord()? md5生成正常的16字节值,以十六进制显示给您,以提高可读性。所以你不能将16字节的值转换为4或8字节的整数而不会丢失。你必须改变你的算法的一部分来使用它作为id。

+0

MD5产生一个20字节的值。 – bdonlan 2009-09-14 17:03:40

+2

嗯...可以是我完全愚蠢的,但... 佛瑞德@ fred的桌面:〜$的md5sum citycode.sql 734e4d6f039a81c8a196db588e1cb002 citycode.sql 73 4E 4D 6F 03 9A 81 C8 A196分贝58 8E 1C B0 02 这里marco92w(问题所有者)值 D4 1D 8C D9 8F 00 B2 04 E9 80 09 98 EC F8 42 7E 什么是错跟我?另外四个字节在哪里? – 2009-09-14 17:28:00

+0

@bdonlan:不,128位等于16个字节,不是吗? – caw 2009-09-14 17:31:52

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('[email protected]'); 
echo $md5 . '<br />'; // 23463b99b62a72f26ed677cc556c44e8 
$dec = md5_hex_to_dec($md5); 
echo $dec . '<br />'; // 0903015257466342942628374306682186817640 
$hex = md5_dec_to_hex($dec); 
echo $hex;    // 23463b99b62a72f26ed677cc556c44e8 

当然,你必须要caref UL使用任何字符串,如确保使用它们只能作为字符串类型,以避免丢失前导零,确保字符串是正确的长度等

+0

非常感谢。这是如何工作的。但现在我可以看到所有其他人想说什么:新的整数很长。而领先的零也是一个问题。 – caw 2009-09-15 10:44:12

+0

很高兴提供帮助。请记住,十进制数字字符串和十六进制数字字符串(md5字符串)在数学上不是相等的;它们仅仅是由这些伴侣功能产生的彼此“翻译”,并转化为它们各自的数字符号集合。 – GZipp 2009-09-15 16:54:20

1

怎么样:

$浮= hexdec(MD5(”串'));

$ INT =(整数)(SUBSTR(hexdec(MD5( '字符串')),0,9)* 100000000);

确定碰撞的可能性更大,但仍然可以使用而不是使用散列在数据库中?

欢呼声,

/马辛

+0

这一个更好:sprintf(“%u”,crc32(md5('string'))); – Marcin 2010-01-03 17:21:42

+0

well lemme计算32 * 16位......你需要64bytes。不知道任何浮动或双倍的长期;)你的数字将失去精度通过截断或四舍五入 – 2010-12-12 13:40:58

0

使用的电子邮件地址作为一个共享文件夹为空,临时文件的文件名,如/var/myprocess/[email protected]

然后,在文件名称上调用ftok。 ftok会返回一个唯一的整数ID。

虽然它不能保证是唯一的,但它可能足以满足您的API。

6

对于32位缩合,可以通过选择MD5散列的4个十六进制对(8个字符)(每对代表一个字节),然后将其转换为intval()来实现简单解决方案。

对于32位无符号诠释:

$inthash = intval(substr(md5($str), 0, 8), 16); 

对于正值只有32位有符号诠释的:

$inthash = intval(substr(md5($str), 0, 8), 16) >> 1; 

这很可能只对工作价值高达64如文档中所述,用于大多数现代系统的位(8字节或16个字符)。

在可以容纳64位整数,消耗了整个128位的MD5哈希值作为2个整数可能看起来像一个分裂策略的系统:

$hash = md5($str); 
$inthash1 = intval(substr($hash, 0, 16), 16); 
$inthash2 = intval(substr($hash, 16, 16), 16);