タイトルそのまんまなんですけど
.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系の動きも若干変わった様で、コードに手を入れる必要がありましたよ。