]> www.wagner.pp.ru Git - oss/ctypescrypto.git/commitdiff
Fixes some style. Improved tests coverage for bio,oid,digest and cipher. Prepare...
authorVictor Wagner <vitus@wagner.pp.ru>
Sun, 21 Dec 2014 08:47:56 +0000 (11:47 +0300)
committerVictor Wagner <vitus@wagner.pp.ru>
Sun, 21 Dec 2014 08:47:56 +0000 (11:47 +0300)
ctypescrypto/bio.py
ctypescrypto/cipher.py
ctypescrypto/digest.py
ctypescrypto/oid.py
ctypescrypto/pkey.py
ctypescrypto/rand.py
ctypescrypto/x509.py
tests/testbio.py
tests/testdigest.py
tests/testoids.py
tests/testx509.py

index 2743f705032ab407e8583c5bfe04c0a89125739b..b1700b9a869ca80dd1eba7dba1c13117782202b0 100644 (file)
@@ -42,7 +42,7 @@ class Membio(object):
                @param length - if specifed, limits amount of data read. If not BIO is read until end of buffer
                """
                if not length is None:
-                       if type(length)!=type(0):
+                       if not isinstance(length,(int,long)):
                                raise TypeError("length to read should be number")
                        buf=create_string_buffer(length)
                        readbytes=libcrypto.BIO_read(self.bio,buf,length)
index 332272570f824c9830dbe003a09c123f138b5aa7..815a42541897232853a0721b9fea12be9d42217b 100644 (file)
@@ -171,7 +171,7 @@ class Cipher:
                """
                if self.cipher_finalized :
                        raise CipherError("No updates allowed")
-               if type(data) != type(""):
+               if not isinstance(data,str):
                        raise TypeError("A string is expected")
                if len(data) <= 0:
                        return ""
index 2963e7034b19eac01bad510ff7ad389e65f0cb1c..30d77c5a57b35f19d2f0aa501f010581ae4740dc 100644 (file)
@@ -41,13 +41,29 @@ class DigestType(object):
        """\r
        def __init__(self,      digest_name):\r
                """\r
-                       Finds digest by its name\r
+                       Finds digest by its name. You can pass Oid object instead of\r
+                       name.\r
+\r
+                       Special case is when None is passed as name. In this case\r
+                       unitialized digest is created, and can be initalized later\r
+                       by setting its digest attribute to pointer to EVP_MD\r
                """\r
-               self.digest_name = digest_name\r
-               self.digest = libcrypto.EVP_get_digestbyname(self.digest_name)\r
+               if digest_name is None:\r
+                       return \r
+               if isinstance(digest_name,Oid):\r
+                       self.digest_name=digest_name.longname()\r
+                       self.digest=libcrypto.EVP_get_digestbyname(self.digest_name)\r
+               else:\r
+                       self.digest_name = str(digest_name)\r
+                       self.digest = libcrypto.EVP_get_digestbyname(self.digest_name)\r
                if self.digest is None:\r
                        raise DigestError("Unknown digest: %s" % self.digest_name)\r
 \r
+       @property\r
+       def name(self):\r
+               if not hasattr(self,'digest_name'):\r
+                       self.digest_name=Oid(libcrypto.EVP_MD_type(self.digest)).longname()\r
+               return self.digest_name\r
        def __del__(self):\r
                pass\r
        def digest_size(self):\r
@@ -69,7 +85,7 @@ class Digest(object):
                """\r
                self._clean_ctx()\r
                self.ctx = libcrypto.EVP_MD_CTX_create()\r
-               if self.ctx == 0:\r
+               if self.ctx is None:\r
                        raise DigestError("Unable to create digest context")\r
                result = libcrypto.EVP_DigestInit_ex(self.ctx, digest_type.digest, None)\r
                if result == 0:\r
