পাইথনে একটি ফাইল হ্যাশ করছে


101

আমি পাইথনটি ইওএফ-তে পড়তে চাই যাতে আমি একটি উপযুক্ত হ্যাশ পেতে পারি, এটি sha1 বা এমডি 5। সাহায্য করুন. আমার এখন পর্যন্ত যা আছে তা এখানে:

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

6
এবং সমস্যা কি?
ইসেদেভ

4
আমি এটি একটি ফাইল হ্যাশ করতে সক্ষম হতে চান। ইওএফ না হওয়া পর্যন্ত এটি পড়া দরকার, ফাইলের আকার যাই হোক না কেন।
user3358300

4
যে ঠিক কি file.read()না - সম্পূর্ণ ফাইল পড়া।
ইসেদেভ

read()পদ্ধতির জন্য ডকুমেন্টেশন বলে?
ইগনাসিও ওয়াজকেজ-আব্রামস

আপনার "হ্যাশিং কি?" এর মধ্য দিয়ে যাওয়া উচিত।
শরীফ মামুন

উত্তর:


141

টিএল; ডিআর টন মেমরি ব্যবহার না করতে বাফার ব্যবহার করে।

আমরা আপনার সমস্যা মূল অংশ পেতে, আমি বিশ্বাস করি, আমরা যখন সঙ্গে কাজ স্মৃতির প্রভাব বিবেচনা খুব বড় ফাইল । আমরা চাই না যে এই খারাপ ছেলেটি 2 গিগাবাইট ফাইলের জন্য 2 জিগ র্যামের মধ্যে মন্থন করুক , সুতরাং পাস্তোরপিস্তিটি উল্লেখ করেছেন যে, আমরা এই বড় ফাইলগুলিকে খণ্ডগুলিতে ডিল করব!

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

আমরা যা করেছি তা হ্যাশলিবের হ্যান্ডি ড্যান্ডি আপডেট পদ্ধতির সাথে যেতে যেতে আমরা 64kb খণ্ডে এই খারাপ ছেলের হ্যাশগুলি আপডেট করছি । এইভাবে আমরা লোকটিকে একসাথে হ্যাশ করতে যে 2 জিবি লাগবে তার চেয়ে অনেক কম স্মৃতি ব্যবহার করব!

আপনি এটি দিয়ে পরীক্ষা করতে পারেন:

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

আশা করি এইটি কাজ করবে!

এছাড়াও এগুলি সমস্তই ডানদিকে সংযুক্ত প্রশ্নে বর্ণিত হয়েছে: পাইথনে বড় ফাইলগুলির MD5 হ্যাশ পান


সংযোজন!

সাধারণত পাইথন লেখার সময় এটি পিপ -8 অনুসরণ করার অভ্যাসে যেতে সহায়তা করে । উদাহরণস্বরূপ, পাইথন ভেরিয়েবলগুলিতে সাধারণত আন্ডারস্কোর বিচ্ছিন্নভাবে উট কেসড থাকে। তবে এটি কেবল শৈলী এবং খারাপ স্টাইল পড়তে হবে এমন লোকদের ব্যতীত কেউই আসলে সেগুলি সম্পর্কে চিন্তা করে না ... যা হতে পারে আপনি এখন থেকে এই কোডগুলি বছর পরে পড়তে পারেন।


@ ইরানমান হ্যালো, আমি {0} "। ফর্ম্যাট (sha1.hexdigest ()) অংশটি পাইনি। আমরা কেবল sha1.hexdigest () ব্যবহার করার পরিবর্তে কেন এটি ব্যবহার করব?
বেলিয়াল

@ বিলিয়াল কি কাজ করছে না? আমি কেবল দুটি হ্যাশের মধ্যে পার্থক্য করার জন্য এটি ব্যবহার করছিলাম ...
র্যান্ডাল হান্ট

@ ইরানমান সবকিছু কাজ করছে, আমি কখনই এটি ব্যবহার করি নি এবং এটি সাহিত্যে দেখিনি। "{0}"। ফর্ম্যাট () ... আমার অজানা। :)
Belial

4
আমি কীভাবে নির্বাচন করব BUF_SIZE?
মার্টিন থোমা

