]> www.wagner.pp.ru Git - oss/ctypescrypto.git/blobdiff - ctypescrypto/digest.py
Fixes some style. Improved tests coverage for bio,oid,digest and cipher. Prepare...
[oss/ctypescrypto.git] / ctypescrypto / digest.py
index 4e33d92bb3e147b28a05fd22dd18ef315078dff2..30d77c5a57b35f19d2f0aa501f010581ae4740dc 100644 (file)
@@ -1,5 +1,6 @@
 """\r
-       Implmenets interface to OpenSSL EVP_Digest* functions.\r
+       Implements interface to OpenSSL EVP_Digest* functions.\r
+\r
        Interface  made as close to hashlib as possible.\r
 \r
        This module is really an excess effort. Hashlib allows access to\r
@@ -18,6 +19,7 @@ from ctypescrypto.exception import LibCryptoError
 from ctypescrypto.oid import Oid\r
 DIGEST_ALGORITHMS = ("MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512")\r
 \r
+__all__ = ['DigestError','Digest','DigestType','new']\r
 \r
 class DigestError(LibCryptoError):\r
        pass\r
@@ -30,7 +32,7 @@ def new(algname):
        md=DigestType(algname)\r
        return Digest(md)\r
 \r
-class DigestType:\r
+class DigestType(object):\r
        """\r
                \r
                Represents EVP_MD object - constant structure which describes\r
@@ -39,13 +41,29 @@ class DigestType:
        """\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
+                       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
@@ -55,7 +73,7 @@ class DigestType:
        def oid(self):\r
                return Oid(libcrypto.EVP_MD_type(self.digest))\r
 \r
-class Digest:\r
+class Digest(object):\r
        """\r
                Represents EVP_MD_CTX object which actually used to calculate\r
                digests.\r
@@ -67,12 +85,12 @@ class Digest:
                """\r
                self._clean_ctx()\r
                self.ctx = libcrypto.EVP_MD_CTX_create()\r
-               if self.ctx == 0:\r
-                       raise DigestError, "Unable to create digest context"\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
                        self._clean_ctx()\r
-                       raise DigestError, "Unable to initialize digest"\r
+                       raise DigestError("Unable to initialize digest")\r
                self.digest_type = digest_type\r
                self.digest_size = self.digest_type.digest_size()\r
                self.block_size = self.digest_type.block_size()\r
@@ -80,15 +98,23 @@ class Digest:
        def __del__(self):\r
                self._clean_ctx()\r
 \r
-       def update(self, data):\r
+       def update(self, data, length=None):\r
                """\r
-                       Hashes given byte string as data\r
+                       Hashes given byte string \r
+\r
+                       @param data - string to hash\r
+                       @param length - if not specifed, entire string is hashed,\r
+                                       otherwise only first length bytes\r
                """\r
                if self.digest_finalized:\r
-                       raise DigestError, "No updates allowed"\r
-               if type(data) != type(""):\r
-                       raise TypeError, "A string is expected"\r
-               result = libcrypto.EVP_DigestUpdate(self.ctx, c_char_p(data), len(data))\r
+                       raise DigestError("No updates allowed")\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
+                       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
                        raise DigestError, "Unable to update digest"\r
                \r
@@ -105,7 +131,7 @@ class Digest:
                length = c_long(0)\r
                result = libcrypto.EVP_DigestFinal_ex(self.ctx, self.digest_out, byref(length))\r
                if result != 1 :\r
-                       raise DigestError, "Unable to finalize digest"\r
+                       raise DigestError("Unable to finalize digest")\r
                self.digest_finalized = True\r
                return self.digest_out.raw[:self.digest_size]\r
        def copy(self):\r