[解決済み] Java のダイジェストと外部ユーティリティで異なる結果
質問内容
Windows Calculator ファイルのハッシュ値を生成する簡単な Java クラスを作成しました。 私は、以下のものを使用しています。
Windows 7 Professional with SP1
. 試しに
Java 6.0.29
と
Java 7.0.03
. なぜJavaと外部ユーティリティやWebサイトで異なるハッシュ値が得られるのか、誰か教えてください。 外部のものはすべて互いに一致し、Javaだけが異なる結果を返しています。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.zip.CRC32;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class Checksum
{
private static int size = 65536;
private static File calc = new File("C:/Windows/system32/calc.exe");
/*
C:\Windows\System32\calc.exe (verified via several different utilities)
----------------------------
CRC-32b = 8D8F5F8E
MD5 = 60B7C0FEAD45F2066E5B805A91F4F0FC
SHA-1 = 9018A7D6CDBE859A430E8794E73381F77C840BE0
SHA-256 = 80C10EE5F21F92F89CBC293A59D2FD4C01C7958AACAD15642558DB700943FA22
SHA-384 = 551186C804C17B4CCDA07FD5FE83A32B48B4D173DAC3262F16489029894FC008A501B50AB9B53158B429031B043043D2
SHA-512 = 68B9F9C00FC64DF946684CE81A72A2624F0FC07E07C0C8B3DB2FAE8C9C0415BD1B4A03AD7FFA96985AF0CC5E0410F6C5E29A30200EFFF21AB4B01369A3C59B58
Results from this class
-----------------------
CRC-32 = 967E5DDE
MD5 = 10E4A1D2132CCB5C6759F038CDB6F3C9
SHA-1 = 42D36EEB2140441B48287B7CD30B38105986D68F
SHA-256 = C6A91CBA00BF87CDB064C49ADAAC82255CBEC6FDD48FD21F9B3B96ABF019916B
*/
public static void main(String[] args)throws Exception {
Map<String, String> hashes = getFileHash(calc);
for (Map.Entry<String, String> entry : hashes.entrySet()) {
System.out.println(String.format("%-7s = %s", entry.getKey(), entry.getValue()));
}
}
private static Map<String, String> getFileHash(File file) throws NoSuchAlgorithmException, IOException {
Map<String, String> results = new LinkedHashMap<String, String>();
if (file != null && file.exists()) {
CRC32 crc32 = new CRC32();
MessageDigest md5 = MessageDigest.getInstance("MD5");
MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
FileInputStream fis = new FileInputStream(file);
byte data[] = new byte[size];
int len = 0;
while ((len = fis.read(data)) != -1) {
crc32.update(data, 0, len);
md5.update(data, 0, len);
sha1.update(data, 0, len);
sha256.update(data, 0, len);
}
fis.close();
results.put("CRC-32", toHex(crc32.getValue()));
results.put(md5.getAlgorithm(), toHex(md5.digest()));
results.put(sha1.getAlgorithm(), toHex(sha1.digest()));
results.put(sha256.getAlgorithm(), toHex(sha256.digest()));
}
return results;
}
private static String toHex(byte[] bytes) {
String result = "";
if (bytes != null) {
StringBuilder sb = new StringBuilder(bytes.length * 2);
for (byte element : bytes) {
if ((element & 0xff) < 0x10) {
sb.append("0");
}
sb.append(Long.toString(element & 0xff, 16));
}
result = sb.toString().toUpperCase();
}
return result;
}
private static String toHex(long value) {
return Long.toHexString(value).toUpperCase();
}
}
解決方法は?
了解です。Windowsのファイルシステムは、プロセスのアーキテクチャによって異なる動作をしています。これは の記事で解説しています。 - を具体的に説明します。
しかし、システムパスがハードコードされている32ビットアプリケーションで、64ビットWindowsで動作している場合はどうでしょうか?プログラムコードを変更せずに、どうやって新しいSysWOW64フォルダを見つけることができるのだろうかと思うかもしれません。その答えは、エミュレーターがSystem32フォルダーへの呼び出しを透過的にSysWOW64フォルダーにリダイレクトするため、たとえSystem32フォルダーにハードコードされていたとしても(C: \WindowsSystem32 など)、エミュレーターは代わりにSysWOW64フォルダーを使用するようにするのです。このため、System32 フォルダを使用する同じソースコードを、32 ビットと 64 ビットの両方のプログラムコードに変更することなくコンパイルすることができます。
をコピーしてみてください。
calc.exe
を別の場所に移動して、もう一度同じツールを実行してみてください。Javaと同じ結果が得られるはずです。
何か
Windowsのファイルシステムが、Javaに与えるのと異なるデータをツールに与えている... Windowsのディレクトリにあるため、おそらく"異なる"を処理することに関係するものだと確信しています。
さらに、C#で再現してみたところ......。 実行しているプロセスのアーキテクチャ . というわけで、サンプルプログラムです。
using System;
using System.IO;
using System.Security.Cryptography;
class Test
{
static void Main()
{
using (var md5 = MD5.Create())
{
string path = "c:/Windows/System32/Calc.exe";
var bytes = md5.ComputeHash(File.ReadAllBytes(path));
Console.WriteLine(BitConverter.ToString(bytes));
}
}
}
そして、これがコンソールセッションです(コンパイラのチャタリングを除いたもの)。
c:\users\jon\Test>csc /platform:x86 Test.cs
c:\users\jon\Test>test
60-B7-C0-FE-AD-45-F2-06-6E-5B-80-5A-91-F4-F0-FC
c:\users\jon\Test>csc /platform:x64 Test.cs
c:\users\jon\Test>test
10-E4-A1-D2-13-2C-CB-5C-67-59-F0-38-CD-B6-F3-C9
関連
-
この行に複数のマーカーがある - HttpServletResponseが型エラーに解決できない
-
undefinedeclipse エラー。この行に複数のアノテーションが見つかりました: - 文字列を型解決に解決できない
-
SpringBootApplication を型解決できない。
-
Dateが型に解決できない問題を解決する
-
スキャナは、タイプに解決することはできません最もルーキー初心者の質問
-
Java コンパイルエラー - スレッド "main" で例外 java.lang.Error: 未解決のコンパイル問題です。
-
Exception: java.util.NoSuchElementException: 行が見つかりません
-
java -serverコマンドで「Error: no `server' JVM at ... jvm.dll」を解決する方法です。
-
コミットには何も追加されないが、未追跡のファイルが存在し、gitで未追跡のファイルに対する完璧な解決策
-
[解決済み] Android端末を異なる周波数で振動させるには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
エラー java.util.NoSuchElementException
-
Java Error スレッド "AWT-EventQueue-0" で例外発生 java.lang.
-
エラーが報告されました。リソースの読み込みに失敗しました:サーバーは500(内部サーバーエラー)のステータスで応答しました。
-
Android Studio 3.1.2 で v4, v7 パッケージが見つからない シンボル 'AppCompatActivity' を解決できない
-
コンストラクタの呼び出しは、コンストラクタのエラー理解の最初のステートメントである必要があります。
-
node js npm gruntインストール、elasticsearch-head 5.Xインストール
-
[オリジナル】java学習ノート【II】よくあるエラー クラスパス上のクラスファイルが見つからない、またはアクセスできない場合
-
org.glassfish.jersey.servlet.ServletContainer
-
java.lang.NoClassDefFoundError: org.apache.jasper.el.ELContextImpl クラスを初期化できませんでした。
-
HttpClientがGZIP形式でない場合の対処法