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))
+ self.key=libcrypto.d2i_PrivateKey_bio(b.bio,None)
if self.key is None:
raise PKeyError("error parsing private key")
elif not pubkey is None:
raise PKeyError("sign_init")
for oper in kwargs:
rv=libcrypto.EVP_PKEY_CTX_ctrl_str(ctx,oper,kwargs[oper])
- if rw==-2:
+ if rv==-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(siglen),digest,len(digest))
libcrypto.EVP_PKEY_CTX_free(ctx)
- return sig.value[:siglen.value]
+ return sig.raw[:siglen.value]
def verify(self,digest,signature,**kwargs):
"""
raise PKeyError("verify_init")
for oper in kwargs:
rv=libcrypto.EVP_PKEY_CTX_ctrl_str(ctx,oper,kwargs[oper])
- if rw==-2:
+ if rv==-2:
raise PKeyError("Parameter %s is not supported by key"%(oper))
if rv<1:
raise PKeyError("Error setting parameter %s"(oper))
rv=libcrypto.EVP_PKEY_verify(ctx,signature,len(signature),digest,len(digest))
if rv<0:
raise PKeyError("Signature verification")
- libcrypto=EVP_PKEY_CTX_free(ctx)
+ libcrypto.EVP_PKEY_CTX_free(ctx)
return rv>0
+ def derive(self,peerkey,**kwargs):
+ """
+ Derives shared key (DH,ECDH,VKO 34.10). Requires
+ private key available
+
+ @param peerkey - other key (may be public only)
+
+ Keyword parameters are algorithm-specific
+ """
+ ctx=libcrypto.EVP_PKEY_CTX_new(self.key,None)
+ if ctx is None:
+ raise PKeyError("Initailizing derive context")
+ if libcrypto.EVP_PKEY_derive_init(ctx)<1:
+ raise PKeyError("derive_init")
+ for oper in kwargs:
+ rv=libcrypto.EVP_PKEY_CTX_ctrl_str(ctx,oper,kwargs[oper])
+ if rv==-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_derive_set_peer(ctx,peerkey.key)<=0:
+ raise PKeyError("Cannot set peer key")
+ keylen=c_long(0)
+ if libcrypto.EVP_PKEY_derive(ctx,None,byref(keylen))<=0:
+ raise PKeyError("computing shared key length")
+ buf=create_string_buffer(keylen)
+ if libcrypto.EVP_PKEY_derive(ctx,buf,byref(keylen))<=0:
+ raise PKeyError("computing actual shared key")
+ libcrypto.EVP_PKEY_CTX_free(ctx)
+ return buf.raw[:keylen]
def generate(algorithm,**kwargs):
"""
Generates new private-public key pair for given algorithm
raise PKeyError("Error generating key")
libcrypto.EVP_PKEY_CTX_free(ctx)
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.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)
+libcrypto.d2i_PUBKEY_bio.restype=c_void_p
+libcrypto.d2i_PUBKEY_bio.argtypes=(c_void_p,c_void_p)
+libcrypto.EVP_PKEY_print_public.argtypes=(c_void_p,c_void_p,c_int,c_void_p)
+
from ctypescrypto.pkey import PKey
import unittest
+from base64 import b64decode, b16decode
+
+def pem2der(s):
+ start=s.find('-----\n')
+ finish=s.rfind('\n-----END')
+ data=s[start+6:finish]
+ return b64decode(data)
class TestReadPkey(unittest.TestCase):
- def test_unencrypted_pem(self):
- rsa="""-----BEGIN PRIVATE KEY-----
+ rsa="""-----BEGIN PRIVATE KEY-----
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAL9CzVZu9bczTmB8
776pPUoPo6WbAfwQqqiGrj91bk2mYE+MNLo4yIQH45IcwGzkyS8+YyQJf8Bux5BC
oZ2nwzXm5+JZkxkN1mtMzit2D7/hHmrZLoSbr0sxXFrD4a35RI4hXnSK9Sk01sXA
gOM+X5Db+3pK
-----END PRIVATE KEY-----
"""
- keytext="""Public-Key: (1024 bit)
+ rsakeytext="""Public-Key: (1024 bit)
Modulus:
00:bf:42:cd:56:6e:f5:b7:33:4e:60:7c:ef:be:a9:
3d:4a:0f:a3:a5:9b:01:fc:10:aa:a8:86:ae:3f:75:
1b:a4:85:ab:b0:87:7b:78:2f
Exponent: 65537 (0x10001)
"""
- key=PKey(privkey=rsa)
- self.assertIsNotNone(key.key)
- self.assertEqual(str(key),keytext)
- def test_unencrypted_pem_ec(self):
- pem="""-----BEGIN EC PRIVATE KEY-----
+ ec1priv="""-----BEGIN EC PRIVATE KEY-----
MHQCAQEEICpxup3qmbwffBBLrsZx7H7/i/+Wm7jTRttMM1KkaZ3DoAcGBSuBBAAK
oUQDQgAEVil1nlGelogimdpB8fO45icsdBt2QdYkAvhqdgCWLMG0D4Rj4oCqJcyG
2WH8J5+0DnGujfEA4TwJ90ECvLa2SA==
-----END EC PRIVATE KEY-----
"""
- keytext="""Public-Key: (256 bit)
+ ec1keytext="""Public-Key: (256 bit)
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:
02:bc:b6:b6:48
ASN1 OID: secp256k1
"""
-
- key=PKey(privkey=pem)
- self.assertIsNotNone(key.key)
- self.assertEqual(str(key),keytext)
- def test_pubkey_pem(self):
- pub="""-----BEGIN PUBLIC KEY-----
+ ec1pub="""-----BEGIN PUBLIC KEY-----
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEVil1nlGelogimdpB8fO45icsdBt2QdYk
AvhqdgCWLMG0D4Rj4oCqJcyG2WH8J5+0DnGujfEA4TwJ90ECvLa2SA==
-----END PUBLIC KEY-----
"""
- key=PKey(pubkey=pub)
- keytext="""Public-Key: (256 bit)
-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:
- fc:27:9f:b4:0e:71:ae:8d:f1:00:e1:3c:09:f7:41:
- 02:bc:b6:b6:48
-ASN1 OID: secp256k1
-"""
+ def test_unencrypted_pem(self):
+ key=PKey(privkey=self.rsa)
+ self.assertIsNotNone(key.key)
+ self.assertEqual(str(key),self.rsakeytext)
+ def test_unencrypted_pem_ec(self):
+
+ key=PKey(privkey=self.ec1priv)
+ self.assertIsNotNone(key.key)
+ self.assertEqual(str(key),self.ec1keytext)
+ def test_unencrypted_der_ec(self):
+ key=PKey(privkey=pem2der(self.ec1priv),format="DER")
+ self.assertIsNotNone(key.key)
+ self.assertEqual(str(key),self.ec1keytext)
+ def test_pubkey_pem(self):
+ key=PKey(pubkey=self.ec1pub)
+ self.assertIsNotNone(key.key)
+ self.assertEqual(str(key),self.ec1keytext)
+ def test_pubkey_der(self):
+ key=PKey(pubkey=pem2der(self.ec1pub),format="DER")
self.assertIsNotNone(key.key)
- self.assertEqual(str(key),keytext)
+ self.assertEqual(str(key),self.ec1keytext)
def test_compare(self):
- pem="""-----BEGIN EC PRIVATE KEY-----
-MHQCAQEEICpxup3qmbwffBBLrsZx7H7/i/+Wm7jTRttMM1KkaZ3DoAcGBSuBBAAK
-oUQDQgAEVil1nlGelogimdpB8fO45icsdBt2QdYkAvhqdgCWLMG0D4Rj4oCqJcyG
-2WH8J5+0DnGujfEA4TwJ90ECvLa2SA==
------END EC PRIVATE KEY-----
-"""
- pub="""-----BEGIN PUBLIC KEY-----
-MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEVil1nlGelogimdpB8fO45icsdBt2QdYk
-AvhqdgCWLMG0D4Rj4oCqJcyG2WH8J5+0DnGujfEA4TwJ90ECvLa2SA==
------END PUBLIC KEY-----
-"""
- key1=PKey(privkey=pem)
+ key1=PKey(privkey=self.ec1priv)
self.assertIsNotNone(key1.key)
- key2=PKey(pubkey=pub)
+ key2=PKey(pubkey=self.ec1pub)
self.assertIsNotNone(key2.key)
self.assertEqual(key1,key2)
-
+ def test_sign(self):
+ signer=PKey(privkey=self.ec1priv)
+ digest=b16decode("FFCA2587CFD4846E4CB975B503C9EB940F94566AA394E8BD571458B9DA5097D5")
+ signature=signer.sign(digest)
+ self.assertTrue(len(signature)>0)
+ verifier=PKey(pubkey=self.ec1pub)
+ self.assertTrue(verifier.verify(digest,signature))
if __name__ == "__main__":
unittest.main()