LoginSignup
12
5

More than 5 years have passed since last update.

GetHashCode()にしてやられた件…

Posted at

タイトルそのまんまなんですけど

.NET Framework 3.5ベースのプログラムを、.NET Framework 4.6ベースに移行しようとして、ドツボに嵌りました。

単独のプログラムじゃないんです。
プログラムAがある情報を暗号化して、プログラムBがそのデータを復号化して利用する、と云う動きをします。

そこで、暗号化のためのシードをGetHashCode()で計算していたんですよ。同じ文字列だったら同じHashを返すのがGetHashCode()だと思っていました。何の疑いもなく…
少なくとも、CLR2.0ベースでは問題はなさそうでしたよ。

で、VS2010で作ったプロジェクトをVS2015で読み込んで、対象のフレームワークを4.6に変更して「さぁ実行!」ってさ。

でも、B君が云うには「復号化でけへんのやけど…」

デバッグ実行までして調べた結果、GetHashCode()で計算されるシードが異なっていると云う事が判明。まぁ、シードが違えば復号化はできないっすよね。

しかし、同じ文字列を与えてHashコードが違うって何なんだよー

調べてみたよ

日本語がとても怪しいのですが、msdnのString.GetHashCode()に以下の記述が…

重要

2 つの文字列オブジェクトが等しい場合は、GetHashCodeメソッドと同じ値を返します。 ただし、一意の文字列値ごとに一意のハッシュ コード値はありません。 異なる文字列は、同じハッシュ コードを返すことができます。

ハッシュ コード自体は、安定しているは保証されません。 .NET Framework のバージョンとプラットフォーム (32 ビットおよび 64 ビット) など、.NET Framework の 1 つのバージョンを全体と同じ文字列のハッシュ コードは異なることができます。 場合によっては、アプリケーション ドメインによっても異なることができます。

その結果、ハッシュが作成された、アプリケーション ドメインの外部のコードを使用しないで、コレクション内のキー フィールドとして使用する必要がありますしないと、永続化することはありません。

最後に、暗号強度が高いハッシュする必要がある場合に、暗号ハッシュ関数によって返される値ではなくはハッシュ コードを使用しないでください。 暗号法のハッシュから派生するクラスを使用して、System.Security.Cryptography.HashAlgorithmまたはSystem.Security.Cryptography.KeyedHashAlgorithmクラスです。

ハッシュ コードの詳細については、次を参照してください。Object.GetHashCodeです。

超約をするなら―

  • 同じ文字列からは同じハッシュコードが返るよ
    でも文字列が違うからと云ってハッシュコードが違うとは限らないので要注意
  • まぁそうは云っても、フレームワークバージョンが違ったりすればハッシュコードも変わるかも知れん
    もっと云えばアプリケーションが違うだけでも異なるかもねー
  • (以下略)

こんなに不安定なんだ、GetHashCode()って…

で、結局

GetHashCode()使うのは諦めて、MD5を計算するようにしました。
B君の機嫌も直ってよかったよかった。

実はこの他にもCLR4に移行した(所為だと思うんですが)事によって、Stream系の動きも若干変わった様で、コードに手を入れる必要がありましたよ。

12
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
5