我如何从Python中派生出hashlib.sha256?
天真的尝试失败了:
import hashlib class fred(hashlib.sha256): pass -> TypeError: Error when calling the metaclass bases cannot create 'builtin_function_or_method' instances 好吧,事实证明hashlib.sha256是一个可调用的,而不是一个类.尝试更有创意的东西也不起作用: import hashlib class fred(type(hashlib.sha256())): pass f = fred -> TypeError: cannot create 'fred' instances 嗯… 那么,我该怎么做? 这是我想要实际实现的目标: class shad_256(sha256): """Double SHA - sha256(sha256(data).digest()) Less susceptible to length extension attacks than sha256 alone.""" def digest(self): return sha256(sha256.digest(self)).digest() def hexdigest(self): return sha256(sha256.digest(self)).hexdigest() 基本上我希望一切都能通过,除非有人要求结果我想插入我自己的额外步骤.是否有一种聪明的方法可以用__new__或某种类型的元类魔法来实现这一目标? 我有一个解决方案,我很满意我发布的答案,但我真的很想知道是否有人能想到更好的东西.要么更简洁,可读性成本非常低,要么更快(特别是在调用更新时),同时仍具有一定的可读性. 更新:我运行了一些测试: # test_sha._timehash takes three parameters,the hash object generator to use,# the number of updates and the size of the updates. # Built in hashlib.sha256 $python2.7 -m timeit -n 100 -s 'import test_sha,hashlib' 'test_sha._timehash(hashlib.sha256,20000,512)' 100 loops,best of 3: 104 msec per loop # My wrapper based approach (see my answer) $python2.7 -m timeit -n 100 -s 'import test_sha,hashlib' 'test_sha._timehash(test_sha.wrapper_shad_256,best of 3: 108 msec per loop # Glen Maynard's getattr based approach $python2.7 -m timeit -n 100 -s 'import test_sha,hashlib' 'test_sha._timehash(test_sha.getattr_shad_256,best of 3: 103 msec per loop 解决方法
只需使用__getattr__使您自己未定义的所有属性都回退到底层对象:
import hashlib class shad_256(object): """ Double SHA - sha256(sha256(data).digest()) Less susceptible to length extension attacks than sha256 alone. >>> s = shad_256('hello world') >>> s.digest_size 32 >>> s.block_size 64 >>> s.sha256.hexdigest() 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9' >>> s.hexdigest() 'bc62d4b80d9e36da29c16c5d4d9f11731f36052c72401a76c23c0fb5a9b74423' >>> s.nonexistant() Traceback (most recent call last): ... AttributeError: '_hashlib.HASH' object has no attribute 'nonexistant' >>> s2 = s.copy() >>> s2.digest() == s.digest() True >>> s2.update("text") >>> s2.digest() == s.digest() False """ def __init__(self,data=None): self.sha256 = hashlib.sha256() if data is not None: self.update(data) def __getattr__(self,key): return getattr(self.sha256,key) def _get_final_sha256(self): return hashlib.sha256(self.sha256.digest()) def digest(self): return self._get_final_sha256().digest() def hexdigest(self): return self._get_final_sha256().hexdigest() def copy(self): result = shad_256() result.sha256 = self.sha256.copy() return result if __name__ == "__main__": import doctest doctest.testmod() 这主要消除了更新调用的开销,但并非完全消除.如果要完全消除它,请将其添加到__init__(并相应地复制): self.update = self.sha256.update 在查找更新时,这将消除额外的__getattr__调用. 这一切都利用了Python成员函数中一个更有用且经常被忽略的属性:函数绑定.回想一下,你可以这样做: a = "hello" b = a.upper b() 因为对成员函数的引用不会返回原始函数,而是返回该函数与其对象的绑定.这就是为什么,当__getattr__返回self.sha256.update时,返回的函数正确地在self.sha256上运行,而不是self. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |