在 Python 中迭代大量数据的有效方法

Efficient way of iterating through large amounts of data in Python

我正在尝试 运行 对 sha512 哈希进行字典攻击。我知道散列由两个单词组成,全部小写,由 space 分隔。这些词来自一本已知的词典 (02-dictionary.txt),其中包含 172,820 个词。目前,我的代码如下:

import hashlib
import sys
import time

def crack_hash(word, target):
    dict_hash = hashlib.sha512(word.encode())
    if dict_hash.hexdigest() == target:
        return (True, word)
    else:
        return (False, None)

if __name__ == "__main__":
    target_hash = sys.argv[1].strip()
    
    fp = open("02-dictionary.txt", "r")

    words = []
    start_time = time.time()
    for word in fp:
        words.append(word)
    fp.close()

    for word1 in words:
        for word2 in words:
            big_word = word1.strip() + " " + word2.strip()
            print(big_word)
            soln_found, soln_word = crack_hash(big_word.strip(), target_hash)
            if soln_found:
                print('Solution found')
                print("The word was:", soln_word)
                break

    end_time = time.time()
    total_time = end_time - start_time
    print("Time taken:", round(total_time, 5), "seconds")

但是,当我 运行 这段代码时,程序 运行 非常慢。我知道 Python 不是最高效的语言,但我猜这个问题更多是源于数据结构的选择。有没有更高效的数据结构?我尝试使用 array 模块,但文档使它看起来好像是设计用于更原始的类型(整数、浮点数、短裤、布尔值、字符等),而不是用于更复杂的类型像字符串(或字符列表)。改进此代码的最佳方法是什么?在大约一个小时的 运行 时间里,我只完成了大约 1% 的所有可能的单词组合。

问题是您正在计算 1780002 = 31684000000(大约 235)个哈希值。这是很多工作。我做了一些更改以在纯 python 中实现一些优化,但我怀疑 hashlib 调用的开销非常大。我认为在本机代码中全部执行此操作会带来更显着的加速。

优化包括以下内容:

  • 将字典中的单词预计算为字节对象
  • 预计算散列第一部分的部分散列结果
import hashlib
import sys
import time


def try_all(words, target_hash):
    for word1 in words:
        hash_prefix = hashlib.sha512(word1 + b' ')
        for word2 in words:
            prefix_copy = hash_prefix.copy()
            prefix_copy.update(word2)
            # print(big_word)
            if prefix_copy.digest() == target_hash:
                print('Solution found')
                big_word = (word1 + b' ' + word2).decode('utf8')
                print(f'The word was: {big_word}')
                return


def read_all_words(filename):
    with open(filename, "rt") as f:
        return [line.strip().encode('utf-8') for line in f]


def get_test_hash(words):
    phrase = words[-2] + b' ' + words[-1]  # pick target towards end
    return hashlib.sha512(phrase).digest()


if __name__ == "__main__":
    words = read_all_words("02-dictionary.txt")
    TESTING = True
    if TESTING:
        words = words[:5000]  # reduce the size of the word list for testing only
        target_hash = get_test_hash(words)
    else:
        target_hash = bytes.fromhex(sys.argv[1].strip())
    start_time = time.time()
    try_all(words, target_hash)
    end_time = time.time()
    total_time = end_time - start_time
    print(f"Time taken: {round(total_time, 5)} seconds")
    print(f'{total_time / pow(len(words), 2)} seconds per hash')

在我的笔记本电脑上,每次哈希大约需要 1.1 * 10-6 秒,因此尝试字典中的所有单词将花费不到 10 小时的时间 CPU时间。