坚持SHA256哈希对象? [英] Persisting sha256 hash objects?

查看:179
本文介绍了坚持SHA256哈希对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一个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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