SHA 哈希在 Java 中出现意外行为 - 提供的代码
SHA Hashing behaving unexpectedly in Java - Code Provided
读入一个文件然后使用 SHA-256 对其进行哈希处理我发现了一个tutorial,其中显示了两种不同的方法。
将我散列的文件 (这是一个 PDF) 与两种方法进行比较时,它们不匹配。我正确地遵循了代码,不明白为什么它不匹配。
这是我的结果:
Hex format: b050692edb134da209adf76347f6c5e49db8734edeaa44876606ec8e5559ab4e
Hex format: b050692edb134da29adf76347f6c5e49db8734edeaa4487666ec8e5559ab4e
中间的两个零好像被砍掉了,就是不明白为什么
Java代码
import java.io.FileInputStream;
import java.security.MessageDigest;
public class SHAHash{
public static void main(String[] args)throws Exception{
MessageDigest md = MessageDigest.getInstance("SHA-256");
FileInputStream fis = new FileInputStream("myfile");
byte[] dataBytes = new byte[1024];
int nread = 0;
while((nread = fis.read(dataBytes))!= -1){
md.update(dataBytes, 0, nread);
};
byte[] mdbytes = md.digest();
StringBuffer sb1 = new StringBuffer();
for(int i = 0; i < mdbytes.length; i++){
sb1.append(Integer.toString((mdbytes[i] & 0xFF) + 0x100, 16).substring(1));
}
System.out.println("Hex format: " + sb1.toString());
StringBuffer sb2 = new StringBuffer();
for(int i = 0; i < mdbytes.length; i++){
sb2.append(Integer.toHexString(0xFF & mdbytes[i]));
}
System.out.println("Hex format: " + sb2.toString());
}
}
而不是 StringBuffer
you should be using StringBuilder
(the methods aren't synchronized and you aren't using multiple threads, it's like the difference between a Vector
and an ArrayList
). Also, you need to preserve leading 0
(s). You could correct your second loop with something like String.format(String, Object...)
。把它们放在一起,
StringBuilder sb2 = new StringBuilder();
for (int i = 0; i < mdbytes.length; i++) {
sb2.append(String.format("%02x", 0xFF & mdbytes[i]));
}
System.out.println("Hex format: " + sb2.toString());
两者的区别在于,第一个加0x100
,然后只取一个子串
这样,第一个循环中的 toString
调用总是 returns 一个以 1
开头的字符串,后跟实际值。这样零就被保留了。
第二个循环产生错误的输出,因为数字零丢失了。
读入一个文件然后使用 SHA-256 对其进行哈希处理我发现了一个tutorial,其中显示了两种不同的方法。
将我散列的文件 (这是一个 PDF) 与两种方法进行比较时,它们不匹配。我正确地遵循了代码,不明白为什么它不匹配。
这是我的结果:
Hex format: b050692edb134da209adf76347f6c5e49db8734edeaa44876606ec8e5559ab4e Hex format: b050692edb134da29adf76347f6c5e49db8734edeaa4487666ec8e5559ab4e
中间的两个零好像被砍掉了,就是不明白为什么
Java代码
import java.io.FileInputStream;
import java.security.MessageDigest;
public class SHAHash{
public static void main(String[] args)throws Exception{
MessageDigest md = MessageDigest.getInstance("SHA-256");
FileInputStream fis = new FileInputStream("myfile");
byte[] dataBytes = new byte[1024];
int nread = 0;
while((nread = fis.read(dataBytes))!= -1){
md.update(dataBytes, 0, nread);
};
byte[] mdbytes = md.digest();
StringBuffer sb1 = new StringBuffer();
for(int i = 0; i < mdbytes.length; i++){
sb1.append(Integer.toString((mdbytes[i] & 0xFF) + 0x100, 16).substring(1));
}
System.out.println("Hex format: " + sb1.toString());
StringBuffer sb2 = new StringBuffer();
for(int i = 0; i < mdbytes.length; i++){
sb2.append(Integer.toHexString(0xFF & mdbytes[i]));
}
System.out.println("Hex format: " + sb2.toString());
}
}
而不是 StringBuffer
you should be using StringBuilder
(the methods aren't synchronized and you aren't using multiple threads, it's like the difference between a Vector
and an ArrayList
). Also, you need to preserve leading 0
(s). You could correct your second loop with something like String.format(String, Object...)
。把它们放在一起,
StringBuilder sb2 = new StringBuilder();
for (int i = 0; i < mdbytes.length; i++) {
sb2.append(String.format("%02x", 0xFF & mdbytes[i]));
}
System.out.println("Hex format: " + sb2.toString());
两者的区别在于,第一个加0x100
,然后只取一个子串
这样,第一个循环中的 toString
调用总是 returns 一个以 1
开头的字符串,后跟实际值。这样零就被保留了。
第二个循环产生错误的输出,因为数字零丢失了。