SHA 256 不同的结果
SHA 256 Different Result
如果我从 Mac
调用命令
echo hello | shasum -a 256
或来自ubuntu
echo hello | sha256sum
然后我得到以下结果
5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03 -
我注意到最后有破折号。
但是当我使用 Python hashlib
或 Java java.security.MessageDigest
时,它们会给我相同的结果如下:
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
所以,谁能指出我哪里错了?
谢谢。
Python:
>>> import hashlib
>>> hashlib.sha256("hello").hexdigest()
Java:
MessageDigest md = MessageDigest.getInstance("SHA-256");
String text = "hello";
md.update(text.getBytes("UTF-8"));
byte[] digest = md.digest();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < digest.length; i++) {
sb.append(String.format("%02x", digest[i] & 0xFF))
}
System.out.println(sb.toString());
echo
命令正在向您的字符串添加尾随换行符。尝试:
hashlib.sha256("hello\n").hexdigest()
TL;DR 这是一个详尽的解释字符和十六进制编码的答案,您可以跳过它并查看下面的代码
sha256sum
和相关命令在输出中添加破折号:-
。这些命令用于显示 *files 的哈希值。单个破折号仅表示输入来自标准输入流(即没有文件名)。不幸的是,我没有看到抑制输出的选项,因此您必须自己将其删除才能获得实际的哈希值。
因此哈希实用程序不仅 return 哈希值。 SHA-256 散列值仅包含 32 个字节。由于人类无法读取二进制,因此二进制使用十六进制显示,但实际值仍应视为字节。十六进制字符只是这些字节的表示。
散列函数的输入由位或更确切地说字节组成。这意味着编码文本的任何差异都意味着哈希值将不同。当涉及到 white-space 和行尾编码时,这尤其棘手。不过,在“hello”的情况下,最好使用 echo
命令的 -n
命令行选项来抑制它,而不是添加尾随换行符。
请注意,十六进制本身也可以以不同的方式显示;你会确保 whitespace 不存在并且比较不区分大小写或者字节的 representation 总是使用相同的大小写。
Shell代码
使用sha256sum
:
echo -n "hello" | sha256sum | tr -d "[:space:]-"
使用 OpenSSL 命令行:
echo -n hello | openssl sha256 -binary | od -An -tx1 | tr -d "[:space:]"
这里 od -An -tx1
将单独显示每个字节,而不是将它们分组,这可能会导致字节顺序问题。
tr -d "[:space:]
将从十六进制中删除 spaces 以及尾随的换行符。对于 sha256sum
,破折号文件指示器也被删除(注意末尾的 -
)。这样就可以执行文本(不区分大小写)比较。
Python代码
在 Python 中没有行尾:
print(hashlib.sha256("hello").hexdigest(), end="")
Java代码
在Java的情况下,您还应该确保文本编码与系统默认编码匹配,否则您可能会遇到麻烦。所以你应该改变:
md.update(text.getBytes("UTF-8"));
至
md.update(text.getBytes());
获取平台字符编码。否则,如果平台的编码与要比较的字符串的 UTF-8 不兼容,比较将失败。
如果我从 Mac
调用命令echo hello | shasum -a 256
或来自ubuntu
echo hello | sha256sum
然后我得到以下结果
5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03 -
我注意到最后有破折号。
但是当我使用 Python hashlib
或 Java java.security.MessageDigest
时,它们会给我相同的结果如下:
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
所以,谁能指出我哪里错了?
谢谢。
Python:
>>> import hashlib
>>> hashlib.sha256("hello").hexdigest()
Java:
MessageDigest md = MessageDigest.getInstance("SHA-256");
String text = "hello";
md.update(text.getBytes("UTF-8"));
byte[] digest = md.digest();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < digest.length; i++) {
sb.append(String.format("%02x", digest[i] & 0xFF))
}
System.out.println(sb.toString());
echo
命令正在向您的字符串添加尾随换行符。尝试:
hashlib.sha256("hello\n").hexdigest()
TL;DR 这是一个详尽的解释字符和十六进制编码的答案,您可以跳过它并查看下面的代码
sha256sum
和相关命令在输出中添加破折号:-
。这些命令用于显示 *files 的哈希值。单个破折号仅表示输入来自标准输入流(即没有文件名)。不幸的是,我没有看到抑制输出的选项,因此您必须自己将其删除才能获得实际的哈希值。
因此哈希实用程序不仅 return 哈希值。 SHA-256 散列值仅包含 32 个字节。由于人类无法读取二进制,因此二进制使用十六进制显示,但实际值仍应视为字节。十六进制字符只是这些字节的表示。
散列函数的输入由位或更确切地说字节组成。这意味着编码文本的任何差异都意味着哈希值将不同。当涉及到 white-space 和行尾编码时,这尤其棘手。不过,在“hello”的情况下,最好使用 echo
命令的 -n
命令行选项来抑制它,而不是添加尾随换行符。
请注意,十六进制本身也可以以不同的方式显示;你会确保 whitespace 不存在并且比较不区分大小写或者字节的 representation 总是使用相同的大小写。
Shell代码
使用sha256sum
:
echo -n "hello" | sha256sum | tr -d "[:space:]-"
使用 OpenSSL 命令行:
echo -n hello | openssl sha256 -binary | od -An -tx1 | tr -d "[:space:]"
这里 od -An -tx1
将单独显示每个字节,而不是将它们分组,这可能会导致字节顺序问题。
tr -d "[:space:]
将从十六进制中删除 spaces 以及尾随的换行符。对于 sha256sum
,破折号文件指示器也被删除(注意末尾的 -
)。这样就可以执行文本(不区分大小写)比较。
Python代码
在 Python 中没有行尾:
print(hashlib.sha256("hello").hexdigest(), end="")
Java代码
在Java的情况下,您还应该确保文本编码与系统默认编码匹配,否则您可能会遇到麻烦。所以你应该改变:
md.update(text.getBytes("UTF-8"));
至
md.update(text.getBytes());
获取平台字符编码。否则,如果平台的编码与要比较的字符串的 UTF-8 不兼容,比较将失败。