@@ -92,11 +108,11 @@ class Digest(object):
                """\r
                if self.digest_finalized:\r
                        raise DigestError("No updates allowed")\r
-               if type(data) != type(""):\r
+               if not isinstance(data,str):\r
                        raise TypeError("A string is expected")\r
                if length is None:\r
-                       length=len(data)\r
-               elif length> len(data):\r
+                       length = len(data)\r
+               elif length > len(data):\r
                        raise ValueError("Specified length is greater than length of data")\r
                result = libcrypto.EVP_DigestUpdate(self.ctx, c_char_p(data), length)\r
                if result != 1:\r
index 6941ce4b399b6b353026dfa99aac02238b656e5e..8caa57a68ad766c94cb79b4d40ad99042939e113 100644 (file)
@@ -29,11 +29,13 @@ class Oid(object):
 
        def __init__(self,value):
                " Object constuctor. Accepts string or integer"
-               if type(value) == type(""):
+               if isinstance(value,unicode):
+                       value=value.encode('ascii')
+               if isinstance(value,str):
                        self.nid=libcrypto.OBJ_txt2nid(value)
                        if self.nid==0:
                                raise ValueError("Cannot find object %s in the database"%(value))
-               elif type(value) == type(0):
+               elif isinstance(value,(int,long)):
                        cn=libcrypto.OBJ_nid2sn(value)
                        if cn is None:
                                raise ValueError("No such nid %d in the database"%(value))
index 85b831d96c870a8e140cecf9f88b1ee00890a6f7..fdf384d3f446c2f97c43e2531e7a457dc9749cb7 100644 (file)
@@ -241,9 +241,9 @@ class PKey(object):
                                continue
                        rv=libcrypto.EVP_PKEY_CTX_ctrl_str(ctx,oper,str(opts[oper]))
                        if rv==-2:
-                               raise PKeyError("Parameter %s is not supported by key"%(oper))
+                               raise PKeyError("Parameter %s is not supported by key"%(oper,))
                        if rv<1:
-                               raise PKeyError("Error setting parameter %s"(oper))
+                               raise PKeyError("Error setting parameter %s"%(oper,))
 # Declare function prototypes
 libcrypto.EVP_PKEY_cmp.argtypes=(c_void_p,c_void_p)
 libcrypto.PEM_read_bio_PrivateKey.restype=c_void_p
index 4cc86e297fe0151264c517133a96b4c32822aa10..4bc073a1ceb63f727d6022e5586d85d577084dbf 100644 (file)
@@ -47,7 +47,7 @@ def seed(data, entropy=None):
                If entropy is not None, it should be floating point(double)
                value estimating amount of entropy  in the data (in bytes).
        """
-       if type(data) != type(""):
+       if not isinstance(data,str):
                raise TypeError("A string is expected")
        ptr = c_char_p(data)
        size = len(data)
index 44919f1ff9a26be49f66b80570872018c319f84c..4f086328f2ee143afed0c939c6efbb9d7631be22 100644 (file)
@@ -148,7 +148,7 @@ class X509Name(object):
                        # Return first matching field
                        idx=libcrypto.X509_NAME_get_index_by_NID(self.ptr,key.nid,-1)
                        if idx<0:
-                               raise KeyError("Key not found "+repr(Oid))
+                               raise KeyError("Key not found "+str(Oid))
                        entry=libcrypto.X509_NAME_get_entry(self.ptr,idx)
                        s=libcrypto.X509_NAME_ENTRY_get_data(entry)
                        b=Membio()
@@ -168,6 +168,8 @@ class X509Name(object):
        def __setitem__(self,key,val):
                if not self.writable:
                        raise ValueError("Attempt to modify constant X509 object")
+               else:
+                       raise NotImplementedError
 
 class _x509_ext(Structure):
        """ Represens C structure X509_EXTENSION """
@@ -191,7 +193,6 @@ class X509_EXT(object):
        def __str__(self):
                b=Membio()
                libcrypto.X509V3_EXT_print(b.bio,self.ptr,0x20010,0)
-               libcrypto.X509V3_EXT_print.argtypes=(c_void_p,POINTER(_x509_ext),c_long,c_int)
                return str(b)
        def __unicode__(self):
                b=Membio()
@@ -547,3 +548,4 @@ libcrypto.X509_EXTENSION_dup.restype=POINTER(_x509_ext)
 libcrypto.X509V3_EXT_print.argtypes=(c_void_p,POINTER(_x509_ext),c_long,c_int)
 libcrypto.X509_get_ext.restype=c_void_p
 libcrypto.X509_get_ext.argtypes=(c_void_p,c_int)
+libcrypto.X509V3_EXT_print.argtypes=(c_void_p,POINTER(_x509_ext),c_long,c_int)
index 1bd2e1f1bf68b068e04b3f4fd8450c12e70741e7..c8fc313902765beb809cec9372e9f3cdf8adb3ac 100644 (file)
@@ -6,8 +6,22 @@ class TestRead(unittest.TestCase):
                s="A quick brown fox jumps over a lazy dog"
                bio=Membio(s)
                data=bio.read()
+               self.assertEqual(data,s)
+               data2=bio.read()
+               self.assertEqual(data2,"")
                del bio
+       def test_readwithlen(self):
+               s="A quick brown fox jumps over a lazy dog"
+               bio=Membio(s)
+               data=bio.read(len(s))
                self.assertEqual(data,s)