4
এটি shasumবাইনারিগুলির মতো একই ফলাফল তৈরি করে না । নীচে তালিকাভুক্ত অন্য উত্তর (মেমরির ভিউ ব্যবহার করে একটি) অন্যান্য হ্যাশিং সরঞ্জামগুলির সাথে সামঞ্জস্যপূর্ণ।
tedivm

61

কোনও ফাইলের হ্যাশ মানের সঠিক এবং দক্ষ গণনার জন্য (পাইথন 3 এ):

  • 'b'অক্ষর এনকোডিং এবং লাইন-শেষের রূপান্তর সংক্রান্ত সমস্যাগুলি এড়ানোর জন্য ফাইলটিকে বাইনারি মোডে (যেমন ফাইলমোডে যুক্ত করুন) খুলুন ।
  • সম্পূর্ণ ফাইলটিকে মেমোরিতে পড়বেন না, কারণ এটি মেমরির অপচয়। পরিবর্তে, ক্রমানুসারে এটি ব্লক করে ব্লকটি পড়ুন এবং প্রতিটি ব্লকের জন্য হ্যাশ আপডেট করুন।
  • ডাবল বাফারিং বাদ দিন, অর্থাত্ বাফারড আইও ব্যবহার করবেন না, কারণ আমরা ইতিমধ্যে একটি সর্বোত্তম ব্লকের আকার ব্যবহার করি।
  • 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()

4
আপনি কীভাবে জানবেন যে সর্বোত্তম ব্লকের আকার কী?
মিতার

4
@ মিটার, একটি নিম্ন সীমাটি সর্বোচ্চ দৈহিক ব্লকের (প্রথাগতভাবে 512 বাইট বা নতুন ডিস্ক সহ 4KiB) এবং সিস্টেম পৃষ্ঠার আকার (অনেক সিস্টেমে 4KiB, অন্যান্য সাধারণ পছন্দ: 8KiB এবং 64 কিবি)) তারপরে আপনি মূলত কিছু বেঞ্চমার্কিং করেন এবং / অথবা প্রকাশিত বেঞ্চমার্ক ফলাফল এবং সম্পর্কিত কাজটি দেখুন (যেমন বর্তমানের আরএসসিএনসি / জিএনইউ সিপি / ... কী ব্যবহার করছেন তা পরীক্ষা করে দেখুন)।
ম্যাক্সচলেপজিগ

চান resource.getpagesize, এখানে কোন কাজে যদি আমরা কিছুটা পরিবর্তনশীল এটা নিখুত চেষ্টা চেয়েছিলেন? আর কি mmap?
jpmc26

@ jpmc26, getpagesize () এখানে তেমন কার্যকর নয় - সাধারণ মানগুলি 4 কিবি বা 8 কিবি, এই পরিসরের কিছু, যেমন 128 কিবি - 128 কিবি থেকে খুব ছোট কিছু সাধারণত একটি ভাল পছন্দ। এমএমএপটি আমাদের ব্যবহারের ক্ষেত্রে তেমন কোনও সহায়তা করে না কারণ আমরা ক্রমান্বয়ে পুরো ফাইলটি সামনে থেকে পিছনে পড়ে থাকি। অ্যাক্সেস প্যাটার্নের মতো আরও এলোমেলো অ্যাক্সেসের মতো এমএমএ্যাপের সুবিধাগুলি রয়েছে, যদি পৃষ্ঠাগুলি একাধিকবার অ্যাক্সেস করা হয় এবং / অথবা এটি এমএমএপি পড়ার বাফার ব্যবস্থাপনাকে সহজ করে তোলে।
ম্যাক্সচলেপজিগ

4
আমি প্রায় ১66 জিবি এবং শেআসাম অ্যালগরিদমের একটি ফাইল সহ (১) @ র্যান্ডল হান্ট এবং (২) আপনার (এই ক্রমে ফাইল ক্যাশে করার কারণে গুরুত্বপূর্ণ) এর সমাধান দুটিই বেনমার্ক করেছি। 20 * 4096 (PAGE_SIZE) এর বাফার ব্যবহারের জন্য সমাধান 1 সংশোধন করা হয়েছিল এবং বাফারিং প্যারামিটার 0 তে সেট করা হয়েছে সলিউশন 2 কেবলমাত্র অ্যালগরিদমকে সংশোধন করা হয়েছিল (sha256 -> sha1)। ফলাফল: (1) 3 এম 37.137 এস (2) 3 এম 30.003 এস। বাইনারি মোডে নেটিভ sha1sum: 3m31.395s
বায়োইনফোর্নেটিক্স

