From b4ee51a0aca14c0af5853545b9e524cc1b57b656 Mon Sep 17 00:00:00 2001 From: Victor Wagner Date: Sat, 25 Oct 2014 21:42:01 +0400 Subject: [PATCH] cleaned up documentation --- README.md | 136 ++++++++++++++++++++++++++------------ ctypescrypto/__init__.py | 10 ++- ctypescrypto/bio.py | 3 + ctypescrypto/cipher.py | 4 ++ ctypescrypto/ec.py | 33 +++++++++ ctypescrypto/engine.py | 7 ++ ctypescrypto/exception.py | 3 + ctypescrypto/oid.py | 1 + ctypescrypto/pkey.py | 13 ++++ tests/testcipher.py | 3 + 10 files changed, 168 insertions(+), 45 deletions(-) create mode 100644 ctypescrypto/ec.py diff --git a/README.md b/README.md index 2054f7b..27991db 100644 --- a/README.md +++ b/README.md @@ -7,48 +7,96 @@ This module is based on works from http://code.google.com/p/ctypescrypto/ -It is aimed to provide Python interface to OpenSSL libcrypto function - -Now supported: - -bio.py - interfase to OpenSSL stream abstraction BIO. Now supports - memory BIOs this module intended to use for parsing/serializing - various ASN.1 based formats like private keys or certificates - Status: bare minimum functionality is implemented and covered by - rests - -oid.py - interface to OpenSSL ASN.1 Object Identifier databsase. - Allows to convert numeric identifier (NIDs) returned by various - OpenSSL function to readable names or dotted-decimal OIDs and back - Status: Fully implemented and covered by tests. - -engine.py - interface to loadable modules with alternate implementations - of cryptoalgorithms. - Status: Bare minumum, neccessary to use GOST algorithms is - implemented. - -rand.py - interface to pseudo-random number generator. - Status: Implemented. Tests now only ensure that no segfault occurs - if arugments are passed correctly - -digests.py - Interface to EVP\_Digest\* family of functions. - Really does almost same as hashlib, which even is able to take - advantage of loaded engines if compiled against dynamic libcrypto - Status: fully implemented and covered by tests - -ciphers.py - Interface to EVP\_Cipher family of function. - Status: Needs test coverage - -pkey.py - Low-level private key operations (like pkey, genpkey and p - keyutl command line ops), all via algorithm-agnostic EVP interface. - Status: Designed and started to implement but most functionality - not yet covered by tests - -exception.py OpenSSL error stack to python exception conversion - Implemented. - -x509 X509 certificates. Support parsing of X509 certificates, - verification and extracting of field values. Possible extnesion - - support creattion of PKCS10 certificate requests. - Status: Interface designed and partially implemented +most recent version can be checked out from + +https://github.com/vbwagner/ctypescrypto.git + +It is aimed to provide Python interface to OpenSSL libcrypto functions. +All the objects in this library are just wrappers around some OpenSSL +data structures and groups of functions. + + + +Digest calculation +------------------ + +Module *ctypescrypto.digest* contain *new()* function which produces +objects simular to python *hashlib* module objects. + +On the systems where hashlib is linked with libcrypto dynamically, +hashlib even able to make use of digest types, provided by loadable +engines. + +This module would utilize same copy of libcrypto library as other +ctypescrypto modules, so it would work with engine-provided digests. + +Symmetric ciphers +----------------- + +Module *ctypescrypto.cipher* contain *new()* function which provides +way to create cipher objects. Cipher padding can be configure later. +This object provides methods *update* and *finish* which allows to +encrypt/decrypt data. All ciphers, supported by your version of OpenSSL +and its loadable engines are supported. + +Public key operations +--------------------- + +Module *ctypescrypto.pkey* provides *PKey* object, which represents +public/private key pair or just public key. With this object you can +sign data, derive shared key and verify signatures. + +This is quite low-level object, which can be used to implement some +non-standard protocols and operations. + +X509 certificates +----------------- + +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 +CA certificates which can be used to high-level signature verifications +(i.e. in PKCS7/CMS messages). + +Certificate has properties corresponding to its subject and issuer +names, public key (of course it is PKey object described above) and +serial number. Subject and issuer names can be indexed by OIDs or by +position of field. Unicode in the names is supported. + +There is no support for certificate validity time yet. + +OID database +------------ + +OpenSSL conteins internal object identifiers (OID) database. Each OID +have apart from dotted-decimal representation long name, short name and +numeric identifer. Module *ctypescrypto.oid* provides interface to the +database. *Oid* objects store numeric identifier internally and can +return both long and short name and dotted-decimal representation. + +BIO library +----------- + +OpenSSL contain BIO (basic input-output) abstraction. And all object +serialization/deserialization use this library. Also human-readble +representation of ASN.1 structures use this library extensively. So, +we've to develop python object which allow to read from python string +via BIO abstraction or write to buffer, which can be returned as python +string or unicode object. + +Exceptions +---------- + +Exceptions, used in the *ctypescrypto* to report problems are tied +closely with OpenSSL error-reporting functions, so if such an exception +occurs, as much as possibly information from inside libcrypto would be +available in the Python + +Engine support +-------------- + +There is just one function *ctypescrypt.engine.set_default*. which loads +specified engine by id and makes it default for all algorithms, +supported by it. It is enough for me to use Russian national +cryptographic algoritms, provided by *gost* engine. diff --git a/ctypescrypto/__init__.py b/ctypescrypto/__init__.py index d4dcf7c..27ad0c5 100644 --- a/ctypescrypto/__init__.py +++ b/ctypescrypto/__init__.py @@ -3,7 +3,15 @@ """ -from ctypes import CDLL +from ctypes import CDLL,c_char_p + +def config(filename=None): + """ + Loads OpenSSL Config file. If none are specified, loads default + (compiled in) one + """ + libcrypto.OPENSSL_config(filename) libcrypto = CDLL("libcrypto.so.1.0.0") +libcrypto.OPENSSL_config.argtypes=(c_char_p,) libcrypto.OPENSSL_add_all_algorithms_conf() diff --git a/ctypescrypto/bio.py b/ctypescrypto/bio.py index f8150f7..a333105 100644 --- a/ctypescrypto/bio.py +++ b/ctypescrypto/bio.py @@ -1,3 +1,6 @@ +""" +Interface to OpenSSL BIO library +""" from ctypescrypto import libcrypto from ctypes import c_char_p, c_void_p, c_int, string_at, c_long,POINTER,byref, create_string_buffer class Membio: diff --git a/ctypescrypto/cipher.py b/ctypescrypto/cipher.py index 3320d2f..c2053e9 100644 --- a/ctypescrypto/cipher.py +++ b/ctypescrypto/cipher.py @@ -1,3 +1,7 @@ +""" +access to symmetric ciphers from libcrypto + +""" from ctypes import create_string_buffer,c_char_p,c_void_p,c_int,c_long,byref,POINTER from ctypescrypto import libcrypto from ctypescrypto.exception import LibCryptoError diff --git a/ctypescrypto/ec.py b/ctypescrypto/ec.py new file mode 100644 index 0000000..d325212 --- /dev/null +++ b/ctypescrypto/ec.py @@ -0,0 +1,33 @@ +""" +Support for EC keypair operation missing form public libcrypto API +""" + + +def create(curve,num): + """ + Creates EC keypair from the just secret key and curve name + + @param curve - name of elliptic curve + @param num - long number representing key + """ + p=libcrypto.EVP_PKEY_new() + ec=libcrypto.EC_KEY_new_by_curvename(curve.nid) + group=libcrypto.EC_KEY_get0_group(ec) + EC_KEY_set_private_key(ec,bn) + priv_key=libcrypt.BN_new() + ctx=BN_CTX_new() + h="%x"%(num) + libcrypto.BN_hex2bn(byref(priv_key),h) + libcrypto.EC_KEY_set_private_key(ec,priv_key) + pub_key=libcrypto.EC_POINT_new(group) + libcrypto.EC_POINT_mul(group,pub_key,priv_key,None,None,ctx) + libcrypto.BN_free(a) + libcrypto.EVP_PKEY_set1_EC_KEY(p,ec) + libcrypto.EC_KEY_free(ec) + return PKey(ptr=p,cansign=True) + + +libcrypto.EVP_PKEY_new.restype=c_void_p +libcrypto.BN_new.restype=c_void_p +libcrypto.BN_hex2bn.argtypes(POINTER(c_void_p),c_char_p) +libcrypto.EC_KEY_set_private_key diff --git a/ctypescrypto/engine.py b/ctypescrypto/engine.py index f05fcb0..dd7c028 100644 --- a/ctypescrypto/engine.py +++ b/ctypescrypto/engine.py @@ -1,9 +1,16 @@ +""" +engine loading and configuration +""" from ctypes import * from ctypescrypto import libcrypto from ctypescrypto.exception import LibCryptoError default=None def set_default(engine): + """ + Loads specified engine and sets it as default for all + algorithms, supported by it + """ global default e=libcrypto.ENGINE_by_id(engine) if e is None: diff --git a/ctypescrypto/exception.py b/ctypescrypto/exception.py index f0f3c53..c4710ec 100644 --- a/ctypescrypto/exception.py +++ b/ctypescrypto/exception.py @@ -1,3 +1,6 @@ +""" +Exception which extracts libcrypto error information +""" from ctypes import * from ctypescrypto import libcrypto strings_loaded=False diff --git a/ctypescrypto/oid.py b/ctypescrypto/oid.py index 9852043..976cd3f 100644 --- a/ctypescrypto/oid.py +++ b/ctypescrypto/oid.py @@ -1,5 +1,6 @@ """ Interface to OpenSSL object identifier database. + It is primarily intended to deal with OIDs which are compiled into the database or defined in the openssl configuration files. diff --git a/ctypescrypto/pkey.py b/ctypescrypto/pkey.py index e4c8c02..f011443 100644 --- a/ctypescrypto/pkey.py +++ b/ctypescrypto/pkey.py @@ -1,3 +1,11 @@ +""" +low-level private/public keypair operation + +PKey object of this module is wrapper around OpenSSL EVP_PKEY object. +""" + +This module provides interface for + from ctypes import c_char_p,c_void_p,byref,c_int,c_long, c_longlong, create_string_buffer,CFUNCTYPE,POINTER from ctypescrypto import libcrypto from ctypescrypto.exception import LibCryptoError,clear_err_stack @@ -8,6 +16,11 @@ class PKeyError(LibCryptoError): CALLBACK_FUNC=CFUNCTYPE(c_int,c_char_p,c_int,c_int,c_char_p) def password_callback(buf,length,rwflag,u): +""" +Example password callback for private key. Assumes that +password is store in the userdata parameter, so allows to pass password +from constructor arguments to the libcrypto keyloading functions +""" cnt=len(u) if length