如何更正TypeError:Unicode对象必须在哈希之前进行编码?

How to correct TypeError: Unicode-objects must be encoded before hashing?

提问人:JohnnyFromBF 提问时间:9/28/2011 最后编辑:AugustinJohnnyFromBF 更新时间:1/14/2021 访问量:560088

问:

我有这个错误:

Traceback (most recent call last):
  File "python_md5_cracker.py", line 27, in <module>
  m.update(line)
TypeError: Unicode-objects must be encoded before hashing

当我尝试在 Python 3.2.2 中执行此代码时:

import hashlib, sys
m = hashlib.md5()
hash = ""
hash_file = input("What is the file name in which the hash resides?  ")
wordlist = input("What is your wordlist?  (Enter the file name)  ")
try:
  hashdocument = open(hash_file, "r")
except IOError:
  print("Invalid file.")
  raw_input()
  sys.exit()
else:
  hash = hashdocument.readline()
  hash = hash.replace("\n", "")

try:
  wordlistfile = open(wordlist, "r")
except IOError:
  print("Invalid file.")
  raw_input()
  sys.exit()
else:
  pass
for line in wordlistfile:
  # Flush the buffer (this caused a massive problem when placed 
  # at the beginning of the script, because the buffer kept getting
  # overwritten, thus comparing incorrect hashes)
  m = hashlib.md5()
  line = line.replace("\n", "")
  m.update(line)
  word_hash = m.hexdigest()
  if word_hash == hash:
    print("Collision! The word corresponding to the given hash is", line)
    input()
    sys.exit()

print("The hash given does not correspond to any supplied word in the wordlist.")
input()
sys.exit()
python-3.x unicode 语法错误 哈希库

评论

3赞 dlamblin 11/28/2017
我发现打开一个带有“rb”的文件对我的案子有帮助。

答:

22赞 Cat Plus Plus 9/28/2011 #1

错误已经说明了您必须执行的操作。 MD5 对字节进行操作,因此您必须将 Unicode 字符串编码为 ,例如使用 .bytesline.encode('utf-8')

439赞 cwallenpoole 9/28/2011 #2

它可能正在查找来自 的字符编码。wordlistfile

wordlistfile = open(wordlist,"r",encoding='utf-8')

或者,如果您正在逐行工作:

line.encode('utf-8')

编辑

根据下面的评论和这个答案

我上面的回答假设所需的输出是来自文件的输出。如果你对工作感到满意,那么你最好使用 .但重要的是要记住,如果您将其与 输出进行比较,则不应使用 。 输出 a 和 不能直接与 bytes 对象进行比较: 。(这个话题还有很多,但我没有时间ATM)。strwordlistbytesopen(wordlist, "rb")hashfilerbhexdigesthashlib.md5(value).hashdigest()str'abc' != b'abc'

还应该注意的是,这一行:

line.replace("\n", "")

应该是

line.strip()

这适用于 bytes 和 str。但是,如果您决定简单地转换为 ,则可以将该行更改为:bytes

line.replace(b"\n", b"")

评论

4赞 Tanky Woo 1/19/2016
open(wordlist,"r",encoding='utf-8')为什么使用带有特定编码的 Open,编码被指定为解码编解码器,如果没有此选项,它使用与平台相关的编码。
1赞 ShadowRanger 1/13/2021
前半部分完全是错误的,令人震惊的是,它得到了如此高的投票。显式指定 只是更改它如何解码磁盘上的字节以获得(存储任意 Unicode 的文本类型),但它会解码为没有它,并且问题首先在于使用。撤消了错误的解码,但 OP 首先应该只是在模式下打开文件(没有编码),所以首先是一个对象(需要一些微不足道的更改来匹配,例如在 )。encodingstrstrstrline.encode('utf-8')'rb'linebytes.replace("\n", '')
0赞 cwallenpoole 1/14/2021
@ShadowRanger 如果 OP 想要一个 ?我在答案中添加了一些内容,但我最初的回复是简短、甜蜜且立即可用的。当我写上面的回复时,这也恰好是我正在做的一个项目的正确答案,所以str¯\_(ツ)_/¯
14赞 tzot 10/15/2011 #3

请先看看这个答案。

现在,错误消息很明确:您只能使用字节,而不能使用 Python 字符串(以前在 Python < 3 中是这样),因此您必须使用您喜欢的编码对字符串进行编码:、,甚至是受限制的 8 位编码之一(有些人可能称之为代码页)。unicodeutf-32utf-16utf-8

当您从文件中读取时,Python 3 会自动将单词列表文件中的字节解码为 Unicode。我建议你这样做:

m.update(line.encode(wordlistfile.encoding))

因此,推送到 MD5 算法的编码数据的编码与底层文件完全相同。

评论