18

আমি সহজভাবে প্রস্তাব করব:

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

এখানে অন্য সমস্ত উত্তর খুব জটিল বলে মনে হচ্ছে। পাইথন ইতিমধ্যে পড়ার সময় বাফার করছে (আদর্শ পদ্ধতিতে, বা আপনি যদি অন্তর্নিহিত স্টোরেজ সম্পর্কে আরও তথ্য রাখেন তবে আপনি সেই বাফারিংটি কনফিগার করেন) এবং তাই হ্যাশ ফাংশনটি আদর্শ হিসাবে খুঁজে পাওয়া ভাল যা এটি দ্রুত বা কম সিপিইউতে নিবিড়তর করে তোলে finds হ্যাশ ফাংশন গণনা করুন। সুতরাং বাফারিংটি অক্ষম করার এবং এটি নিজেই অনুকরণ করার চেষ্টা করার পরিবর্তে আপনি পাইথন বাফারিং ব্যবহার করেন এবং আপনার কী নিয়ন্ত্রণ করা উচিত তা নিয়ন্ত্রণ করুন: আপনার ডেটার ভোক্তা যা আদর্শ, হ্যাশ ব্লকের আকার খুঁজে পান।


নিখুঁত উত্তর, তবে এটি দুর্দান্ত হবে, যদি আপনি সম্পর্কিত ডক দিয়ে আপনার বক্তব্যগুলি ফিরিয়ে দেন: পাইথন 3 - উন্মুক্ত () এবং পাইথন 2 - উন্মুক্ত () । এমনকি উভয়ের মধ্যে পার্থক্য মনে করুন, পাইথন 3 এর পদ্ধতিটি আরও পরিশীলিত। তবুও, আমি সত্যিই ভোক্তা কেন্দ্রিক দৃষ্টিভঙ্গি প্রশংসা!
মুরমেল

hash.block_sizeঠিক 'হ্যাশ অ্যালগরিদমের অভ্যন্তরীণ ব্লক আকার' হিসাবে নথিভুক্ত করা হয়। হাশলিব এটিকে আদর্শ মনে করে না । প্যাকেজ ডকুমেন্টেশনের কোনও কিছুই এটি মাপের ইনপুট পছন্দ করে না বলে প্রস্তাব দেয় । আপনি যদি এটির মতো ফোন করেন তবে এটি কম সিপিইউ ব্যবহার করে না। আপনার কলটি অনেকগুলি অপ্রয়োজনীয় অবজেক্ট তৈরি এবং ফাইল বাফার থেকে আপনার নতুন খণ্ড বাইটস অবজেক্টে অনাবশ্যক কপিগুলিতে নিয়ে যায়। update()hash.block_sizefile.read()
ম্যাক্সচলেপজিগ

হ্যাশগুলি খণ্ডগুলিতে তাদের রাজ্য আপডেট করে block_size। আপনি যদি তাদের এই অংশগুলিতে সরবরাহ না করে থাকেন তবে তাদের বাফার করতে হবে এবং পর্যাপ্ত ডেটা উপস্থিত হওয়ার জন্য অপেক্ষা করতে হবে, বা প্রদত্ত ডেটাটিকে অভ্যন্তরীণভাবে ভাগ করে দেবে। সুতরাং, আপনি কেবল এটি বাইরের দিকে পরিচালনা করতে পারেন এবং তারপরে অভ্যন্তরীণভাবে যা ঘটে তা সরল করুন। আমি এই আদর্শ খুঁজে। উদাহরণস্বরূপ দেখুন: stackoverflow.com/a/51335622/252025
মিতার

