如何逆向工程散列函数

问题描述:

我想创建一个函数,根据散列表中我希望值去的地方生成散列键。如何逆向工程散列函数

我的散列函数是(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开始迭代直到获得正确的散列值来蛮力。 –

您正在使用错误的种类。你在做整数划分,但你需要做模块划分。在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