0赞 ShadowRanger 1/13/2021
当您可以在二进制模式下处理文件并处理整个过程时,为什么只解码以重新编码?bytes
0赞 tzot 1/13/2021
@ShadowRanger对于这个简单的情况(只需阅读行并去除每行末尾的 b'\n'),您的建议是正确且充分的。
183赞 Jaykumar Patel 3/19/2014 #4

你必须定义像 , 试试这个简单的方法,encoding formatutf-8

此示例使用 SHA256 算法生成一个随机数:

>>> import hashlib
>>> hashlib.sha256(str(random.getrandbits(256)).encode('utf-8')).hexdigest()
'cd183a211ed2434eac4f31b317c573c50e6c24e3a28b82ddcb0bf8bedf387a9f'
12赞 jfs 3/26/2014 #5

您可以以二进制模式打开文件:

import hashlib

with open(hash_file) as file:
    control_hash = file.readline().rstrip("\n")

wordlistfile = open(wordlist, "rb")
# ...
for line in wordlistfile:
    if hashlib.md5(line.rstrip(b'\n\r')).hexdigest() == control_hash:
       # collision

评论

4赞 ShadowRanger 1/13/2021
我非常惊讶,我不得不向下滚动这么远才能找到第一个理智的答案。除非有理由认为文件编码错误(因此必须从错误的编码解码,然后使用正确的哈希编码进行编码),否则这是迄今为止最好的解决方案,避免无意义的解码和重新编码,而只进行处理(OP 代码中错误的来源)。wordlistbytes
0赞 Nishad C M 7/7/2022
python3.*,我能弄清楚的唯一工作选项是以二进制模式打开文件。然后进行哈希操作。python2 只是正常打开和散列文本工作。
19赞 Khắc Nghĩa Từ 9/11/2017 #6

要存储密码 (PY3):

import hashlib, os
password_salt = os.urandom(32).hex()
password = '12345'

hash = hashlib.sha512()
hash.update(('%s%s' % (password_salt, password)).encode('utf-8'))
password_hash = hash.hexdigest()

评论

2赞 Yash 12/12/2018
此行使密码无法使用。password_salt = os.urandom(32).hex() 它应该是一个固定的已知值,但它只能是服务器的秘密。请纠正我或根据您的代码进行调整。
2赞 Carson 1/10/2019
我同意@Yash你要么为每个哈希值使用一个盐(不是最好的),要么如果你为每个哈希生成一个随机盐,你必须将它与哈希一起存储,以便以后再次使用进行比较
-4赞 udz 6/24/2018 #7

该程序是上述MD5破解程序的无错误和增强版本,它读取包含哈希密码列表的文件,并将其与英语词典单词列表中的哈希单词进行检查。希望对您有所帮助。

我从以下链接下载了英语词典 https://github.com/dwyl/english-words

# md5cracker.py
# English Dictionary https://github.com/dwyl/english-words 

import hashlib, sys

hash_file = 'exercise\hashed.txt'
wordlist = 'data_sets\english_dictionary\words.txt'

try:
    hashdocument = open(hash_file,'r')
except IOError:
    print('Invalid file.')
    sys.exit()
else:
    count = 0
    for hash in hashdocument:
        hash = hash.rstrip('\n')
        print(hash)
        i = 0
        with open(wordlist,'r') as wordlistfile:
            for word in wordlistfile:
                m = hashlib.md5()
                word = word.rstrip('\n')            
                m.update(word.encode('utf-8'))
                word_hash = m.hexdigest()
                if word_hash==hash:
                    print('The word, hash combination is ' + word + ',' + hash)
                    count += 1
                    break
                i += 1
        print('Itiration is ' + str(i))
    if count == 0:
        print('The hash given does not correspond to any supplied word in the wordlist.')
    else:
        print('Total passwords identified is: ' + str(count))
sys.exit()
45赞 Sabyasachi 12/16/2018 #8
import hashlib
string_to_hash = '123'
hash_object = hashlib.sha256(str(string_to_hash).encode('utf-8'))
print('Hash', hash_object.hexdigest())

评论

0赞 kundan 10/30/2020
hashlib.sha256 方法始终需要 Unicode。在 Python-2 中,str 既是 str 又是 unicode,因此只需传递string_to_hash就可以正常工作。但是,在 Python-3 中,string(text, here string_to_hash) 和 unicode 是两种不同的类型。因此,当我们只传递 string_to_hash(文本类型)时,它会抛出错误,指出需要 unicode 值。
16赞 Mike Cash 1/29/2019 #9

对这一行进行编码为我修复了它。

m.update(line.encode('utf-8'))
6赞 SBimochan 4/5/2020 #10

如果是单行字符串。用 b 或 B 包裹它,例如:

variable = b"This is a variable"

variable2 = B"This is also a variable"