+               data2=bio.read(5)
+               self.assertEqual(data2,"")
+       def test_readwrongtype(self):
+               s="A quick brown fox jumps over a lazy dog"
+               bio=Membio(s)
+               with self.assertRaises(TypeError):
+                       data=bio.read("5")
        def test_reset(self):
                s="A quick brown fox jumps over a lazy dog"
                bio=Membio(s)
index e8400809e08713903092ae279ce571aaab9f222f..741c1d67c1808682a3aba317242c05ea47f353cd 100644 (file)
@@ -9,32 +9,58 @@ class TestDigestType(unittest.TestCase):
                self.assertEqual(d.digest_size(),16)
                self.assertEqual(d.block_size(),64)
                self.assertEqual(d.oid(),Oid("md4"))
+               self.assertEqual(d.name,'md4')
        def test_md5(self):
                d=digest.DigestType("md5")
                self.assertEqual(d.digest_size(),16)
                self.assertEqual(d.block_size(),64)
                self.assertEqual(d.oid(),Oid("md5"))
+               self.assertEqual(d.name,'md5')
        def test_sha1(self):
                d=digest.DigestType("sha1")
                self.assertEqual(d.digest_size(),20)
                self.assertEqual(d.block_size(),64)
                self.assertEqual(d.oid(),Oid("sha1"))
+               self.assertEqual(d.name,'sha1')
        def test_sha256(self):
                d=digest.DigestType("sha256")
                self.assertEqual(d.digest_size(),32)
                self.assertEqual(d.block_size(),64)
                self.assertEqual(d.oid(),Oid("sha256"))
+               self.assertEqual(d.name,'sha256')
        def test_sha384(self):
                d=digest.DigestType("sha384")
                self.assertEqual(d.digest_size(),48)
                self.assertEqual(d.block_size(),128)
                self.assertEqual(d.oid(),Oid("sha384"))
+               self.assertEqual(d.name,'sha384')
        def test_sha512(self):
                d=digest.DigestType("sha512")
                self.assertEqual(d.digest_size(),64)
                self.assertEqual(d.block_size(),128)
                self.assertEqual(d.oid(),Oid("sha512"))
-               
+               self.assertEqual(d.name,'sha512')
+       def test_createfromoid(self):
+               oid=Oid('sha256')
+               d=digest.DigestType(oid)
+               self.assertEqual(d.digest_size(),32)
+               self.assertEqual(d.block_size(),64)
+               self.assertEqual(d.oid(),Oid("sha256"))
+               self.assertEqual(d.name,'sha256')
+       def test_createfromEVP_MD(self):
+               d1=digest.DigestType("sha256")
+               d2=digest.DigestType(None)
+               with self.assertRaises(AttributeError):
+                       s=d2.name
+               d2.digest=d1.digest
+               self.assertEqual(d2.digest_size(),32)
+               self.assertEqual(d2.block_size(),64)
+               self.assertEqual(d2.oid(),Oid("sha256"))
+               self.assertEqual(d2.name,'sha256')
+       def test_invalidDigest(self):
+               with self.assertRaises(digest.DigestError):
+                       d=digest.DigestType("no-such-digest")
+
 
 class TestIface(unittest.TestCase):
        """ Test all methods with one algorithms """
@@ -46,6 +72,10 @@ class TestIface(unittest.TestCase):
                dgst.update(self.msg)
                self.assertEqual(dgst.digest_size,20)
                self.assertEqual(dgst.hexdigest(),self.dgst)
+       def test_digestwithdata(self):
+               md=digest.DigestType("sha1")
+               dgst=digest.Digest(md)
+               self.assertEqual(dgst.digest(self.msg),b16decode(self.dgst))
        def test_length(self):
                l=len(self.msg)
                msg=self.msg+" Dog barks furiously."
index f324f7e663a790daaf57b2f3f5da7e06142b8d05..0ff256484c0917eeb588ca1cadd0913487d603bc 100644 (file)
@@ -24,12 +24,18 @@ class TestStandard(unittest.TestCase):
                o=Oid("2.5.4.3")
                x=Oid(o.nid)
                self.assertEqual(o.nid,x.nid)
+       def test_fromunicode(self):
+               o=Oid(u'commonName')
+               self.assertEqual(o.shortname(),'CN')
        def test_wrongoid(self):
                with self.assertRaises(ValueError):
                        o=Oid("1.2.3.4.5.6.7.8.10.111.1111")
        def test_wrongname(self):
                with self.assertRaises(ValueError):
                        o=Oid("No such oid in the database")
