2010-05-04 98 views
3

理論上,散列唯一值會產生一個唯一值嗎?獨特價值哈希值=唯一哈希值?

比方說,我有一個2列數據庫表:id和代碼。 id是一個自動遞增的int,代碼是一個varchar。如果我做...

$code = sha1($id); 

...然後將$ code存儲到與$ id相同的行中。我的代碼欄也是唯一的嗎?

如果我追加當前時間,怎麼辦?例如:

$code = sha1($id . time()); 

謝謝。

+0

不能確定地說話,但我不認爲你的散列可以保證是唯一的,因爲sha1函數有#個輸出。這表明由於有無限數量的潛在密鑰,因此某些不同的密鑰在加密時必須映射到相同的值。我不知道sha1算法的內部,所以我不能告訴你是否有任何數字beteween 1和你的數據庫的數字列max val散列到相同的值。有人可能知道這個問題的答案,但我認爲你會更好地使用不同的方法。 $ code = uniqid()? – 2010-05-04 19:11:37

+0

很感謝。我不知道uniqid(),我一定會看看。 – nebs 2010-05-04 19:16:39

回答

7

一般來說,答案是否定的。這很簡單:SHA-1具有2^160個不同的輸出 - 160位,但還有更多的輸入(例如,有2^320個不同的40字節字符串,並且它們不能全部映射到獨特的輸出)。

給定一個足夠的值子集,答案可能是。它取決於確切的算法和子集的大小:如果可能的輸入數量小於可能的輸出數量,則可能(但不能保證)。在考慮這一點時,記住birthday paradox可能會有所幫助:碰撞概率不會隨輸入數量線性增加。

+0

謝謝。因此獲得唯一值的唯一方法是生成並掃描數據庫以檢查它是否存在(如果是,則重複)?這幾乎是我試圖避免在這裏做的,但我想這是唯一的方法。 – nebs 2010-05-04 19:11:01

+0

不幸的是,如果你想保證一個獨特的價值,沒有別的辦法。這也是爲什麼你不能輕鬆地反轉哈希:我可以告訴你,「1」的SHA-1哈希是「356a192b7913b04c54574d18c28d46e6395428ab」,但是還有許多其他值會生成哈希。 – 2010-05-04 19:14:41

+0

我明白了。事情是我可能不需要產生超過1000個獨特的值。在這種情況下,所有的價值觀都是獨一無二的,是否可以安全地說? – nebs 2010-05-04 19:16:08

-1

這取決於哈希算法。但理論上,除非散列與原始字符串完全相同,否則散列可能不是唯一的。

值的哈希值是原始值的精簡表示。通過刪除信息來創建哈希,您正在丟失使其在域中唯一的部分內容,因此增加了該值不唯一的可能性。唯一保證它是唯一的方法是使用原始值本身,這會破壞哈希的目的。

+0

「保證它是唯一的唯一方法就是使用原始價值本身」 - 顯然不是真的! – 2010-05-04 19:27:46

+0

@馬丁 - 請解釋一下你的意思,_why_是我的陳述不真實? – 2010-05-04 19:33:13

+0

哈希顯然不一定是唯一性的原始字符串來保證。例如,它可能是原始字符串ROT13,並且仍然是唯一的。 – 2010-05-04 19:54:04

0

有兩種不同的值給出相同散列的可能性很小。雖然很小,但不是不可能的。

-1

一個人不得不問這個問題,你爲什麼要這麼做?如果你的數據庫已經提供了一個唯一的標識符,爲什麼你需要生成另一個唯一的標識符?

你也可以考慮在PHP之外,如果你需要的話,許多數據庫引擎會爲你生成UUID樣式的主鍵。

這裏的重點是散列算法,如sha1()不適用於這種類型的工作;它們用於驗證兩個(可能非常長的)字符串輸入是相同的。與類似但不精確的字符串相撞的機會非常遙遠,但與非常不同的字符串碰撞的機會變得更高。

+0

爲什麼downvote? – 2012-08-21 13:47:42