坚持SHA256哈希对象? [英] Persisting sha256 hash objects?
问题描述
我需要一个Python / C / C ++ / Java实现可暂停散列进步和商品在文件中以这样的方式取得的进展,进度是<强>恢复从该文件在后一阶段。
没有什么语言是从上面列出的书面材料时,应适当在Python工作。这是建议您可以提供与hashlib很好地工作但它是没有必要的。此外,如果这样的事情存在,该链路是足够的。
一个想法后,你的实现应该实现的。
进口hashlib
进口hashpersist#这个是必要的。SHA256 = hashlib.sha256(你好)
hashpersist.save_state(SHA256,开('test_file里面','W'))sha256_recovered = hashpersist.load_state(开放(test_file里面','R'))
sha256_recovered.update(世界)
打印sha256_recovered.hexdigest()
这应该给了相同的输出,我们做了与标准的SHA256功能的Hello World的简单散列。
a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e
原来更容易比我想象的要重写hashlib是可恢复的,最少,SHA-256的部分。我花了一些时间与使用OpenSSL加密库C code打,但后来我意识到,我并不需要所有的东西,我可以只使用ctypes的。
rehash.py
#!在/ usr /斌/包膜蟒蛇'''使用的ctypes与OpenSSL的密码库SHA-256的可恢复执行 撰稿PM 2Ring 2014年11月13日
'''从ctypes的导入*SHA_LBLOCK = 16
SHA256_DIGEST_LENGTH = 32类SHA256_CTX(结构):
_fields_ = [
(H,c_long * 8),
(NL,c_long)
(新罕布什尔,c_long)
(数据,c_long * SHA_LBLOCK)
(民,c_uint)
(md_len,c_uint)
]HashBuffType = c_ubyte * SHA256_DIGEST_LENGTH#crypto = cdll.LoadLibrary(libcrypto.so)
密码= cdll.LoadLibrary(LIBEAY32.DLL如果os.name ==NT其他libssl.so)SHA256类(对象):
digest_size = SHA256_DIGEST_LENGTH 高清__init __(自我,datastr =无):
self.ctx = SHA256_CTX()
crypto.SHA256_Init(按地址(self.ctx))
如果datastr:
self.update(datastr) 高清更新(自我,datastr):
crypto.SHA256_Update(按地址(self.ctx),datastr,c_int的(LEN(datastr))) #Clone当前上下文
高清_copy_ctx(个体经营):
CTX = SHA256_CTX()
指针(CTX)[0] = self.ctx
返回CTX 高清拷贝(个体经营):
其他= SHA256()
other.ctx = self._copy_ctx()
返回其它 高清消化(个体经营):
万一#preserve背景下,我们被调用之前散列是
#真正完成,因为SHA256_Final()清除SHA256_CTX
CTX = self._copy_ctx()
hashbuff = HashBuffType()
crypto.SHA256_Final(hashbuff,按地址(self.ctx))
self.ctx = CTX
返回STR(ByteArray的(hashbuff)) 高清hexdigest(个体经营):
返回self.digest()。EN code(十六进制)#Tests
高清的main():
cPickle的进口
进口hashlib 数据=(没有人希望,在spammish,征收!) 打印老调重弹\\ n 啥啊= SHA256(''。加入(数据))
打印shaA.hexdigest()
印刷再版(shaA.digest())
打印消化大小=,shaA.digest_size
打印 沙巴= SHA256()
shaB.update(数据[0])
打印shaB.hexdigest() #TEST酸洗
sha_pickle = cPickle.dumps(沙巴,-1)
打印泡菜长:LEN(sha_pickle)
汇众= cPickle.loads(sha_pickle) shaC.update(数据[1])
打印shaC.hexdigest() #TEST复制。需要注意的是副本可以腌制
鲥鱼= shaC.copy() shaC.update(数据[2])
打印shaC.hexdigest()
#Verify对hashlib.sha256()
打印\\ nhashlib \\ n 鲥鱼= hashlib.sha256(''。加入(数据))
打印shaD.hexdigest()
印刷再版(shaD.digest())
打印消化大小=,shaD.digest_size
打印 SHAE = hashlib.sha256(数据[0])
打印shaE.hexdigest() shaE.update(数据[1])
打印shaE.hexdigest() #TEST复制。需要注意的是hashlib副本无法进行腌制
shaF = shaE.copy()
shaF.update(数据[2])
打印shaF.hexdigest()
如果__name__ =='__main__':
主要()
resumable_SHA-256.py
#!在/ usr /斌/包膜蟒蛇'''可恢复的SHA-256散列使用OpenSSL的密码库的大文件 散列过程可以由控制-C(SIGINT)和SIGTERM中断。
当接收到一个信号,散列继续直至结束
当前组块,则当前文件的位置,总文件大小,并
沙对象保存到一个文件中。该文件的名称由形成
追加'.hash'到的文件的名称被散列。 只是重新运行该程序以恢复散列。在.hash文件将被删除
一旦散列完毕。 撰稿PM 2Ring 2014年11月14日
'''cPickle的进口泡菜作为
进口OS
进口信号
进口SYS进口翻版退出=假块大小= 1&LT;&LT; 16#64kB的
blocksperchunk = 1&所述;&下; 8块大小=块大小* blocksperchunk高清处理器(正负号,车架):
全球退出
打印\\ nGot信号%d个,清理。 %正负号
退出= TRUE
高清do_hash(FNAME,文件大小):
hashname = FNAME +.hash
如果os.path.exists(hashname):
开放(hashname,RB)为f:
POS,FSIZE,沙=和pickle.load(F)
如果FSIZE =文件大小!
打印错误:%s的文件大小不匹配记录在%s的大小%(FNAME,hashname)
打印%d个!=%d个。中止%(FSIZE,文件大小)
出口(1)
其他:
POS,FSIZE,沙= 0,文件大小,rehash.sha256() 成品=假
开放(FNAME,RB)为f:
f.seek(POS)
而不是(退出或完成):
对于在_的xrange(blocksperchunk):
块= f.read(块大小)
如果块=='':
成品= TRUE
打破
sha.update(块) POS + =块大小
sys.stderr.write(%6.2f %%%d个\\ r的%(100.0 * POS / FSIZE,FSIZE))
如果完成或退出:
打破 如果不干了:
开放(hashname,世行)为f:
和pickle.dump((POS,FSIZE,SHA),F -1)
ELIF os.path.exists(hashname):
os.remove(hashname) 返回(不退出),POS,sha.hexdigest()
高清的main():
如果len(sys.argv中)= 2!
打印文件的可恢复SHA-256散列。
打印用法:\\ npython%s的文件名\\ n%sys.argv中[0]
出口(1) FNAME = sys.argv中[1]
文件大小= os.path.getsize(FNAME) signal.signal(signal.SIGINT,处理程序)
signal.signal(signal.SIGTERM,处理程序) 完成后,POS机,hexdigest = do_hash(FNAME,文件大小)
如果完成:
打印%s%S%(hexdigest,FNAME)
其他:
打印%FNAME'%s'的不完整的SHA-256散列
打印%的%hexdigest
打印%D /%d字节进行处理。 %(POS,文件大小)
如果__name__ =='__main__':
主要()
演示
进口翻版
进口泡菜
沙= rehash.sha256(你好)
S = pickle.dumps(sha.ctx)
沙= rehash.sha256()
sha.ctx = pickle.loads(S)
sha.update(世界)
打印sha.hexdigest()
输出
a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e
修改
我只是做了小修改,以允许翻版
在Windows上工作,太,虽然我只测试了它在WinXP。在的libeay32.dll
可在当前目录下,或者在某个系统库搜索路径,如: WINDOWS \\ SYSTEM32
。我相当古老的(而且大多未使用)XP安装找不到.dll文件,即使它使用OpenOffice和查杀。于是我就从查杀文件夹,SYSTEM32复制它。而现在它完美。 :)
I need a Python/C/C++/Java implementation which can pause hashing progress and store that progress in a file in such a way that the progress is recoverable from that file at a later stage.
No matter in what language it is written from above listed, it should work properly in Python. It is recommend that you may provide that to work well with "hashlib" however it is not necessary. Also, if such a thing already exist, a link to that is sufficient.
For an idea, what your implementation should achieve.
import hashlib
import hashpersist #THIS IS NEEDED.
sha256 = hashlib.sha256("Hello ")
hashpersist.save_state(sha256, open('test_file', 'w'))
sha256_recovered = hashpersist.load_state(open('test_file', 'r'))
sha256_recovered.update("World")
print sha256_recovered.hexdigest()
This should give the same output as we had done simple hashing of "Hello World" with standard sha256 function.
a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e
It turned out to be easier than I thought to rewrite hashlib to be resumable, at least, the SHA-256 portion. I spent some time playing with C code that uses the OpenSSL crypto library, but then I realised that I don't need all that stuff, I can just use ctypes.
rehash.py
#! /usr/bin/env python
''' A resumable implementation of SHA-256 using ctypes with the OpenSSL crypto library
Written by PM 2Ring 2014.11.13
'''
from ctypes import *
SHA_LBLOCK = 16
SHA256_DIGEST_LENGTH = 32
class SHA256_CTX(Structure):
_fields_ = [
("h", c_long * 8),
("Nl", c_long),
("Nh", c_long),
("data", c_long * SHA_LBLOCK),
("num", c_uint),
("md_len", c_uint)
]
HashBuffType = c_ubyte * SHA256_DIGEST_LENGTH
#crypto = cdll.LoadLibrary("libcrypto.so")
crypto = cdll.LoadLibrary("libeay32.dll" if os.name == "nt" else "libssl.so")
class sha256(object):
digest_size = SHA256_DIGEST_LENGTH
def __init__(self, datastr=None):
self.ctx = SHA256_CTX()
crypto.SHA256_Init(byref(self.ctx))
if datastr:
self.update(datastr)
def update(self, datastr):
crypto.SHA256_Update(byref(self.ctx), datastr, c_int(len(datastr)))
#Clone the current context
def _copy_ctx(self):
ctx = SHA256_CTX()
pointer(ctx)[0] = self.ctx
return ctx
def copy(self):
other = sha256()
other.ctx = self._copy_ctx()
return other
def digest(self):
#Preserve context in case we get called before hashing is
# really finished, since SHA256_Final() clears the SHA256_CTX
ctx = self._copy_ctx()
hashbuff = HashBuffType()
crypto.SHA256_Final(hashbuff, byref(self.ctx))
self.ctx = ctx
return str(bytearray(hashbuff))
def hexdigest(self):
return self.digest().encode('hex')
#Tests
def main():
import cPickle
import hashlib
data = ("Nobody expects ", "the spammish ", "imposition!")
print "rehash\n"
shaA = sha256(''.join(data))
print shaA.hexdigest()
print repr(shaA.digest())
print "digest size =", shaA.digest_size
print
shaB = sha256()
shaB.update(data[0])
print shaB.hexdigest()
#Test pickling
sha_pickle = cPickle.dumps(shaB, -1)
print "Pickle length:", len(sha_pickle)
shaC = cPickle.loads(sha_pickle)
shaC.update(data[1])
print shaC.hexdigest()
#Test copying. Note that copy can be pickled
shaD = shaC.copy()
shaC.update(data[2])
print shaC.hexdigest()
#Verify against hashlib.sha256()
print "\nhashlib\n"
shaD = hashlib.sha256(''.join(data))
print shaD.hexdigest()
print repr(shaD.digest())
print "digest size =", shaD.digest_size
print
shaE = hashlib.sha256(data[0])
print shaE.hexdigest()
shaE.update(data[1])
print shaE.hexdigest()
#Test copying. Note that hashlib copy can NOT be pickled
shaF = shaE.copy()
shaF.update(data[2])
print shaF.hexdigest()
if __name__ == '__main__':
main()
resumable_SHA-256.py
#! /usr/bin/env python
''' Resumable SHA-256 hash for large files using the OpenSSL crypto library
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 current file position, total file size, and
the sha object 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.14
'''
import cPickle as pickle
import os
import signal
import sys
import rehash
quit = False
blocksize = 1<<16 # 64kB
blocksperchunk = 1<<8
chunksize = blocksize * blocksperchunk
def handler(signum, frame):
global quit
print "\nGot signal %d, cleaning up." % signum
quit = True
def do_hash(fname, filesize):
hashname = fname + '.hash'
if os.path.exists(hashname):
with open(hashname, 'rb') as f:
pos, fsize, sha = pickle.load(f)
if fsize != filesize:
print "Error: file size of '%s' doesn't match size recorded in '%s'" % (fname, hashname)
print "%d != %d. Aborting" % (fsize, filesize)
exit(1)
else:
pos, fsize, sha = 0, filesize, rehash.sha256()
finished = False
with open(fname, 'rb') as f:
f.seek(pos)
while not (quit or finished):
for _ in xrange(blocksperchunk):
block = f.read(blocksize)
if block == '':
finished = True
break
sha.update(block)
pos += chunksize
sys.stderr.write(" %6.2f%% of %d\r" % (100.0 * pos / fsize, fsize))
if finished or quit:
break
if quit:
with open(hashname, 'wb') as f:
pickle.dump((pos, fsize, sha), f, -1)
elif os.path.exists(hashname):
os.remove(hashname)
return (not quit), pos, sha.hexdigest()
def main():
if len(sys.argv) != 2:
print "Resumable SHA-256 hash of a file."
print "Usage:\npython %s filename\n" % sys.argv[0]
exit(1)
fname = sys.argv[1]
filesize = os.path.getsize(fname)
signal.signal(signal.SIGINT, handler)
signal.signal(signal.SIGTERM, handler)
finished, pos, hexdigest = do_hash(fname, filesize)
if finished:
print "%s %s" % (hexdigest, fname)
else:
print "sha-256 hash of '%s' incomplete" % fname
print "%s" % hexdigest
print "%d / %d bytes processed." % (pos, filesize)
if __name__ == '__main__':
main()
demo
import rehash
import pickle
sha=rehash.sha256("Hello ")
s=pickle.dumps(sha.ctx)
sha=rehash.sha256()
sha.ctx=pickle.loads(s)
sha.update("World")
print sha.hexdigest()
output
a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e
edit
I've just made a minor edit to allow rehash
to work on Windows, too, although I've only tested it on WinXP. The libeay32.dll
can be in the current directory, or somewhere in the system library search path, eg WINDOWS\system32
. My rather ancient (and mostly unused) XP installation couldn't find the .dll, even though it's used by OpenOffice and Avira. So I just copied it from the Avira folder to system32. And now it works perfectly. :)
这篇关于坚持SHA256哈希对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!