2017-02-21 49 views
2

ハッシュテーブルのどこに値を入れたいかに基づいてハッシュキーを生成する関数を作成しようとしています。ハッシュ関数をリバースエンジニアリングする方法

私のハッシュ関数は(a + b * (key)) % c = hash valueです。私はSOにこれにsimilar questionを見てきた、と私が試したことはdb * (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

あなたは[Perfect Hash Function](https://en.wikipedia.org/wiki/Perfect_hash_function)を読んでみたいと思います –

+0

私はキーとハッシュ値の間に1対1の関係はないと知っていますが、目的のハッシュ値を生成する無限の数の鍵から1つを取得します。たとえば、正しいハッシュ値が得られるまで、0以上の値を繰り返してbruteを強制することができます。 –

答えて

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()'を使用する必要があります。新しいBigInteger()は使用しないでください。最後に、乗数の逆数は定数でなければならず、効率のために 'int'算術演算として実行されます:' return(h-a)* B_INV; ' – erickson

+0

@ericksonあなたの提案をテストしただけで動作します。ちょうど興味深い、 'B_INV'は何を指していますか? –

+1

@Jedi_Maseter_Sam 'B_INV'は' b'の乗法逆数であり、モジュロ 'c'です。私は 'c'が2^32であると仮定していますが、そうでなければ' int'算術オーバーフローに頼るのではなく、余分な演算を1つだけ必要とします。 'b'と' B_INV'を乗算すると1になります。 'B_INV'を' BigInteger bb = BigInteger.valueOf(b)、bc = BigInteger.valueOf(c);}として計算することができます。 int B_INV = bb.modInverse(bc).intValue(); 'プログラムの起動時に、または関連するクラスが初期化されたときにこれを行います。その後、不要な 'BigInteger'費用を節約できます。 – erickson

関連する問題