-from ctypes import byref,c_int,c_long, c_longlong, create_string_buffer
+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 LibCryptoErrors,clear_err_stack
+from ctypescrypto.exception import LibCryptoError,clear_err_stack
from ctypescrypto.bio import Membio
class PKeyError(LibCryptoError):
pass
CALLBACK_FUNC=CFUNCTYPE(c_int,c_char_p,c_int,c_int,c_char_p)
-def password_callback(buf,length,rwflag,u)
+def password_callback(buf,length,rwflag,u):
cnt=len(u)
if length<cnt:
cnt=length
_cb=CALLBACK_FUNC(password_callback)
class PKey:
- def __init__(self,ptr,cansign)
- self.key=ptr:
- self.cansign=cansign
+ def __init__(self,ptr=None,privkey=None,pubkey=None,format="PEM",cansign=False,password=None):
+ if not ptr is None:
+ self.key=ptr
+ self.cansign=cansign
+ if not privkey is None or not pubkey is None:
+ raise TypeError("Just one of pubkey or privkey can be specified")
+ elif not privkey is None:
+ if not pubkey is None:
+ raise TypeError("Just one of pubkey or privkey can be specified")
+ b=Membio(privkey)
+ self.cansign=True
+ if format == "PEM":
+ self.key=libcrypto.PEM_read_bio_PrivateKey(b.bio,None,_cb,c_char_p(password))
+ else:
+ self.key=libcrypto.d2i_PKCS8PrivateKey_bio(b.bio,None,_cb,c_char_p(password))
+ if self.key is None:
+ raise PKeyError("error parsing private key")
+ elif not pubkey is None:
+ b=Membio(pubkey)
+ self.cansign=False
+ if format == "PEM":
+ self.key=libcrypto.PEM_read_bio_PUBKEY(b.bio,None,_cb,None)
+ else:
+ self.key=libcrypto.d2i_PUBKEY_bio(b.bio,None)
+ if self.key is None:
+ raise PKeyError("error parsing public key")
+ else:
+ raise TypeError("Neither public, nor private key is specified")
+
+
def __del__(self):
libcrypto.EVP_PKEY_free(self.key)
def __eq__(self,other):
def __str__(self):
""" printable representation of public key """
b=Membio()
- libcrypto.EVP_PKEY_print_public(b.bio,self.key,0,NULL)
+ libcrypto.EVP_PKEY_print_public(b.bio,self.key,0,None)
return str(b)
- def privpem(s,password=None):
- """ Class method for load from the pem string of private key """
- b=Membio(s)
- return PKey(libcrypto.PEM_read_bio_PrivateKey(b.bio,NULL,_cb,c_char_p(password))
- def privder(s):
- """ Class method for load from the binary ASN1 structure of private key """
- b=Membio(s)
- return PKey(libcrypto.d2i_PrivateKey_bio(b.bio,NULL),True)
- def pubpem(s):
- """ Class method for load from public key pem string"""
- b=Membio(s)
- return PKey(libcrypto.PEM_read_bio_PUBKEY(b.bio,NULL,cb,c_char_p(password)),False)
- def pubder(s):
- """ Class method for load from the binary ASN1 structure """
- b=Membio(s)
- return PKey(libcrypto.d2i_PUBKEY_bio(b.bio,NULL),False)
def sign(self,digest,**kwargs):
"""
Signs given digest and retirns signature
raise PKeyError("sign_init")
for oper in kwargs:
rv=libcrypto.EVP_PKEY_CTX_ctrl_str(ctx,oper,kwargs[oper])
- if rw=-2:
+ if rw==-2:
raise PKeyError("Parameter %s is not supported by key"%(oper))
if rv<1:
raise PKeyError("Error setting parameter %s"(oper))
if libcrypto.EVP_PKEY_sign(ctx,None,byref(siglen),digest,len(digest))<1:
raise PKeyError("signing")
sig=create_string_buffer(siglen.value)
- libcrypto.EVP_PKEY_sign(ctx,sig,byref(signlen),digest,len(digest)
+ libcrypto.EVP_PKEY_sign(ctx,sig,byref(signlen),digest,len(digest))
libcrypto.EVP_PKEY_CTX_free(ctx)
return sig.value[:siglen.value]
raise PKeyError("verify_init")
for oper in kwargs:
rv=libcrypto.EVP_PKEY_CTX_ctrl_str(ctx,oper,kwargs[oper])
- if rw=-2:
+ if rw==-2:
raise PKeyError("Parameter %s is not supported by key"%(oper))
if rv<1:
raise PKeyError("Error setting parameter %s"(oper))
raise PKeyError("keygen_init")
for oper in kwargs:
rv=libcrypto.EVP_PKEY_CTX_ctrl_str(ctx,oper,kwargs[oper])
- if rw=-2:
+ if rw==-2:
raise PKeyError("Parameter %s is not supported by key"%(oper))
if rv<1:
raise PKeyError("Error setting parameter %s"(oper))
if libcrypto.EVP_PKEY_keygen(ctx,byref(key))<=0:
raise PKeyError("Error generating key")
libcrypto.EVP_PKEY_CTX_free(ctx)
- return PKey(key,True)
+ return PKey(ptr=key,cansign=True)
+# Declare function prototypes
+libcrypto.EVP_PKEY_cmp.argtypes=(c_void_p,c_void_p)
+libcrypto.PEM_read_bio_PrivateKey.restype=c_void_p
+libcrypto.PEM_read_bio_PrivateKey.argtypes=(c_void_p,POINTER(c_void_p),CALLBACK_FUNC,c_char_p)
+libcrypto.d2i_PKCS8PrivateKey_bio.restype=c_void_p
+libcrypto.d2i_PKCS8PrivateKey_bio.argtypes=(c_void_p,POINTER(c_void_p),CALLBACK_FUNC,c_char_p)
+libcrypto.PEM_read_bio_PUBKEY.restype=c_void_p
+libcrypto.PEM_read_bio_PUBKEY.argtypes=(c_void_p,POINTER(c_void_p),CALLBACK_FUNC,c_char_p)
import unittest
class TestReadPkey(unittest.TestCase):
- test_unencrypted_pem(self):
+ def test_unencrypted_pem(self):
rsa="""-----BEGIN PRIVATE KEY-----
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAL9CzVZu9bczTmB8
776pPUoPo6WbAfwQqqiGrj91bk2mYE+MNLo4yIQH45IcwGzkyS8+YyQJf8Bux5BC
1b:a4:85:ab:b0:87:7b:78:2f
Exponent: 65537 (0x10001)
"""
- key=PKey.privpem(rsa)
+ key=PKey(privkey=rsa)
+ self.assertIsNotNone(key.key)
self.assertEqual(str(key),keytext)
def test_unencrypted_pem_ec(self):
pem="""-----BEGIN EC PRIVATE KEY-----
-----END EC PRIVATE KEY-----
"""
keytext="""Public-Key: (256 bit)
-pub:
+pub:
04:56:29:75:9e:51:9e:96:88:22:99:da:41:f1:f3:
b8:e6:27:2c:74:1b:76:41:d6:24:02:f8:6a:76:00:
96:2c:c1:b4:0f:84:63:e2:80:aa:25:cc:86:d9:61:
ASN1 OID: secp256k1
"""
- key=PKey.privpem(pem)
+ key=PKey(privkey=pem)
+ self.assertIsNotNone(key.key)
self.assertEqual(str(key),keytext)
def test_pubkey_pem(self):
- pubkey="-----BEGIN PUBLIC KEY-----
+ pub="""-----BEGIN PUBLIC KEY-----
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEVil1nlGelogimdpB8fO45icsdBt2QdYk
AvhqdgCWLMG0D4Rj4oCqJcyG2WH8J5+0DnGujfEA4TwJ90ECvLa2SA==
-----END PUBLIC KEY-----
"""
- key=PKey.pubpem(pem)
+ key=PKey(pubkey=pub)
keytext="""Public-Key: (256 bit)
-pub:
+pub:
04:56:29:75:9e:51:9e:96:88:22:99:da:41:f1:f3:
b8:e6:27:2c:74:1b:76:41:d6:24:02:f8:6a:76:00:
96:2c:c1:b4:0f:84:63:e2:80:aa:25:cc:86:d9:61:
02:bc:b6:b6:48
ASN1 OID: secp256k1
"""
-
+ self.assertIsNotNone(key.key)
self.assertEqual(str(key),keytext)
def test_compare(self):
pem="""-----BEGIN EC PRIVATE KEY-----
2WH8J5+0DnGujfEA4TwJ90ECvLa2SA==
-----END EC PRIVATE KEY-----
"""
- pubkey="-----BEGIN PUBLIC KEY-----
+ pub="""-----BEGIN PUBLIC KEY-----
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEVil1nlGelogimdpB8fO45icsdBt2QdYk
AvhqdgCWLMG0D4Rj4oCqJcyG2WH8J5+0DnGujfEA4TwJ90ECvLa2SA==
-----END PUBLIC KEY-----
"""
- key1=Pkey.privpem(pem)
- key2=Pkey.pubpem(pubkey)
+ key1=PKey(privkey=pem)
+ self.assertIsNotNone(key1.key)
+ key2=PKey(pubkey=pub)
+ self.assertIsNotNone(key2.key)
self.assertEqual(key1,key2)
+if __name__ == "__main__":
+ unittest.main()