Pet*_*ans 25 java security hash
当我使用以下方法在Java中计算字符串的SHA-256时
public static void main(String[] args) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hash = md.digest("password".getBytes());
StringBuffer sb = new StringBuffer();
for(byte b : hash) {
sb.append(Integer.toHexString(b & 0xff));
}
System.out.println(sb.toString());
}
Run Code Online (Sandbox Code Playgroud)
我明白了:
5e884898da2847151d0e56f8dc6292773603dd6aabbdd62a11ef721d1542d8
Run Code Online (Sandbox Code Playgroud)
在命令行上我执行以下操作(我需要-n不添加换行符):
echo -n "password" | sha256sum
Run Code Online (Sandbox Code Playgroud)
得到
5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
Run Code Online (Sandbox Code Playgroud)
如果我们更仔细地比较这些,我会发现两个微妙的差异
5e884898da2847151d0e56f8dc6292773603dd6aabbdd62a11ef721d1542d8
5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
Run Code Online (Sandbox Code Playgroud)
要么 :
5e884898da28 47151d0e56f8dc6292773603d d6aabbdd62a11ef721d1542d8
5e884898da28 0 47151d0e56f8dc6292773603d 0 d6aabbdd62a11ef721d1542d8
Run Code Online (Sandbox Code Playgroud)
这两个中哪一个是正确的?
结果:两者都是,但我错了......
使用以下方法修复它:
StringBuffer sb = new StringBuffer();
for(byte b : hash) {
sb.append(String.format("%02x", b));
}
Run Code Online (Sandbox Code Playgroud)
谢谢!
Sea*_*wen 29
我将采取一个合理的猜测:两者都输出相同的摘要,但在您的Java代码中输出byte[]结果为十六进制字符串,您输出小字节值(小于16)而没有前导0.所以一个值为"的字节" 0x0d"被写为"d"而不是"0d".
pax*_*blo 10
罪魁祸首是toHexString.这似乎是输出6为值6,而sha256sum一个正输出06.Integer.toHexString()状态的Java文档:
该值转换为十六进制(基数为16)的ASCII数字字符串,没有额外的前导0.
字符串中的其他零不会受到影响,因为它们是字节的后半部分(例如30).
解决这个问题的一种方法是改变:
for(byte b : hash) {
sb.append(Integer.toHexString(b & 0xff));
}
Run Code Online (Sandbox Code Playgroud)
至:
for(byte b : hash) {
if (b < 16) sb.append("0");
sb.append(Integer.toHexString(b & 0xff));
}
Run Code Online (Sandbox Code Playgroud)