web-dev-qa-db-ja.com

Pythonのファイルのハッシュ化

pythonにEOFを読み取らせて、sha1かmd5かにかかわらず、適切なハッシュを取得できます。助けてください。ここに私がこれまで持っているものがあります:

import hashlib

inputFile = raw_input("Enter the name of the file:")
openedFile = open(inputFile)
readFile = openedFile.read()

md5Hash = hashlib.md5(readFile)
md5Hashed = md5Hash.hexdigest()

sha1Hash = hashlib.sha1(readFile)
sha1Hashed = sha1Hash.hexdigest()

print "File Name: %s" % inputFile
print "MD5: %r" % md5Hashed
print "SHA1: %r" % sha1Hashed
62
user3358300

TL; DRはバッファを使用して、大量のメモリを使用しません。

非常に大きなファイルを操作することのメモリへの影響を考慮すると、問題の核心に到達します。 pasztorpisti が指摘するように、この悪い男の子が2ギガバイトのRAMで2ギガバイトのRAMを使い回すのは望ましくありません。

import sys
import hashlib

# BUF_SIZE is totally arbitrary, change for your app!
BUF_SIZE = 65536  # lets read stuff in 64kb chunks!

md5 = hashlib.md5()
sha1 = hashlib.sha1()

with open(sys.argv[1], 'rb') as f:
    while True:
        data = f.read(BUF_SIZE)
        if not data:
            break
        md5.update(data)
        sha1.update(data)

print("MD5: {0}".format(md5.hexdigest()))
print("SHA1: {0}".format(sha1.hexdigest()))

Hashlibの便利なダンディ pdate method とともに、この悪い男の子のハッシュを64kbのチャンクで更新しています。この方法では、一度にすべての人をハッシュするのにかかる2GBよりもはるかに少ないメモリを使用します!

これをテストするには:

$ mkfile 2g bigfile
$ python hashes.py bigfile
MD5: a981130cf2b7e09f4686dc273cf7187e
SHA1: 91d50642dd930e9542c39d36f0516d45f4e1af0d
$ md5 bigfile
MD5 (bigfile) = a981130cf2b7e09f4686dc273cf7187e
$ shasum bigfile
91d50642dd930e9542c39d36f0516d45f4e1af0d  bigfile

お役に立てば幸いです!

また、これらすべては右側のリンクされた質問で概説されています: Pythonで大きなファイルのMD5ハッシュを取得


補遺!

一般的にpythonを書くときは、次の習慣を身につけるのに役立ちます pep-8 。たとえば、python変数では通常、キャメルケースではなくアンダースコアで区切られます。しかし、それは単なるスタイルであり、悪いスタイルを読まなければならない人を除いて、誰もそれらのことを本当に気にかけません...

100
Randall Hunt

ファイルのハッシュ値を正しく効率的に計算するには(Python 3):

  • ファイルをバイナリモードで開き(つまり、ファイルモードに'b'を追加)、文字エンコードと行末変換の問題を回避します。
  • ファイル全体をメモリに読み込まないでください。メモリの無駄です。代わりに、ブロックごとに順番に読み取り、各ブロックのハッシュを更新します。
  • 既に最適なブロックサイズを使用しているため、ダブルバッファリングを排除します。つまり、バッファIOを使用しません。
  • readinto()を使用して、バッファチャーニングを回避します。

例:

import hashlib

def sha256sum(filename):
    h  = hashlib.sha256()
    b  = bytearray(128*1024)
    mv = memoryview(b)
    with open(filename, 'rb', buffering=0) as f:
        for n in iter(lambda : f.readinto(mv), 0):
            h.update(mv[:n])
    return h.hexdigest()
35
maxschlepzig

ファイルをバイナリモードで開きます。open()のデフォルトモードは'r'で、「テキストモードで読み取り用に開く」です。テキストモードでは、データに対して改行変換が実行されるため、プラットフォーム固有のバグも発生する可能性がありますが、テキストモードの結果として発生する可能性のある問題は、「\ r\n」シーケンスが「\ n」シーケンスに置き換えられることですあなたが手に入れる文字列。特にバイナリファイルの場合、すべてのファイルに「\ r\n」シーケンスが含まれているわけではないため、バグは常に発生するわけではなく、キャッチするのは困難です。

openedFile = open(inputFile, 'rb')

ここには別の小さな問題があります。1つの大きなチャンクでファイルを読み取ります。小さい数キロバイトのチャンクで読み取ることにより、使用可能なメモリに収まらない場合でも非常に大きなファイルをハッシュできます。

6
pasztorpisti

私は単に提案します:

def get_digest(file_path):
    h = hashlib.sha256()

    with open(file_path, 'rb') as file:
        while True:
            # Reading is buffered, so we can read smaller chunks.
            chunk = file.read(h.block_size)
            if not chunk:
                break
            h.update(chunk)

    return h.hexdigest()

ここにある他のすべての答えは複雑すぎるようです。 Pythonは読み取り時に既にバッファリングされているため(理想的な方法で、または基礎となるストレージに関する詳細情報がある場合はそのバッファリングを構成します)、ハッシュ関数が理想を見つけたチャンクで読み取る方が高速であるか、ハッシュ関数を計算するために、CPUをあまり使用しないようにします。したがって、バッファリングを無効にして自分でエミュレートしようとする代わりに、Pythonバッファリングを使用して、制御する必要があるものを制御します。つまり、データのコンシューマが理想的なハッシュブロックサイズを見つけます。

3
Mitar

異なるアルゴリズムで大きなファイルをハッシュできるモジュールをプログラムしました。

pip3 install py_essentials

次のようなモジュールを使用します。

from py_essentials import hashing as hs
hash = hs.fileChecksum("path/to/the/file.txt", "sha256")
2
phyyyl
import hashlib
user = input("Enter ")
h = hashlib.md5(user.encode())
h2 = h.hexdigest()
with open("encrypted.txt","w") as e:
    print(h2,file=e)


with open("encrypted.txt","r") as e:
    p = e.readline().strip()
    print(p)
2
Ome Mishra