Pyleiptic与Pickle有时会失败

时间:2016-04-08 13:02:33

标签: python python-3.x openssl

如果我使用以下几次运行以下测试用例:

python3 -m unittest test_pyelliptic.py

大约15次中有一次失败。

测试用例:

import unittest, pyelliptic, pickle

class PyellipticTestCase(unittest.TestCase):
    def setUp(self):
        self.alice = pyelliptic.ECC()
        self.bob = pyelliptic.ECC()

    def test_pickleSign(self):
        tm = {"text":"contract","amount":12}
        tms1 = {"doc":tm,"c1":self.bob.get_pubkey(),"s1":self.bob.sign(pickle.dumps(tm))}
        tms2bb = {"doc":tms1,"c2":self.alice.get_pubkey(),"s2":self.alice.sign(pickle.dumps(tms1))}
        tms2 = pickle.loads(pickle.dumps(tms2bb))
        self.assertEqual(tms2['s2'],tms2bb['s2'])
        self.assertTrue(pyelliptic.ECC(pubkey=self.alice.get_pubkey()).verify(tms2bb['s2'],pickle.dumps(tms2['doc']))) #<--- FAILs sometimes

我的系统:

  • OS:14.04.1-Ubuntu(内核3.16.0-36-generic)
  • Phtyon3:Python 3.4.0(默认,2014年4月11日,13:05:18)
  • OpenSSL:1.0.1f 2014年1月6日
  • pyelliptic:1.5.7

我还在Python 3.4.3的类似系统上对此进行了测试,并且可以重现行为。

您可以在系统上重现故障吗? 如果是,是什么原因造成的?

更新

如果我用verbose(python3 -m unittest -v test_pyelliptic2.py)运行测试,它会产生以下输出(运行两次):

X@X:~/test$ python3 -m unittest -v test_pyelliptic2.py 
test_pickleSign (test_pyelliptic2.PyellipticTestCase) ... ok

----------------------------------------------------------------------
Ran 1 test in 0.012s

OK
X@X:~/test$ python3 -m unittest -v test_pyelliptic2.py 
test_pickleSign (test_pyelliptic2.PyellipticTestCase) ... FAIL

======================================================================
FAIL: test_pickleSign (test_pyelliptic2.PyellipticTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "XX/test/test_pyelliptic2.py", line 14, in test_pickleSign
    self.assertTrue(pyelliptic.ECC(pubkey=self.alice.get_pubkey()).verify(tms2bb['s2'],pickle.dumps(tms2['doc']))) #<--- FAILs sometimes
AssertionError: False is not true

----------------------------------------------------------------------
Ran 1 test in 0.013s

FAILED (failures=1)

1 个答案:

答案 0 :(得分:0)

经过一些进一步的研究后发现,二进制pickle输出取决于字典中元素的排序。 因此,以下测试用例在二进制数组的比较中失败:

def test_pickleOrder(self):
        d1 = {"test1":12,"test2":14.2,"test3":"test"}
        d2 = {"test3":"test","test1":12,"test2":14.2}       
        self.assertEqual(d1,d2)     
        d1p = pickle.dumps(d1)
        d2p = pickle.dumps(d2)      
        self.assertEqual(d1p,d2p) #<--- fails here

顺便说一句:这不仅适用于泡菜,也适用于json和bson模块