2 Implements interface to OpenSSL EVP_Digest* functions.
\r
4 Interface made as close to hashlib as possible.
\r
6 This module is really an excess effort. Hashlib allows access to
\r
7 mostly same functionality except oids and nids of hashing
\r
8 algortithms (which might be needed for private key operations).
\r
10 hashlib even allows to use engine-provided digests if it is build
\r
11 with dinamically linked libcrypto - so use
\r
12 ctypescrypto.engine.set_default("gost",xFFFF) and md_gost94
\r
13 algorithm would be available both to this module and hashlib.
\r
16 from ctypes import c_int, c_char_p, c_void_p, POINTER, c_long,c_longlong, create_string_buffer,byref
\r
17 from ctypescrypto import libcrypto
\r
18 from ctypescrypto.exception import LibCryptoError
\r
19 from ctypescrypto.oid import Oid
\r
20 DIGEST_ALGORITHMS = ("MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512")
\r
22 __all__ = ['DigestError','Digest','DigestType','new']
\r
24 class DigestError(LibCryptoError):
\r
29 Behaves just like hashlib.new. Creates digest object by
\r
32 md=DigestType(algname)
\r
38 Represents EVP_MD object - constant structure which describes
\r
42 def __init__(self, digest_name):
\r
44 Finds digest by its name
\r
46 self.digest_name = digest_name
\r
47 self.digest = libcrypto.EVP_get_digestbyname(self.digest_name)
\r
48 if self.digest is None:
\r
49 raise DigestError("Unknown digest: %s" % self.digest_name)
\r
53 def digest_size(self):
\r
54 return libcrypto.EVP_MD_size(self.digest)
\r
55 def block_size(self):
\r
56 return libcrypto.EVP_MD_block_size(self.digest)
\r
58 return Oid(libcrypto.EVP_MD_type(self.digest))
\r
62 Represents EVP_MD_CTX object which actually used to calculate
\r
66 def __init__(self,digest_type):
\r
68 Initializes digest using given type.
\r
71 self.ctx = libcrypto.EVP_MD_CTX_create()
\r
73 raise DigestError("Unable to create digest context")
\r
74 result = libcrypto.EVP_DigestInit_ex(self.ctx, digest_type.digest, None)
\r
77 raise DigestError("Unable to initialize digest")
\r
78 self.digest_type = digest_type
\r
79 self.digest_size = self.digest_type.digest_size()
\r
80 self.block_size = self.digest_type.block_size()
\r
85 def update(self, data, length=None):
\r
87 Hashes given byte string
\r
89 @param data - string to hash
\r
90 @param length - if not specifed, entire string is hashed,
\r
91 otherwise only first length bytes
\r
93 if self.digest_finalized:
\r
94 raise DigestError("No updates allowed")
\r
95 if type(data) != type(""):
\r
96 raise TypeError("A string is expected")
\r
99 elif length> len(data):
\r
100 raise ValueError("Specified length is greater than length of data")
\r
101 result = libcrypto.EVP_DigestUpdate(self.ctx, c_char_p(data), length)
\r
103 raise DigestError, "Unable to update digest"
\r
105 def digest(self, data=None):
\r
107 Finalizes digest operation and return digest value
\r
108 Optionally hashes more data before finalizing
\r
110 if self.digest_finalized:
\r
111 return self.digest_out.raw[:self.digest_size]
\r
112 if data is not None:
\r
114 self.digest_out = create_string_buffer(256)
\r
116 result = libcrypto.EVP_DigestFinal_ex(self.ctx, self.digest_out, byref(length))
\r
118 raise DigestError("Unable to finalize digest")
\r
119 self.digest_finalized = True
\r
120 return self.digest_out.raw[:self.digest_size]
\r
123 Creates copy of the digest CTX to allow to compute digest
\r
124 while being able to hash more data
\r
126 new_digest=Digest(self.digest_type)
\r
127 libcrypto.EVP_MD_CTX_copy(new_digest.ctx,self.ctx)
\r
130 def _clean_ctx(self):
\r
132 if self.ctx is not None:
\r
133 libcrypto.EVP_MD_CTX_destroy(self.ctx)
\r
135 except AttributeError:
\r
137 self.digest_out = None
\r
138 self.digest_finalized = False
\r
140 def hexdigest(self,data=None):
\r
142 Returns digest in the hexadecimal form. For compatibility
\r
145 from base64 import b16encode
\r
146 return b16encode(self.digest(data))
\r
149 # Declare function result and argument types
\r
150 libcrypto.EVP_get_digestbyname.restype = c_void_p
\r
151 libcrypto.EVP_get_digestbyname.argtypes = (c_char_p,)
\r
152 libcrypto.EVP_MD_CTX_create.restype = c_void_p
\r
153 libcrypto.EVP_DigestInit_ex.argtypes = (c_void_p,c_void_p,c_void_p)
\r
154 libcrypto.EVP_DigestUpdate.argtypes = (c_void_p,c_char_p,c_longlong)
\r
155 libcrypto.EVP_DigestFinal_ex.argtypes = (c_void_p,c_char_p,POINTER(c_long))
\r
156 libcrypto.EVP_MD_CTX_destroy.argtypes = (c_void_p,)
\r
157 libcrypto.EVP_MD_CTX_copy.argtypes=(c_void_p, c_void_p)
\r
158 libcrypto.EVP_MD_type.argtypes=(c_void_p,)
\r
159 libcrypto.EVP_MD_size.argtypes=(c_void_p,)
\r
160 libcrypto.EVP_MD_block_size.argtypes=(c_void_p,)
\r