【问题标题】:How to correct TypeError: Unicode-objects must be encoded before hashing?如何纠正 TypeError:Unicode 对象必须在散列之前进行编码?
【发布时间】:2011-11-26 23:17:54
【问题描述】:

我有这个错误:

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()

【问题讨论】:

  • 我发现用 'rb' 打开文件对我的情况很有帮助。

标签: python python-3.x unicode syntax-error hashlib


【解决方案1】:

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

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

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

line.encode('utf-8')

编辑

根据下面的评论和this answer

我上面的回答假设所需的输出是来自wordlist 文件的str。如果您对在bytes 工作感到满意,那么您最好使用open(wordlist, "rb")。但重要的是要记住,如果您将hexdigest 的输出与hexdigest 的输出进行比较,您的hashfile 应该使用rbhashlib.md5(value).hashdigest() 输出 str 并且不能直接与字节对象进行比较:'abc' != b'abc'。 (这个话题还有很多,但我没有时间提款机)。

还需要注意的是这一行:

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

应该是

line.strip()

这对字节和 str 都有效。但是,如果您决定简单地转换为bytes,那么您可以将行更改为:

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

【讨论】:

  • open(wordlist,"r",encoding='utf-8')为什么要使用open的特定编码,编码指定解码编解码器,没有这个选项,它使用平台相关的编码。
  • 本文的前半部分完全错误,令人震惊的是,它获得了如此高的投票。显式指定encoding 只是改变了它如何解码磁盘上的字节以获得str(一种存储任意Unicode 的文本类型),但如果没有它,它会解码为str,问题在于使用str第一名。 line.encode('utf-8') undoes 错误解码,但 OP 应该首先以 'rb' 模式打开文件(没有编码)所以 linebytes 对象第一名(需要进行一些细微的更改来匹配,例如在.replace("\n", ''))。
  • @ShadowRanger 如果 OP 想要 str?我在答案中添加了一些内容,但我最初的回复是简短、甜蜜且立即可用。当我写上述回复时,它也恰好是我正在从事的一个项目的正确答案,所以¯\_(ツ)_/¯
【解决方案2】:

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

variable = b"This is a variable"

variable2 = B"This is also a variable"

【讨论】:

    【解决方案3】:

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

    m.update(line.encode('utf-8'))
    

    【讨论】:

      【解决方案4】:
      import hashlib
      string_to_hash = '123'
      hash_object = hashlib.sha256(str(string_to_hash).encode('utf-8'))
      print('Hash', hash_object.hexdigest())
      

      【讨论】:

      • hashlib.sha256 方法总是需要 unicode。在 Python-2 中,str 既是 str 又是 unicode,因此只需传递 string_to_hash 就可以正常工作。但是,在 Python-3 中 string(text, here string_to_hash) 和 unicode 是两种不同的类型。因此,当我们只传递 string_to_hash(文本类型)时,它会抛出错误,说明需要 unicode 值。
      【解决方案5】:

      该程序是上述 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()
      

      【讨论】:

        【解决方案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()
        

        【讨论】:

        • 此行使密码无法使用。 password_salt = os.urandom(32).hex() 它应该是一个固定的已知值,但它只能对服务器保密。请纠正我或使其适应您的代码。
        • 我同意@Yash 你要么为每个散列使用一个盐(不是最好的),要么为每个散列生成一个随机盐,你必须将它与散列一起存储以使用稍后再进行比较
        【解决方案7】:

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

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

        >>> import hashlib
        >>> hashlib.sha256(str(random.getrandbits(256)).encode('utf-8')).hexdigest()
        'cd183a211ed2434eac4f31b317c573c50e6c24e3a28b82ddcb0bf8bedf387a9f'
        

        【讨论】:

          【解决方案8】:

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

          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
          

          【讨论】:

          • 我非常惊讶我不得不向下滚动这么远才能找到第一个理智的答案。除非有某些理由认为 wordlist 文件的编码错误(因此必须从错误的编码中解码,然后使用正确的编码进行散列编码),否则这是迄今为止最好的解决方案,避免无意义的解码和重新编码赞成只处理bytes(OP 代码中的错误来源)。
          【解决方案9】:

          请先看看that的答案。

          现在,错误消息很清楚:您只能使用字节,而不是 Python 字符串(在 Python unicode),因此您必须使用首选编码对字符串进行编码:utf-32utf-16utf-8 甚至是一种受限的 8 位编码(有些人可能称之为代码页)。

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

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

          以便推送到 md5 算法的编码数据与底层文件完全一样编码。

          【讨论】:

          • 当您可以在二进制模式下处理文件并全程处理bytes时,为什么只解码重新编码?
          • @ShadowRanger 对于这个简单的案例(只是读取行并在每行末尾剥离 b'\n')你的建议是正确和充分的。
          【解决方案10】:

          错误已经说明了你必须做什么。 MD5 对字节进行操作,因此您必须将 Unicode 字符串编码为 bytes,例如line.encode('utf-8')

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-08-21
            • 1970-01-01
            • 2020-06-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多