このインタビューの質問をされました。それに対する正しい答えが何であるかはわかりません(および答えの背後にある理由):
sin(x) は良いハッシュ関数ですか?
つまりsin()
、次の理由により、これは適切なハッシュ関数ではありません。
x
の人にとってはそれ自体に勝るものはありませんx
. キーとキーのハッシュの間に一見明らかな関係があってはなりません。sin()
、別のコンパイラや別の種類の CPU/コンピューターでは機能しない可能性があります。sin()
単純な整数演算関数よりもはるかに遅い場合があります。あまり。
注意すべきもう1つのポイント:
ハッシュ関数としてのsine(x)の場合-指定された近距離のキーにも近距離のハッシュ値が含まれるため、望ましくありません。優れたハッシュ関数は、キーの性質に関係なく、ハッシュ値を均等に分散します。
数学的知識に基づく:
Sine(x) は周期的であるため、x の異なる値から同じ数に到達するため、Sine(x) はハッシュ関数としてはひどいものになります。これは、複数の値がまったく同じポイントにハッシュされるためです。**戻り値には 0 から pi までの値が無限にありますが、それを超えると値が繰り返されます。したがって、0 & pi & 2*pi はすべて同じポイントにハッシュされます。
増分を十分に小さくして、Sine(x) に x^2 などを掛けることができれば、せいぜい平凡なものになりますが、そうする場合は、単に x^2 を使用しないでください。とにかく、周期関数を一緒に捨てます。
**無限: 数えたくないほど大きな数。
注: Sine(x) の値は小さく、丸め誤差の影響を受ける可能性があります。
注: 正弦関数から取得した値は、整数で乗算してから、値を配列オフセットなどとして使用できるように、変更するか、下限または上限を取得する必要があります。
sin(x)
は360度ごとに繰り返される三角関数であるため、ハッシュが頻繁に繰り返されるため、ハッシュ関数としては不十分になります。
簡単な反論:
sin(0) == sin(360) == sin(720) == sin(..)
これは良いハッシュ関数の特性ではありません。
使用することにしたとしても、sin によって返される値を表すのは困難です。罪関数:
sin x = x - x^3/3! + x^5/5! - ...
これは、浮動小数点の精度の問題により正確に表すことができません。つまり、同じ値に対して 2 つの異なるハッシュが生成される可能性があります。
ハッシュ値は、通常、有用であるためには整数でなければなりません。sin
は整数を生成しないため、適切ではありません。
賢く使えば、sin(x) は優れた暗号化ハッシュ関数になると思います。入力はラジアン単位の自然数である必要があり、決して pi を含んではなりません。任意精度の演算を使用する必要があります。すべての自然数 x (ラジアン) に対して、sin(x) は常に超越無理数であり、同じ正弦を持つ自然数は他にありません。しかし、落とし穴があります。攻撃者は、ハッシュのアークサインを計算することで、入力に関する情報を取得できます。これを防ぐために、小数部分と小数部分の最初の桁のいくつかを無視し、次の n (たとえば 100) 桁のみを保持して、このような攻撃を計算上実行不可能にします。入力を少し変更すると、まったく異なる結果が得られるようです。これは望ましい特性です。関数の結果は統計的にランダムに見えますが、これも良い特性です。私' それが衝突耐性であることを証明する方法がわかりませんが、なぜそれができなかったのかわかりません。また、特定のハッシュになる特定の入力を見つける方法が思いつきません。私は、それが確かに良い地下室であると盲目的に信じるべきだと言っているのではありません。ハッシュ関数。1つになるのは良い候補のように思えます。私たちはそれにチャンスを与え、それが正しいことを証明することに集中すべきです。そして、それは私にとって非常に良いものかもしれません。遅いと言う人へ: はい、そうです。これは、パスワードをハッシュする場合に適しています。ここに、このアイデアの perl コードをいくつか添付します。bash と bc を使用して Linux で実行されます。(bc はコマンドラインの任意精度計算機で、ほとんどのディストリビューションに含まれています) このページに興味があるので、このページで回答を確認します。私はCSの学部生で、もっと学びたいと思っています。
use warnings;
use strict;
my $input='5AFF36B7';#Input for bc (as a hex number)
$input='1'.$input;#put '1' in front of input, so that 0x0 , 0x00 , 0x1 , 0x01 , etc ... ,
#all give different nonzero results
my $a=`bc -l -q <<< "scale=256;obase=16;ibase=16;s($input)"`;#call bc, keep result in $a
#keep only fractional part
$a=~tr/a-zA-Z0-9//cd;#Clean up string, keep only alphanumerics
my @m = $a =~ /./g;#Convert string to array of chars
#PRINT OUTPUT
#We ignore some digits, for security reasons:
#If we don't ignore any of the first digits, an attacker could gain information
#about the input by computing the inverse of sin (the arcsin of the hash)
#By ignoring enough of the first digits, it becomes computationally
#infeasible to compute arcsin
#Also, to avoid problems with roundoff error, we ignore some of the last digits
for (my $c=100;$c<200;$c++){
print $m[$c];
}