2009-09-14 87 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);