]> www.wagner.pp.ru Git - oss/ctypescrypto.git/blobdiff - ctypescrypto/digest.py
digest module covered by tests
[oss/ctypescrypto.git] / ctypescrypto / digest.py
index 4b0eeb5c1e7c39c30a56628cbe29593bf25387c1..4e33d92bb3e147b28a05fd22dd18ef315078dff2 100644 (file)
@@ -1,17 +1,32 @@
 """\r
        Implmenets interface to OpenSSL EVP_Digest* functions.\r
-       Interface  made as close to hashlib as possible\r
+       Interface  made as close to hashlib as possible.\r
+\r
+       This module is really an excess effort. Hashlib allows access to\r
+       mostly same functionality except oids and nids of hashing\r
+       algortithms (which might be needed for private key operations).\r
+\r
+       hashlib even allows to use engine-provided digests if it is build\r
+       with dinamically linked libcrypto - so use\r
+       ctypescrypto.engine.set_default("gost",xFFFF) and md_gost94\r
+       algorithm would be available both to this module and hashlib.\r
+\r
 """\r
-from ctypes import c_int, c_char_p, c_void_p, POINTER, c_long_long\r
+from ctypes import c_int, c_char_p, c_void_p, POINTER, c_long,c_longlong, create_string_buffer,byref\r
 from ctypescrypto import libcrypto\r
 from ctypescrypto.exception import LibCryptoError\r
+from ctypescrypto.oid import Oid\r
 DIGEST_ALGORITHMS = ("MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512")\r
 \r
 \r
 class DigestError(LibCryptoError):\r
-    pass\r
+       pass\r
 \r
 def new(algname):\r
+       """\r
+               Behaves just like hashlib.new. Creates digest object by\r
+               algorithm name\r
+       """\r
        md=DigestType(algname)\r
        return Digest(md)\r
 \r
@@ -22,78 +37,77 @@ class DigestType:
                digest algorithm\r
 \r
        """\r
-    def __init__(self,  digest_name):\r
+       def __init__(self,      digest_name):\r
                """\r
                        Finds digest by its name\r
                """\r
-        self.digest_name = digest_name\r
-        self.digest = libcrypto.EVP_get_digestbyname(self.digest_name)\r
-        if self.digest == 0:\r
-            raise DigestError, "Unknown digest: %s" % self.digest_name\r
+               self.digest_name = 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
-    def __del__(self):\r
-        pass\r
+       def __del__(self):\r
+               pass\r
        def digest_size(self):\r
                return libcrypto.EVP_MD_size(self.digest)\r
        def block_size(self):\r
                return libcrypto.EVP_MD_block_size(self.digest)\r
        def oid(self):\r
-               pass\r
-               #FIXME TBD\r
-               # return Oid(nid=libcrypto.EVP_MD_type(self.digest)\r
+               return Oid(libcrypto.EVP_MD_type(self.digest))\r
+\r
 class Digest:\r
        """\r
                Represents EVP_MD_CTX object which actually used to calculate\r
                digests.\r
 \r
        """\r
-    def __init__(self,  digest_type):\r
+       def __init__(self,digest_type):\r
                """\r
                        Initializes digest using given type.\r
                """\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
-        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
-        self.digest_type = digest_type\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
+               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
+               self.digest_type = digest_type\r
                self.digest_size = self.digest_type.digest_size()\r
                self.block_size = self.digest_type.block_size()\r
 \r
-    def __del__(self):\r
-        self._clean_ctx()\r
+       def __del__(self):\r
+               self._clean_ctx()\r
 \r
-    def update(self, data):\r
+       def update(self, data):\r
                """\r
                        Hashes given byte string as data\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
-        if result != 1:\r
-            raise DigestError, "Unable to update digest"\r
-        \r
-    def digest(self, data=None):\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
+               if result != 1:\r
+                       raise DigestError, "Unable to update digest"\r
+               \r
+       def digest(self, data=None):\r
                """\r
                        Finalizes digest operation and return digest value\r
-                       Optionally hashes data before finalizing\r
+                       Optionally hashes more data before finalizing\r
                """\r
-        if self.digest_finalized:\r
+               if self.digest_finalized:\r
                        return self.digest_out.raw[:self.digest_size]\r
-        if data is not None:\r
-            self.update(data)\r
-        self.digest_out = create_string_buffer(256)\r
-        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
-        self.digest_finalized = True\r
-        return self.digest_out.raw[:self.digest_size]\r
+               if data is not None:\r
+                       self.update(data)\r
+               self.digest_out = create_string_buffer(256)\r
+               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
+               self.digest_finalized = True\r
+               return self.digest_out.raw[:self.digest_size]\r
        def copy(self):\r
                """\r
                        Creates copy of the digest CTX to allow to compute digest\r
@@ -103,15 +117,15 @@ class Digest:
                libcrypto.EVP_MD_CTX_copy(new_digest.ctx,self.ctx)\r
                return new_digest\r
 \r
-    def _clean_ctx(self):\r
-        try:\r
-            if self.ctx is not None:\r
-                libcrypto.EVP_MD_CTX_destroy(self.ctx)\r
-                del(self.ctx)\r
-        except AttributeError:\r
-            pass\r
-        self.digest_out = None\r
-        self.digest_finalized = False\r
+       def _clean_ctx(self):\r
+               try:\r
+                       if self.ctx is not None:\r
+                               libcrypto.EVP_MD_CTX_destroy(self.ctx)\r
+                               del(self.ctx)\r
+               except AttributeError:\r
+                       pass\r
+               self.digest_out = None\r
+               self.digest_finalized = False\r
 \r
        def hexdigest(self,data=None):\r
                """\r
@@ -119,11 +133,12 @@ class Digest:
                        with hashlib\r
                """\r
                from base64 import b16encode\r
-               return b16encode(self.digest(data)\r
+               return b16encode(self.digest(data))\r
 \r
 \r
 # Declare function result and argument types\r
 libcrypto.EVP_get_digestbyname.restype = c_void_p\r
+libcrypto.EVP_get_digestbyname.argtypes = (c_char_p,)\r
 libcrypto.EVP_MD_CTX_create.restype = c_void_p\r
 libcrypto.EVP_DigestInit_ex.argtypes = (c_void_p,c_void_p,c_void_p)\r
 libcrypto.EVP_DigestUpdate.argtypes = (c_void_p,c_char_p,c_longlong)\r