我有两个用于计算SHA1的小片段。
一个是非常快但似乎它不正确而另一个非常慢但是正确
我认为FileInputStream
转换为ByteArrayInputStream
是问题所在。
快速版:
MessageDigest md = MessageDigest.getInstance("SHA1");
FileInputStream fis = new FileInputStream("path/to/file.exe");
ByteArrayInputStream byteArrayInputStream =
new ByteArrayInputStream(fis.toString().getBytes());
DigestInputStream dis = new DigestInputStream(byteArrayInputStream, md);
BufferedInputStream bis = new BufferedInputStream(fis);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int ch;
while ((ch = dis.read()) != -1) {
byteArrayOutputStream.write(ch);
}
byte[] newInput = byteArrayOutputStream.toByteArray();
System.out.println("in digest : " +
byteArray2Hex(dis.getMessageDigest().digest()));
byteArrayOutputStream = new ByteArrayOutputStream();
DigestOutputStream digestOutputStream =
new DigestOutputStream(byteArrayOutputStream, md);
digestOutputStream.write(newInput);
System.out.println("out digest: " +
byteArray2Hex(digestOutputStream.getMessageDigest().digest()));
System.out.println("length: " +
new String(
byteArray2Hex(digestOutputStream.getMessageDigest().digest())).length());
digestOutputStream.close();
byteArrayOutputStream.close();
dis.close();
慢版:
MessageDigest algorithm = MessageDigest.getInstance("SHA1");
FileInputStream fis = new FileInputStream("path/to/file.exe");
BufferedInputStream bis = new BufferedInputStream(fis);
DigestInputStream dis = new DigestInputStream(bis, algorithm);
// read the file and update the hash calculation
while (dis.read() != -1);
// get the hash value as byte array
byte[] hash = algorithm.digest();
转换方法:
private static String byteArray2Hex(byte[] hash) {
Formatter formatter = new Formatter();
for (byte b : hash) {
formatter.format("%02x", b);
}
return formatter.toString();
}
我希望有另一种可能性让它运行,因为我需要性能。
答案 0 :(得分:18)
答案 1 :(得分:8)
这样做:
MessageDigest md = MessageDigest.getInstance("SHA1");
InputStream in = new FileInputStream("hereyourinputfilename");
byte[] buf = new byte[8192];
for (;;) {
int len = in.read(buf);
if (len < 0)
break;
md.update(buf, 0, len);
}
in.close();
byte[] hash = md.digest();
性能来自于按块处理数据。这里的8 kB缓冲区应该足够块。您不必使用BufferedInputStream
,因为8 kB缓冲区也可用作I / O缓冲区。
答案 2 :(得分:4)
快速且不正确的原因是(我认为)它没有散列文件内容!
FileInputStream fis = new FileInputStream("C:/Users/Ich/Downloads/srware_iron.exe");
ByteArrayInputStream byteArrayInputStream =
new ByteArrayInputStream(fis.toString().getBytes());
fis.toString()
调用不会读取文件的内容。相反,它给你一个字符串(我怀疑)看起来像这样:
"java.io.FileInputStream@xxxxxxxx"
然后您继续计算SHA1哈希值。 FileInputStream
及其超类不会覆盖Object::toString
...
将InputStream的全部内容读取到byte[]
的简单方法是使用Apache Commons I / O辅助方法 - IOUtils.toByteArray(InputStream)
。
答案 3 :(得分:1)
public void computeSHAHash(String path)// path to your file
{
String SHAHash = null;
try
{
MessageDigest md = MessageDigest.getInstance("SHA1");
InputStream in = new FileInputStream(path);
byte[] buf = new byte[8192];
int len = -1;
while((len = in.read(buf)) > 0)
{
md.update(buf, 0, len);
}
in.close();
byte[] data = md.digest();
try
{
SHAHash = convertToHex(data);
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Toast.makeToast(getApplicationContext(),"Generated Hash ="+SHAHash,Toast.LENGTH_SHORT).show();
}
private static String convertToHex(byte[] data) throws java.io.IOException
{
StringBuffer sb = new StringBuffer();
String hex = null;
hex = Base64.encodeToString(data, 0, data.length, NO_OPTIONS);
sb.append(hex);
return sb.toString();
}