block_sizeকোন দরকারী পঠিত আকার তুলনায় অনেক ছোট। এছাড়াও, যে কোনও কার্যকর ব্লক এবং পঠন মাপ দুটি হ'ল ক্ষমতা। সুতরাং, পড়ার আকারটি সম্ভবত শেষের ব্যতীত সমস্ত পাঠের জন্য ব্লকের আকার দ্বারা বিভাজ্য। উদাহরণস্বরূপ, sha256 ব্লকের আকার 64 বাইট। এর অর্থ এটি যে update()কোনও একটিতে কোনও বাফারিং ছাড়াই সরাসরি ইনপুটটি প্রক্রিয়া করতে সক্ষম block_size। সুতরাং, কেবলমাত্র শেষ পঠনটি যদি ব্লকের আকার দ্বারা বিভাজ্য না হয় তবে একবারে একবারে এটি 63 বাইট পর্যন্ত বাফার করতে হবে। সুতরাং, আপনার শেষ মন্তব্যটি ভুল এবং আপনি নিজের উত্তরে যে দাবি করছেন তা সমর্থন করে না।
maxschlepzig

মুল বক্তব্যটি হল যে কাউকে বাফারিং অনুকূল করতে হবে না কারণ এটি পড়ার সময় পাইথন ইতিমধ্যে সম্পন্ন করেছে। সুতরাং আপনাকে কেবলমাত্র বিদ্যমান বাফারটির উপর হ্যাশ করার সময় আপনি কী পরিমাণ লুপিং করতে চান তা ঠিক করতে হবে।
মিতার

6

আমি একটি মডিউল প্রোগ্রাম করেছি যা বিভিন্ন অ্যালগরিদমের সাহায্যে বড় ফাইল হ্যাশ করতে সক্ষম।

pip3 install py_essentials

মডিউলটি এটির মতো ব্যবহার করুন:

from py_essentials import hashing as hs
hash = hs.fileChecksum("path/to/the/file.txt", "sha256")

এটি কি ক্রস প্ল্যাটফর্ম (লিনাক্স + উইন)? এটি পাইথন 3 নিয়ে কাজ করছে? এছাড়াও এটি এখনও বজায় রাখা হয়?
বাসজ

5

এখানে পাইথন 3, পসিক্স সলিউশন (উইন্ডোজ নয়!) ব্যবহার mmapকরে মেমরিটিতে বস্তুটি মানচিত্রের জন্য ব্যবহার করা হয়।

import hashlib
import mmap

def sha256sum(filename):
    h  = hashlib.sha256()
    with open(filename, 'rb') as f:
        with mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ) as mm:
            h.update(mm)
    return h.hexdigest()

নিষ্পাপ প্রশ্ন ... mmapএই পরিস্থিতিতে ব্যবহার করে কী লাভ ?
জোনাথন বি

4
@ জোনাথনবি। বেশিরভাগ পদ্ধতি অযথা bytesমেমরিতে অবজেক্ট তৈরি করে এবং readখুব বেশি বা খুব কম সময়ে কল করে। এটি ফাইলটি সরাসরি ভার্চুয়াল মেমরিতে ম্যাপ করবে এবং সেখান থেকে এটি হ্যাশ করবে - অপারেটিং সিস্টেমটি ফাইলের সামগ্রীগুলি সরাসরি বাফার ক্যাশে থেকে পঠন প্রক্রিয়াটিতে ম্যাপ করতে পারে। এই ওপর এক উল্লেখযোগ্য গুণক দ্বারা দ্রুত হতে পারে এর মানে হল এই এক
Antti Haapala

@ জোনাথনবি। আমি পরীক্ষাটি করেছিলাম এবং পার্থক্যটি এই ক্ষেত্রে তাত্পর্যপূর্ণ নয় , আমরা ভোটাভুটি পদ্ধতিতে ~ 15% সম্পর্কে কথা বলছি।
এন্টি হাপাল

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

4
আপনি মূলত এমনটি করছেন echo $USER_INPUT | md5sum > encrypted.txt && cat encrypted.txtযা ফাইলগুলির হ্যাশিংয়ের সাথে সম্পর্কিত নয় বিশেষত বড়দের সাথে নয়।
মুরমেল

4
হ্যাশিং! = এনক্রিপ্ট করা
বাগমনোট 123
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.