2017-02-21 70 views
2

我想創建一個函數,根據散列表中我希望值去的地方生成散列鍵。如何逆向工程散列函數

我的散列函數是(a + b * (key)) % c = hash value。我見過一個similar question這對SO,和我的嘗試與d更換b * (key),只是這樣做:

private int ReverseModulus(int a, int b, int c, int hashValue) 
{ 
    if(hashValue >= c) 
     return -1; 
    if(a < hashValue) 
     return (hashValue - a)/b; 
    return (c + hashValue - a)/b; 
} 

但似乎大部分時間hashValue != Hash(ReverseModulus(a,b,c, hashValue))

我想知道,如果做法是錯誤的,或者如果有隻是在代碼中的錯誤。

+7

通過設計,哈希是單向的。 – Servy

+0

我想你想讀[完美散列函數(https://en.wikipedia.org/wiki/Perfect_hash_function) –

+0

我知道有沒有鑰匙和哈希值之間的一個一對一的關係,但我只是想從無限數量的密鑰中得到一個將產生所需散列值的密鑰。例如,您可以通過從0開始迭代直到獲得正確的散列值來蠻力。 –

回答

0

您正在使用錯誤的種類。你在做整數劃分,但你需要做模塊劃分。在Java中,您可以使用BigInteger

bh = new BigInteger(hashValue); 
ba = new BigInteger(a); 
bc = new BigInteger(c); 
bn = bh.subtract(ba); 
return bn.modInverse(bc).intValue(); 

和C#推測具有類似的庫函數。

+1

不應該是'bn.multiply(bb.modInverse(bc))'?此外,您需要使用'BigInteger.valueOf()',而不是'new BigInteger()'。最後,乘數的倒數應該是一個常數,並且所有這些都是以'int'算法來計算效率:'return(h - a)* B_INV;' – erickson

+0

@erickson我剛剛測試了您的建議,它的工作原理。只是好奇,B_INV是指什麼? –

+1

@Jedi_Maseter_Sam'B_INV'是'b'的乘法倒數,模'c'。我假設'c'是2^32,但如果不是,你只需要一個額外的操作,而不是依靠'int'算術溢出。如果你乘以'b'和'B_INV',模'c',你會得到1。你可以將'B_INV'計算爲'BigInteger bb = BigInteger.valueOf(b),bc = BigInteger.valueOf(c); int B_INV = bb.modInverse(bc).intValue();'當你的程序啓動時,或者相關的類被初始化時,或者甚至把它計算出來並寫入你的程序中。那麼你可以節省不必要的'BigInteger'開銷。 – erickson