+       def test_wrongnid(self):
+               with self.assertRaises(ValueError):
+                       o=Oid(9999999)
        def test_wrongtype(self):
                with self.assertRaises(TypeError):
                        o=Oid([2,5,3,4])
index a54417ba5733cb0e966f92bc7c196f8b624c2c0b..82b6d55f817615e7dcbf606d87aae96032f12df6 100644 (file)
@@ -118,6 +118,12 @@ zVMSW4SOwg/H7ZMZ2cn6j1g0djIvruFQFGHUqFijyDATI+/GJYw2jxyA
        def test_subject(self):
                c=X509(self.cert1)
                self.assertEqual(unicode(c.subject),u'C=RU,ST=Москва,L=Москва,O=Частное лицо,CN=Виктор Вагнер')
+       def test_subject_str(self):
+               c=X509(self.cert1)
+               self.assertEqual(str(c.subject),b'C=RU,ST=\\D0\\9C\\D0\\BE\\D1\\81\\D0\\BA\\D0\\B2\\D0\\B0,L=\\D0\\9C\\D0\\BE\\D1\\81\\D0\\BA\\D0\\B2\\D0\\B0,O=\\D0\\A7\\D0\\B0\\D1\\81\\D1\\82\\D0\\BD\\D0\\BE\\D0\\B5 \\D0\\BB\\D0\\B8\\D1\\86\\D0\\BE,CN=\\D0\\92\\D0\\B8\\D0\\BA\\D1\\82\\D0\\BE\\D1\\80 \\D0\\92\\D0\\B0\\D0\\B3\\D0\\BD\\D0\\B5\\D1\\80')
+       def test_subject_len(self):
+               c=X509(self.cert1)
+               self.assertEqual(len(c.subject),5)
        def test_issuer(self):
                c=X509(self.cert1)
                self.assertEqual(unicode(c.issuer),u'C=RU,ST=Москва,O=Удостоверяющий центр,CN=Виктор Вагнер,emailAddress=vitus@wagner.pp.ru')
@@ -125,6 +131,19 @@ zVMSW4SOwg/H7ZMZ2cn6j1g0djIvruFQFGHUqFijyDATI+/GJYw2jxyA
                c=X509(self.cert1)
                self.assertEqual(c.subject[Oid("C")],"RU")
                self.assertEqual(c.subject[Oid("L")],u'\u041c\u043e\u0441\u043a\u0432\u0430')
+       def test_subjectbadsubfield(self):
+               c=X509(self.cert1)
+               with self.assertRaises(KeyError):
+                       x=c.subject[Oid("streetAddress")]
+       def test_subjectfieldindex(self):
+               c=X509(self.cert1)
+               self.assertEqual(repr(c.subject[0]),repr((Oid('C'),u'RU')))
+       def test_subjectbadindex(self):
+               c=X509(self.cert1)
+               with self.assertRaises(IndexError):
+                       x=c.subject[11]
+               with self.assertRaises(IndexError):
+                       x=c.subject[-1]
        def test_notBefore(self):
                c=X509(self.cert1)
                self.assertEqual(c.startDate,datetime.datetime(2014,10,26,19,07,17,0,utc))
@@ -169,11 +188,16 @@ zVMSW4SOwg/H7ZMZ2cn6j1g0djIvruFQFGHUqFijyDATI+/GJYw2jxyA
                cert=X509(self.cert1)
                ext=cert.extensions[0]
                self.assertEqual(str(ext),'CA:FALSE')
+               self.assertEqual(unicode(ext),u'CA:FALSE')
        def test_extenson_find(self):
                cert=X509(self.cert1)
                exts=cert.extensions.find(Oid('subjectAltName'))
                self.assertEqual(len(exts),1)
                self.assertEqual(exts[0].oid,Oid('subjectAltName'))
+       def test_extension_bad_find(self):
+               cert=X509(self.cert1)
+               with self.assertRaises(TypeError):
+                       exts=cert.extensions.find('subjectAltName')
        def test_extenson_critical(self):
                cert=X509(self.digicert_cert)
                crit_exts=cert.extensions.find_critical()
@@ -190,6 +214,9 @@ zVMSW4SOwg/H7ZMZ2cn6j1g0djIvruFQFGHUqFijyDATI+/GJYw2jxyA
                pk2=c.pubkey
                self.assertFalse(c.verify(key=pk2))
                self.assertTrue(c.verify(key=pubkey))
+       def test_verify_self_singed(self):
+               ca=X509(self.ca_cert)
+               self.assertTrue(ca.verify())
        def test_default_filestore(self):
                store=X509Store(default=True)
                c1=X509(self.cert1)