1 from ctypes import byref,c_int,c_long, c_longlong, create_string_buffer
2 from ctypescrypto import libcrypto
3 from ctypescrypto.exception import LibCryptoErrors,clear_err_stack
4 from ctypescrypto.bio import Membio
6 class PKeyError(LibCryptoError):
10 def __init__(self,ptr,cansign)
14 libcrypto.EVP_PKEY_free(self.key)
15 def __eq__(self,other):
16 """ Compares two public keys. If one has private key and other
17 doesn't it doesn't affect result of comparation
19 return libcrypto.EVP_PKEY_cmp(self.key,other.key)==1
20 def __ne__(self,other):
21 return not self.__eq__(other)
23 """ printable representation of public key """
25 libcrypto.EVP_PKEY_print_public(b.bio,self.key,0,NULL)
27 def privpem(s,password=None):
28 """ Class method for load from the pem string of private key """
30 return PKey(libcrypto.PEM_read_bio_PrivateKey(b.bio,NULL,cb,c_char_p(password))
33 """ Class method for load from the binary ASN1 structure of private key """
35 return PKey(libcrypto.d2i_PrivateKey_bio(b.bio,NULL),True)
37 """ Class method for load from public key pem string"""
39 return PKey(libcrypto.PEM_read_bio_PUBKEY(b.bio,NULL,cb,c_char_p(password)),False)
41 """ Class method for load from the binary ASN1 structure """
43 return PKey(libcrypto.d2i_PUBKEY_bio(b.bio,NULL),False)
44 def sign(self,digest,**kwargs):
46 Signs given digest and retirns signature
47 Keyword arguments allows to set various algorithm-specific
48 parameters. See pkeyutl(1) manual.
50 ctx=libcrypto.EVP_PKEY_CTX_new(self.key,None)
52 raise PkeyError("Initailizing sign context")
53 if libcrypto.EVP_PKEY_sign_init(ctx)<1:
54 raise PkeyError("sign_init")
56 rv=libcrypto.EVP_PKEY_CTX_ctrl_str(ctx,oper,kwargs[oper])
58 raise PKeyError("Parameter %s is not supported by key"%(oper))
60 raise PKeyError("Error setting parameter %s"(oper))
61 # Find out signature size
63 if libcrypto.EVP_PKEY_sign(ctx,None,byref(siglen),digest,len(digest))<1:
64 raise PkeyError("signing")
65 sig=create_string_buffer(siglen.value)
66 libcrypto.EVP_PKEY_sign(ctx,sig,byref(signlen),digest,len(digest)
67 libcrypto.EVP_PKEY_CTX_free(ctx)
68 return sig.value[:siglen.value]
70 def verify(self,digest,signature,**kwargs):
72 Verifies given signature on given digest
73 Returns True if Ok, False if don't match
75 ctx=libcrypto.EVP_PKEY_CTX_new(self.key,None)
77 raise PkeyError("Initailizing verify context")
78 if libcrypto.EVP_PKEY_verify_init(ctx)<1:
79 raise PkeyError("verify_init")
81 rv=libcrypto.EVP_PKEY_CTX_ctrl_str(ctx,oper,kwargs[oper])
83 raise PKeyError("Parameter %s is not supported by key"%(oper))
85 raise PKeyError("Error setting parameter %s"(oper))
86 rv=libcrypto.EVP_PKEY_verify(ctx,signature,len(signature),digest,len(digest))
88 raise PKeyError("Signature verification")
89 libcrypto=EVP_PKEY_CTX_free(ctx)
91 def generate(algorithm,**kwargs):
93 Generates new private-public key pair for given algorithm
94 (string like 'rsa','ec','gost2001') and algorithm-specific
98 ameth=libcrypto.EVP_PKEY_asn1_find_str(byref(tmpeng),algorithm,-1)
100 raise PKeyError("Algorithm %s not foind\n"%(algname))
103 libcrypto.EVP_PKEY_asn1_get0_info(byref(pkey_id),None,None,None,None,ameth)
104 libcrypto.ENGINE_finish(tmpeng)
105 ctx=libcrypto.EVP_PKEY_CTX_new_id(pkey_id)
107 raise PKeyError("Creating context for key type %d"%(pkey_id.value))
108 if libcrypto.EVP_PKEY_keygen_init(ctx) <=0 :
109 raise PKeyError("keygen_init")
111 rv=libcrypto.EVP_PKEY_CTX_ctrl_str(ctx,oper,kwargs[oper])
113 raise PKeyError("Parameter %s is not supported by key"%(oper))
115 raise PKeyError("Error setting parameter %s"(oper))
117 if libcrypto.EVP_PKEY_keygen(ctx,byref(key))<=0:
118 raise PKeyError("Error generating key")
119 libcrypto.EVP_PKEY_CTX_free(ctx)
120 return PKey(key,True)