Commits

Jason R. Coombs committed 12f53b9

Moved Digest to evp.py

Comments (0)

Files changed (3)

ctypescrypto/digest.py

-from ctypes import *
+from evp import DigestType, Digest
 
-DIGEST_ALGORITHMS = ("MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512")
-
-class DigestError(Exception):
-    pass
-
-class DigestType:
-
-    def __init__(self, libcrypto, digest_name):
-        self.libcrypto = libcrypto
-        self.digest_name = digest_name
-        self.digest = self.libcrypto.EVP_get_digestbyname(self.digest_name)
-        if self.digest == 0:
-            raise DigestError, "Unknown digest: %s" % self.digest_name
-
-    def __del__(self):
-        pass
-
-class Digest:
-
-    def __init__(self, libcrypto, digest_type):
-        self.libcrypto = libcrypto
-        self._clean_ctx()
-        self.ctx = self.libcrypto.EVP_MD_CTX_create()
-        if self.ctx == 0:
-            raise DigestError, "Unable to create digest context"
-        result = self.libcrypto.EVP_DigestInit_ex(self.ctx, digest_type.digest, None)
-        if result == 0:
-            self._clean_ctx()
-            raise DigestError, "Unable to initialize digest"
-        self.digest_type = digest_type
-
-    def __del__(self):
-        self._clean_ctx()
-
-    def update(self, data):
-        if self.digest_finalized:
-            raise DigestError, "No updates allowed"
-        if type(data) != type(""):
-            raise TypeError, "A string is expected"
-        result = self.libcrypto.EVP_DigestUpdate(self.ctx, c_char_p(data), len(data))
-        if result != 1:
-            raise DigestError, "Unable to update digest"
-        
-    def digest(self, data=None):
-        if self.digest_finalized:
-            raise DigestError, "Digest operation is already completed"
-        if data is not None:
-            self.update(data)
-        self.digest_out = create_string_buffer(256)
-        length = c_long(0)
-        result = self.libcrypto.EVP_DigestFinal_ex(self.ctx, byref(self.digest_out), byref(length))
-        if result != 1 :
-            raise DigestError, "Unable to finalize digest"
-        self.digest_finalized = True
-        return self.digest_out.raw[:length.value]
-
-    def _clean_ctx(self):
-        try:
-            if self.ctx is not None:
-                self.libcrypto.EVP_MD_CTX_destroy(self.ctx)
-                del(self.ctx)
-        except AttributeError:
-            pass
-        self.digest_out = None
-        self.digest_finalized = False

ctypescrypto/evp.py

 			raise DigestError("Unknown Digest: %(digest_name)s" % vars())
 		return res.contents
 
+class DigestContext(Structure):
+	_fields_ = [
+		('digest', POINTER(DigestType)),
+		('engine', c_void_p), # todo, POINTER(ENGINE)
+		('flags', c_ulong),
+		('md_data', c_void_p),
+		('pctx', c_void_p), # todo, POINTER(EVP_PKEY_CTX)
+		('update', c_void_p),
+		]
+
+	@staticmethod
+	def create():
+		res = lib.EVP_MD_CTX_create()
+		if not res:
+			raise DigestError("Unable to create digest context")
+		return res
+
+	def destroy(self):
+		lib.EVP_MD_CTX_destroy(self)
+
+	def __del__(self):
+		self.destroy()
+
+class Digest(object):
+	finalized = False
+	def __init__(self, digest_type):
+		self.digest_type = digest_type
+		self.context = DigestContext.create()
+		result = lib.EVP_DigestInit_ex(self.context, digest_type, None)
+		if result == 0:
+			raise DigestError("Unable to initialize digest")
+
+	def update(self, data):
+		if self.finalized:
+			raise DigestError("Digest is finalized; no updates allowed")
+		if not isinstance(data, basestring):
+			raise TypeError("A string is expected")
+		result = lib.EVP_DigestUpdate(self.context, data, len(data))
+		if result != 1:
+			raise DigestError, "Unable to update digest"
+		
+	def digest(self, data=None):
+		if self.digest_finalized:
+			raise DigestError, "Digest operation is already completed"
+		if data is not None:
+			self.update(data)
+		self.digest_out = create_string_buffer(256)
+		length = c_long(0)
+		result = self.libcrypto.EVP_DigestFinal_ex(self.ctx, byref(self.digest_out), byref(length))
+		if result != 1 :
+			raise DigestError, "Unable to finalize digest"
+		self.digest_finalized = True
+		return self.digest_out.raw[:length.value]
+
 lib = find_library('libeay32')
 lib.EVP_get_digestbyname.argtypes = c_char_p,
 lib.EVP_get_digestbyname.restype = POINTER(DigestType)

tests/test_misc.py

 import binascii
 
 def test_basic_functionality():
-	digest_type = digest.DigestType(libcrypto, 'SHA512')
+	digest_type = digest.DigestType.from_name('SHA512')
 	sha512 = digest.Digest(libcrypto, digest_type)
 	sha512.update("test")
 	assert binascii.hexlify(sha512.digest()) == "ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f5"
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.