Java和哈希算法用于比较文件

6

我需要对文件进行指纹识别以匹配双重文件。2013年推荐使用Java的什么?我是否应该比较文件大小,还是这是一个不必要的检查?

误判概率应该非常接近于0。

编辑:有很多答案,谢谢。今天备份软件的标准是什么? SHA-256?更高吗?我猜md5不太适合?


128位或256位哈希通常适用于正常使用。您还可以比较文件大小,将文件放入不同的桶中,然后仅在有两个以上相同大小的文件时进行哈希。 - nhahtdh
第三方库是否允许?至少Guava具有使这比在纯Java中所需做的工作更加容易的功能。 - Louis Wasserman
MD5对此非常适用。请注意,MD5不能再被视为安全的哈希算法。您必须根据您的情况确定这是否重要。(是否有可能黑客试图欺骗您的软件,使其认为两个文件是相同的?) - Jesper
@Jesper:如果攻击者控制了这两个文件,那么无论是MD5还是SHA1都没有关系。如果攻击者只控制了一个文件,那么要找到第二个预像攻击仍然很困难。 - nhahtdh
2个回答

13
如果希望误报概率为,而不是"比被雷劈的概率还要低",那么根本不能使用任何哈希算法;必须逐字节比较文件。另外,如果可以使用第三方库,可以使用Guava的一行代码来逐字节比较两个文件。
Files.asByteSource(file1).contentEquals(Files.asByteSource(file2));

它负责打开和关闭文件以及比较的详细信息。

如果您愿意接受虚警概率小于被雷击中的可能性,那么您可以这样做

Files.hash(file, Hashing.sha1()); // or md5(), or sha256(), or...

你可以使用HashCode方法返回一个哈希码,然后将其与另一个文件的哈希值进行比较。 (该版本还处理了MessageDigest的混乱,正确打开和关闭文件等问题。)


MD5是可以的,甚至64位哈希对于大多数目的来说已经足够好了。在实际(非安全)使用级别上,碰撞的机会极低:http://en.wikipedia.org/wiki/Birthday_paradox#Probability_table - nhahtdh
我认为你现在想要的方法是“toByteArray”。 - Setheron
@Setheron:你为什么这么说?这些操作都不需要“toByteArray”。(而且,即使文件太大无法放入RAM中,它们也应该能正常工作。) - Louis Wasserman
@LouisWasserman 我的错,由于某些原因我使用的 Guava 版本没有 asByteSource。最终我使用了 "Files.equal(originalWallet, modifiedWallet)"。 - Setheron

1

您是否想知道如何在Java中获取文件的md5校验和?如果是这样,请阅读接受的答案这里这里。基本上,做这个:

import java.security.DigestInputStream;
...
...

MessageDigest md_1 = MessageDigest.getInstance("MD5");
MessageDigest md_2 = MessageDigest.getInstance("MD5");
InputStream is_1 = new FileInputStream("file1.txt");
InputStream is_2 = new FileInputStream("file2.txt");
try {
  is_1 = new DigestInputStream(is_1, md_1);
  is_2 = new DigestInputStream(is_2, md_2);
}
finally {
  is_1.close();
  is_2.close();
}
byte[] digest_1 = md_1.digest();
byte[] digest_2 = md_2.digest();

// compare digest_1 and digest_2

我是否还应该比较文件大小,或者这是一个不必要的检查?

这是不必要的。


MD5用于比较文件是否安全吗? - Stig
SHA被认为比MD5更安全。然而,两个不同文件共享相同的MD5校验和的概率几乎为零。 - Barney
1
再次比较文件大小是不必要的,但我认为最好这样做,因为我们可以跳过昂贵的磁盘读取来计算哈希值。 - nhahtdh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接