Из-за pigeonhole principle не хэш-функции может генерировать хэши, которые являются уникальными/противоударными. Хорошая функция хэширования устойчива к столкновениям и затрудняет создание файла, который создает заданный хеш. Разработка хорошей хэш-функции - это передовая тема, и я, конечно, не специалист в этой области. Однако, поскольку мой код основан на sha256, он должен быть довольно устойчивым к столкновению, и, надеюсь, также сложно создать файл, который создает указанный хэш, но я не могу гарантировать никаких гарантий в этом отношении.
Это возобновляемая хэш-функция, основанная на sha256, которая довольно быстро. Требуется около 44 секунд для хэширования 1,4-гигабайтного файла на моем 2 ГГц компьютере с 2 ГБ оперативной памяти.
persistent_hash.py
#! /usr/bin/env python
''' Use SHA-256 to make a resumable hash function
The file is divided into fixed-sized chunks, which are hashed separately.
The hash of each chunk is combined into a hash for the whole file.
The hashing process may be interrupted by Control-C (SIGINT) or SIGTERM.
When a signal is received, hashing continues until the end of the
current chunk, then the file position and current hex digest is saved
to a file. The name of this file is formed by appending '.hash' to the
name of the file being hashed.
Just re-run the program to resume hashing. The '.hash' file will be deleted
once hashing is completed.
Written by PM 2Ring 2014.11.11
'''
import sys
import os
import hashlib
import signal
quit = False
blocksize = 1<<16 # 64kB
blocksperchunk = 1<<10
chunksize = blocksize * blocksperchunk
def handler(signum, frame):
global quit
print "\nGot signal %d, cleaning up." % signum
quit = True
def do_hash(fname):
hashname = fname + '.hash'
if os.path.exists(hashname):
with open(hashname, 'rt') as f:
data = f.read().split()
pos = int(data[0])
current = data[1].decode('hex')
else:
pos = 0
current = ''
finished = False
with open(fname, 'rb') as f:
f.seek(pos)
while not (quit or finished):
full = hashlib.sha256(current)
part = hashlib.sha256()
for _ in xrange(blocksperchunk):
block = f.read(blocksize)
if block == '':
finished = True
break
part.update(block)
full.update(part.digest())
current = full.digest()
pos += chunksize
print pos
if finished or quit:
break
hexdigest = full.hexdigest()
if quit:
with open(hashname, 'wt') as f:
f.write("%d %s\n" % (pos, hexdigest))
elif os.path.exists(hashname):
os.remove(hashname)
return (not quit), pos, hexdigest
def main():
if len(sys.argv) != 2:
print "Calculate resumable hash of a file."
print "Usage:\npython %s filename\n" % sys.argv[0]
exit(1)
fname = sys.argv[1]
signal.signal(signal.SIGINT, handler)
signal.signal(signal.SIGTERM, handler)
print do_hash(fname)
if __name__ == '__main__':
main()
Что вы имеете в виду именно с "уникальным" и "столкновение резистентной"? –
@ErwinSmout Дорогой друг, вопрос обновлен. Теперь вы можете отменить свою Downvote. –
Вероятно, вы получили нисходящий ответ на этот вопрос, потому что SO не является службой написания кода и потому, что вы не отправили какой-либо собственный код. –