我试图理解SHA-2算法。而且人们如何编码消息"L"似乎有点模糊(参见维基百科的SHA256-2伪代码)。消息是用ASCII、UTF-8还是UTF-16编码的?我明白,从技术上讲,消息L可能是我们在加密之前决定的任何东西,但我想检查我的小测试程序与其他网站,如https://www.dcode.fr/sha256-hash,我意识到我甚至不能检查任何东西(除了空"),而不知道我们是否填充'1'和随后的'0'到消息的9位表示或消息的16位表示。如果我使用ASCII(在这种情况下与UTF-8相同)作为单词'dcode',我希望消息以以下二进制序列开始:
d:01100100:UTF-8:100
c:01100011:UTF-8:99
o:01101111:UTF-8:111
d:01100100:UTF-8:100
e:01100101:UTF-8:101
0110010001100011011011110110010001100101
有人能证明我想的是对的吗?如果您知道预先哈希消息的标准应该是UTF-8或UTF-16(可能用于特定应用程序),那么您将不胜感激。
这个答案很接近,但答案缺乏特异性
如何在sha家族中填充消息
编码无关紧要。消息L"就是一堆比特。文本可以用您喜欢的任何编码进行编码。SHA256算法处理的是最终编码的位,所以如果文本用UTF8或UTF16编码,您将得到不同的答案。
当你收到消息时,SHA256可以被验证,然后消息可以被解码。发送者必须告诉你预期的SHA256和文本的编码。
供参考,链接1的站点使用字符的ASCII值来生成列出的哈希值。确保用dCode
,而不是问题中的dcode
。以下Python代码:
>>> import hashlib
>>> hashlib.sha256('dCode'.encode('ascii')).hexdigest()
'254cd63ece8595b5c503783d596803f1552e0733d02fe4080b217eadb17711dd'
就填充而言,消息(在本例中为"dCode")是5个字节(40位)。根据维基百科SHA-256:
预处理(Padding):
从长度为L位的原始消息开始
追加一个'1'位
追加K个'0'位,其中K为最小值>= 0,使得(L + 1 + K + 64)是512的倍数
追加L为64位大端整数,使后处理的总长度为512位的倍数使得消息中的位为:1,(比特数是512的倍数)
"dCode"是5字节(40比特)。必须至少再增加9个字节(1位和7个K位组成1个字节,加上64位(8字节)的位端值l,即14个字节。对512位取模的消息需要64个字节,因此在最后的8字节长度之前必须再添加50个零字节。在Python中应该是:
>>> def preprocess(msg):
... # original message length in bits
... L = len(msg) * 8
... # append another byte binary 10000000 + the 8-byte big-endian L
... msg += b'x80' + L.to_bytes(8,'big')
... n = len(msg) * 8 # new total length
... if n % 512 != 0: # if not modulo 512
... n = 512 - n % 512 # how many more bits needed
... n //= 8 # convert to bytes
... # Python magic to insert n bytes in the right place
... msg = msg[:L // 8 + 1] + b'x00' * n + msg[L // 8 + 1:]
... return msg
...
>>> preprocess(b'dCode').hex()
'64436f64658000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028'
>>> len(preprocess(b'dCode')) # in bytes
64
注意:上面的算法假设消息的大小是8位的倍数(面向字节的消息),但是SHA-256支持任何位长度。
1SHA-256on dCode.fr [online website],检索于2022-06-12,https://www.dcode.fr/sha256-hash