From 828210758e4e99f2db8aba9d7f0750b7626b0f1f Mon Sep 17 00:00:00 2001 From: Victor Wagner Date: Fri, 6 Jun 2014 17:43:20 +0400 Subject: [PATCH] Added pkey serialization (untested) and started to implement x509 --- ctypescrypto/pkey.py | 41 ++++++++++++++++++++++++++++++++++++++++- ctypescrypto/x509.py | 36 ++++++++++++++++++++++++++++-------- 2 files changed, 68 insertions(+), 9 deletions(-) diff --git a/ctypescrypto/pkey.py b/ctypescrypto/pkey.py index a561ddf..e4c8c02 100644 --- a/ctypescrypto/pkey.py +++ b/ctypescrypto/pkey.py @@ -175,6 +175,42 @@ class PKey: raise PKeyError("Error generating key") libcrypto.EVP_PKEY_CTX_free(ctx) return PKey(ptr=key,cansign=True) + def exportpub(self,format="PEM"): + """ + Returns public key as PEM or DER structure. + """ + b=Membio() + if format == "PEM": + r=libcrypto.PEM_write_bio_PUBKEY(b.bio,self.key) + else: + r=libcrypto.i2d_PUBKEY_bio(b.bio,self.key) + if r==0: + raise PKeyError("error serializing public key") + return str(b) + def exportpriv(self,format="PEM",password=None,cipher=None): + """ + Returns public key as PEM or DER Structure. + If password and cipher are specified, encrypts key + on given password, using given algorithm. Cipher must be + an ctypescrypto.cipher.CipherType object + """ + b=Membio() + if cipher is None: + evp_cipher=None + else: + if password is None: + raise NotImplementedError("Interactive password entry is not supported") + evp_cipher=cipher.cipher + if format == "PEM": + r=libcrypto.PEM_write_bio_PrivateKey(b.bio,self.key,evp_cipher,_cb, + password) + else: + if cipher is not None: + raise NotImplementedError("Der-formatted encrypted keys are not supported") + r=libcrypto.i2d_PrivateKey_bio(b.bio,self.key) + if r==0: + raise PKeyError("error serializing private key") + return str(b) @staticmethod def _configure_context(ctx,opts,skip=[]): """ @@ -237,4 +273,7 @@ libcrypto.EVP_PKEY_verify.restype=c_int libcrypto.EVP_PKEY_verify.argtypes=(c_void_p,c_char_p,c_long,c_char_p,c_long) libcrypto.EVP_PKEY_verify_init.restype=c_int libcrypto.EVP_PKEY_verify_init.argtypes=(c_void_p,) - +libcrypto.PEM_write_bio_PrivateKey.argtypes=(c_void_p,c_void_p,CALLBACK_FUNC,c_char_p) +libcrypto.PEM_write_bio_PUBKEY.argtypes=(c_void_p,c_void_p) +libcrypto.i2d_PUBKEY_bio.argtypes=(c_void_p,c_void_p) +libcrypto.i2d_PrivateKey_bio.argtypes=(c_void_p,c_void_p) diff --git a/ctypescrypto/x509.py b/ctypescrypto/x509.py index 28c587c..9005fc2 100644 --- a/ctypescrypto/x509.py +++ b/ctypescrypto/x509.py @@ -1,20 +1,28 @@ from ctypes import c_void_p from ctypescrypto.bio import Membio +from ctypescrypto.pkey import Pkey from ctypescrypto.exception import LibCryptoError from crypescrypto import libcrypto +class X509Error(LibCryptoError): + pass + + class X509Name: def __init__(self,ptr): self.ptr=ptr def __del__(self): libcrypto.X509_NAME_free(self.ptr) def __str__(self): + b=Membio() + libcrypto.X509_NAME_print_ex(b.bio,self.ptr,0,PRING_FLAG) + return str(b).decode("utf-8") def __len__(self): return libcrypto.X509_NAME_entry_count(self.ptr) def __getattr__(self,key): - + def __setattr__(self,key,val): class X509_extlist: @@ -36,21 +44,33 @@ class X509_extlist: class X509: - def __init__(self,ptr): - self.cert = ptr + def __init__(self,data=None,ptr=None,format="PEM"): + if ptr is not None: + if data is not None: + raise TypeError("Cannot use data and ptr simultaneously") + self.cert = ptr + elif data is None: + raise TypeError("data argument is required") + b=Membio(data) + if format == "PEM": + self.cert=libcrypto.PEM_read_bio_X509(b.bio,None,None,None) + else: + self.cert=libcrypto.d2i_X509_bio(b.bio,None) + if self.cert is None: + raise X509Error("error reading certificate") def __del__(self): libcrypto.X509_free(self.cert) def __str__(self): """ Returns der string of the certificate """ + b=Membio() + if libcrypto.i2d_X509_bio(b.bio,self.cert)==0: + raise X509Error("error serializing certificate") def pubkey(self): """ Returns EVP PKEy object of certificate public key""" - return PKey(libcrypto.X509_get_pubkey(self.cert,False) + return PKey(ptr=libcrypto.X509_get_pubkey(self.cert,False)) def verify(self,key): """ Verify self on given issuer key """ - def frompem(s): - """ Create X509 object from pem string """ - def fromder(s): - """ Create X509 object from der string """ + def subject(self): return X509Name(libcrypto.X509_get_subject_name(self.cert)) def issuer(self): -- 2.39.2