1

我正在尝试编写一个函数来 md5 散列任何 python 对象。我想在 python2 和 python3 中返回相同的 md5 值。

我知道python3中的pickle.dumps,它返回字节,而在python2中,它返回str。如您所见,以下代码现在给了我相同的字符串:

print( [      pickle.dumps( obj, protocol = 2 )   ] ) # in python2
print( [ str( pickle.dumps( obj, protocol = 2 ) ) ] ) # in python3

两者都给了我:

['\x80\x02]q\x00(U\x011q\x01K\x02U\x013q\x02K\x04e.']

但问题是,在python3中:

hashlib.md5.update( some_string )

必须进行编码。如果我在 python3 中对字符串进行编码,那么它不会给我与 python2 中相同的 md5 值。谁能给我一个解决方案?感谢你们。

这是我的代码:

from __future__ import print_function
import hashlib
import pickle
import sys

is_py2 = (sys.version_info[0] == 2)

obj = ['1',2,'3',4]
m = hashlib.md5()

if is_py2:                                                    # if it's python2
    print(    [      pickle.dumps( obj, protocol = 2 ) ] )
    m.update(        pickle.dumps( obj, protocol = 2 )   )
else:                                                         # if it's python3
    print(    [ str( pickle.dumps( obj, protocol = 2 ) ) ] )
    m.update(        pickle.dumps( obj, protocol = 2 ).encode( "utf-8" ) ) # I wish I could don not encode

print( m.hexdigest() )
4

2 回答 2

0

1)pickle.dumps将返回一个字节字符串,所以你的打印是错误的。

2)如果由于某种原因您在 unicode 字符串上有此类内容,则不能将多字节编解码器用作 utf-8(默认值)。

foo = '\x80\x02]q\x00(U\x011q\x01K\x02U\x013q\x02K\x04e.'.encode('latin-1')

latin-1将有一个 1 对 1 的映射,所以你最终会得到正确的字节。


PS:你为什么在打印中使用列表?也许你正在寻找print(repr(...))

于 2014-10-12T04:44:31.430 回答
0

有一个衬垫可以进行 2x 和 3x 编码,您可以对任何编码进行此操作。

>>> hashlib.new(algorithm, repr(object).encode()).hexdigest()

有关变量名称的完整上下文,请参见:https ://github.com/uqfoundation/klepto/blob/master/klepto/crypto.py#L26……有关编码、序列化、之类的。所有工作在 python 2.x 和 3.x 中。

我看到您希望 python 2.x 和 3.x 返回相同的哈希值。嗯...我认为这行不通。如果它有任何机会或md5在 2.x 中返回与 3.x 中相同的编码,则您可能必须先使用repror pickle(protocol 2) 或其他方式对其进行处理。

Python 2.7.8 (default, Jul 13 2014, 02:29:54) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import klepto
>>> klepto.crypto.hash(klepto.crypto.pickle(object), algorithm='md5')
'ee16782749cb00e4b66922df545877f0'

因此,pickle andmd5似乎不起作用,并且通常不应该,因为某些对象在 2.x 和 3.x 之间发生了变化(例如object,是 atype现在它是 a class)。这也意味着repr或其他类似的东西通常也不能用作编码器。

Python 3.3.5 (default, Mar 10 2014, 21:37:38) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import klepto
>>> klepto.crypto.hash(klepto.crypto.pickle(object), algorithm='md5')
'35eb4c374cafe09c8ac01661701b6b6e'

也许还有klepto其他适合您的编码器之一。

于 2014-10-12T15:58:12.997 回答