From: Victor Wagner Date: Sun, 21 Dec 2014 10:04:43 +0000 (+0300) Subject: style fixes X-Git-Url: https://www.wagner.pp.ru/gitweb/?p=oss%2Fctypescrypto.git;a=commitdiff_plain;h=ff669c32aa77c9ebfb9c5371b2c8a9d41de614f8 style fixes --- diff --git a/README.md b/README.md index ee8356b..4b6d5d8 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,19 @@ python big integer. X509 certificates ----------------- +Certificates are cryptographically signed documents, which tie together +public key and some attributes of key owner (certificate subject). +Certificates are signed by some trusted organizations called Certificate +Authorities (one which have issued given certificate, is called +certificate issuer). Your browser or operating system typically have +predefined store of the trusted CA certificates (although nothing +prevent you from running your own CA using openssl command line utility, +and trust only it). + + + +Certificates are described in [RFC 5280](http://tools.ietf.org/html/rfc5280) + Module **ctypescrypto.x509** contains objects **X509** which represents certificate (and can be constructed from string, contained PEM or DER certificate) and object **X509Store** which is a store of trusted @@ -103,6 +116,16 @@ some operations with CMS and certificate verification. CMS documents ------------- +CMS stands for Cryptographic Message Syntax. It is defined in the +[RFC 5652](http://tools.ietf.org/html/rfc5652). +CMS defines several types of documents. There is **SignedData**, +which can be read by anyone, but is protected from authorized changes +by digital signature of its author. There is **EnvelopedData** protected +from unauthorized reading by cipher and allowed to be read only by +owners of certain private keys, and there is **EncryptedData**, which +are protected by symmetric cipher keys. + + There is basic factory function **CMS()**, which parses PEM or der representation of cryptographic message and generates appropriate object. There are **SignedData**, **EnvelopedData** and diff --git a/ctypescrypto/__init__.py b/ctypescrypto/__init__.py index ebf8c41..7ae7125 100644 --- a/ctypescrypto/__init__.py +++ b/ctypescrypto/__init__.py @@ -13,7 +13,7 @@ def config(filename=None): """ libcrypto.OPENSSL_config(filename) -__all__ = ['bio','cipher','cms','config','digest','ec','engine','exception','oid','pbkdf2','pkey','rand','x509'] +__all__ = ['config'] libcrypto = CDLL("libcrypto.so.1.0.0") libcrypto.OPENSSL_config.argtypes=(c_char_p,) diff --git a/ctypescrypto/cipher.py b/ctypescrypto/cipher.py index 815a425..ff61478 100644 --- a/ctypescrypto/cipher.py +++ b/ctypescrypto/cipher.py @@ -117,10 +117,7 @@ class Cipher: if self.ctx == 0: raise CipherError("Unable to create cipher context") self.encrypt = encrypt - if encrypt: - enc = 1 - else: - enc = 0 + enc=1 if encrypt else 0 if not iv is None and len(iv) != cipher_type.iv_length(): raise ValueError("Invalid IV length for this algorithm") @@ -151,10 +148,7 @@ class Cipher: """ Sets padding mode of the cipher """ - if padding: - padding_flag = 1 - else: - padding_flag = 0 + padding_flag=1 if padding else 0 libcrypto.EVP_CIPHER_CTX_set_padding(self.ctx, padding_flag) def update(self, data): @@ -173,7 +167,7 @@ class Cipher: raise CipherError("No updates allowed") if not isinstance(data,str): raise TypeError("A string is expected") - if len(data) <= 0: + if len(data) == 0: return "" outbuf=create_string_buffer(self.block_size+len(data)) outlen=c_int(0) diff --git a/ctypescrypto/cms.py b/ctypescrypto/cms.py index 3158b62..5a54bde 100644 --- a/ctypescrypto/cms.py +++ b/ctypescrypto/cms.py @@ -171,7 +171,7 @@ class SignedData(CMSBase): res=libcrypto.CMS_verify(self.ptr,certstack,store.store,bio,None,flags) return res>0 @property - def signers(self,store=None): + def signers(self): """ Return list of signer's certificates """ diff --git a/ctypescrypto/digest.py b/ctypescrypto/digest.py index 30d77c5..586a1fb 100644 --- a/ctypescrypto/digest.py +++ b/ctypescrypto/digest.py @@ -1,176 +1,176 @@ -""" - Implements interface to OpenSSL EVP_Digest* functions. - - Interface made as close to hashlib as possible. - - This module is really an excess effort. Hashlib allows access to - mostly same functionality except oids and nids of hashing - algortithms (which might be needed for private key operations). - - hashlib even allows to use engine-provided digests if it is build - with dinamically linked libcrypto - so use - ctypescrypto.engine.set_default("gost",xFFFF) and md_gost94 - algorithm would be available both to this module and hashlib. - -""" -from ctypes import c_int, c_char_p, c_void_p, POINTER, c_long,c_longlong, create_string_buffer,byref -from ctypescrypto import libcrypto -from ctypescrypto.exception import LibCryptoError -from ctypescrypto.oid import Oid -DIGEST_ALGORITHMS = ("MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512") - -__all__ = ['DigestError','Digest','DigestType','new'] - -class DigestError(LibCryptoError): - pass - -def new(algname): - """ - Behaves just like hashlib.new. Creates digest object by - algorithm name - """ - md=DigestType(algname) - return Digest(md) - -class DigestType(object): - """ - - Represents EVP_MD object - constant structure which describes - digest algorithm - - """ - def __init__(self, digest_name): - """ - Finds digest by its name. You can pass Oid object instead of - name. - - Special case is when None is passed as name. In this case - unitialized digest is created, and can be initalized later - by setting its digest attribute to pointer to EVP_MD - """ - if digest_name is None: - return - if isinstance(digest_name,Oid): - self.digest_name=digest_name.longname() - self.digest=libcrypto.EVP_get_digestbyname(self.digest_name) - else: - self.digest_name = str(digest_name) - self.digest = libcrypto.EVP_get_digestbyname(self.digest_name) - if self.digest is None: - raise DigestError("Unknown digest: %s" % self.digest_name) - - @property - def name(self): - if not hasattr(self,'digest_name'): - self.digest_name=Oid(libcrypto.EVP_MD_type(self.digest)).longname() - return self.digest_name - def __del__(self): - pass - def digest_size(self): - return libcrypto.EVP_MD_size(self.digest) - def block_size(self): - return libcrypto.EVP_MD_block_size(self.digest) - def oid(self): - return Oid(libcrypto.EVP_MD_type(self.digest)) - -class Digest(object): - """ - Represents EVP_MD_CTX object which actually used to calculate - digests. - - """ - def __init__(self,digest_type): - """ - Initializes digest using given type. - """ - self._clean_ctx() - self.ctx = libcrypto.EVP_MD_CTX_create() - if self.ctx is None: - raise DigestError("Unable to create digest context") - result = 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 - self.digest_size = self.digest_type.digest_size() - self.block_size = self.digest_type.block_size() - - def __del__(self): - self._clean_ctx() - - def update(self, data, length=None): - """ - Hashes given byte string - - @param data - string to hash - @param length - if not specifed, entire string is hashed, - otherwise only first length bytes - """ - if self.digest_finalized: - raise DigestError("No updates allowed") - if not isinstance(data,str): - raise TypeError("A string is expected") - if length is None: - length = len(data) - elif length > len(data): - raise ValueError("Specified length is greater than length of data") - result = libcrypto.EVP_DigestUpdate(self.ctx, c_char_p(data), length) - if result != 1: - raise DigestError, "Unable to update digest" - - def digest(self, data=None): - """ - Finalizes digest operation and return digest value - Optionally hashes more data before finalizing - """ - if self.digest_finalized: - return self.digest_out.raw[:self.digest_size] - if data is not None: - self.update(data) - self.digest_out = create_string_buffer(256) - length = c_long(0) - result = libcrypto.EVP_DigestFinal_ex(self.ctx, self.digest_out, byref(length)) - if result != 1 : - raise DigestError("Unable to finalize digest") - self.digest_finalized = True - return self.digest_out.raw[:self.digest_size] - def copy(self): - """ - Creates copy of the digest CTX to allow to compute digest - while being able to hash more data - """ - new_digest=Digest(self.digest_type) - libcrypto.EVP_MD_CTX_copy(new_digest.ctx,self.ctx) - return new_digest - - def _clean_ctx(self): - try: - if self.ctx is not None: - libcrypto.EVP_MD_CTX_destroy(self.ctx) - del(self.ctx) - except AttributeError: - pass - self.digest_out = None - self.digest_finalized = False - - def hexdigest(self,data=None): - """ - Returns digest in the hexadecimal form. For compatibility - with hashlib - """ - from base64 import b16encode - return b16encode(self.digest(data)) - - -# Declare function result and argument types -libcrypto.EVP_get_digestbyname.restype = c_void_p -libcrypto.EVP_get_digestbyname.argtypes = (c_char_p,) -libcrypto.EVP_MD_CTX_create.restype = c_void_p -libcrypto.EVP_DigestInit_ex.argtypes = (c_void_p,c_void_p,c_void_p) -libcrypto.EVP_DigestUpdate.argtypes = (c_void_p,c_char_p,c_longlong) -libcrypto.EVP_DigestFinal_ex.argtypes = (c_void_p,c_char_p,POINTER(c_long)) -libcrypto.EVP_MD_CTX_destroy.argtypes = (c_void_p,) -libcrypto.EVP_MD_CTX_copy.argtypes=(c_void_p, c_void_p) -libcrypto.EVP_MD_type.argtypes=(c_void_p,) -libcrypto.EVP_MD_size.argtypes=(c_void_p,) -libcrypto.EVP_MD_block_size.argtypes=(c_void_p,) +""" + Implements interface to OpenSSL EVP_Digest* functions. + + Interface made as close to hashlib as possible. + + This module is really an excess effort. Hashlib allows access to + mostly same functionality except oids and nids of hashing + algortithms (which might be needed for private key operations). + + hashlib even allows to use engine-provided digests if it is build + with dinamically linked libcrypto - so use + ctypescrypto.engine.set_default("gost",xFFFF) and md_gost94 + algorithm would be available both to this module and hashlib. + +""" +from ctypes import c_int, c_char_p, c_void_p, POINTER, c_long,c_longlong, create_string_buffer,byref +from ctypescrypto import libcrypto +from ctypescrypto.exception import LibCryptoError +from ctypescrypto.oid import Oid +DIGEST_ALGORITHMS = ("MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512") + +__all__ = ['DigestError','Digest','DigestType','new'] + +class DigestError(LibCryptoError): + pass + +def new(algname): + """ + Behaves just like hashlib.new. Creates digest object by + algorithm name + """ + md=DigestType(algname) + return Digest(md) + +class DigestType(object): + """ + + Represents EVP_MD object - constant structure which describes + digest algorithm + + """ + def __init__(self, digest_name): + """ + Finds digest by its name. You can pass Oid object instead of + name. + + Special case is when None is passed as name. In this case + unitialized digest is created, and can be initalized later + by setting its digest attribute to pointer to EVP_MD + """ + if digest_name is None: + return + if isinstance(digest_name,Oid): + self.digest_name=digest_name.longname() + self.digest=libcrypto.EVP_get_digestbyname(self.digest_name) + else: + self.digest_name = str(digest_name) + self.digest = libcrypto.EVP_get_digestbyname(self.digest_name) + if self.digest is None: + raise DigestError("Unknown digest: %s" % self.digest_name) + + @property + def name(self): + if not hasattr(self,'digest_name'): + self.digest_name=Oid(libcrypto.EVP_MD_type(self.digest)).longname() + return self.digest_name + def __del__(self): + pass + def digest_size(self): + return libcrypto.EVP_MD_size(self.digest) + def block_size(self): + return libcrypto.EVP_MD_block_size(self.digest) + def oid(self): + return Oid(libcrypto.EVP_MD_type(self.digest)) + +class Digest(object): + """ + Represents EVP_MD_CTX object which actually used to calculate + digests. + + """ + def __init__(self,digest_type): + """ + Initializes digest using given type. + """ + self._clean_ctx() + self.ctx = libcrypto.EVP_MD_CTX_create() + if self.ctx is None: + raise DigestError("Unable to create digest context") + result = 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 + self.digest_size = self.digest_type.digest_size() + self.block_size = self.digest_type.block_size() + + def __del__(self): + self._clean_ctx() + + def update(self, data, length=None): + """ + Hashes given byte string + + @param data - string to hash + @param length - if not specifed, entire string is hashed, + otherwise only first length bytes + """ + if self.digest_finalized: + raise DigestError("No updates allowed") + if not isinstance(data,str): + raise TypeError("A string is expected") + if length is None: + length = len(data) + elif length > len(data): + raise ValueError("Specified length is greater than length of data") + result = libcrypto.EVP_DigestUpdate(self.ctx, c_char_p(data), length) + if result != 1: + raise DigestError, "Unable to update digest" + + def digest(self, data=None): + """ + Finalizes digest operation and return digest value + Optionally hashes more data before finalizing + """ + if self.digest_finalized: + return self.digest_out.raw[:self.digest_size] + if data is not None: + self.update(data) + self.digest_out = create_string_buffer(256) + length = c_long(0) + result = libcrypto.EVP_DigestFinal_ex(self.ctx, self.digest_out, byref(length)) + if result != 1 : + raise DigestError("Unable to finalize digest") + self.digest_finalized = True + return self.digest_out.raw[:self.digest_size] + def copy(self): + """ + Creates copy of the digest CTX to allow to compute digest + while being able to hash more data + """ + new_digest=Digest(self.digest_type) + libcrypto.EVP_MD_CTX_copy(new_digest.ctx,self.ctx) + return new_digest + + def _clean_ctx(self): + try: + if self.ctx is not None: + libcrypto.EVP_MD_CTX_destroy(self.ctx) + del(self.ctx) + except AttributeError: + pass + self.digest_out = None + self.digest_finalized = False + + def hexdigest(self,data=None): + """ + Returns digest in the hexadecimal form. For compatibility + with hashlib + """ + from base64 import b16encode + return b16encode(self.digest(data)) + + +# Declare function result and argument types +libcrypto.EVP_get_digestbyname.restype = c_void_p +libcrypto.EVP_get_digestbyname.argtypes = (c_char_p,) +libcrypto.EVP_MD_CTX_create.restype = c_void_p +libcrypto.EVP_DigestInit_ex.argtypes = (c_void_p,c_void_p,c_void_p) +libcrypto.EVP_DigestUpdate.argtypes = (c_void_p,c_char_p,c_longlong) +libcrypto.EVP_DigestFinal_ex.argtypes = (c_void_p,c_char_p,POINTER(c_long)) +libcrypto.EVP_MD_CTX_destroy.argtypes = (c_void_p,) +libcrypto.EVP_MD_CTX_copy.argtypes=(c_void_p, c_void_p) +libcrypto.EVP_MD_type.argtypes=(c_void_p,) +libcrypto.EVP_MD_size.argtypes=(c_void_p,) +libcrypto.EVP_MD_block_size.argtypes=(c_void_p,)