From 525eda99ba5ee2791615aa3c172b0b5bbb481724 Mon Sep 17 00:00:00 2001 From: Victor Wagner Date: Thu, 5 Jun 2014 22:20:20 +0400 Subject: [PATCH] Now passess sign/verify tests --- ctypescrypto/pkey.py | 48 ++++++++++++++++++++++---- tests/testpkey.py | 81 ++++++++++++++++++++++---------------------- 2 files changed, 82 insertions(+), 47 deletions(-) diff --git a/ctypescrypto/pkey.py b/ctypescrypto/pkey.py index 0ef789d..bb99533 100644 --- a/ctypescrypto/pkey.py +++ b/ctypescrypto/pkey.py @@ -31,7 +31,7 @@ class PKey: 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: @@ -75,7 +75,7 @@ class PKey: 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)) @@ -84,9 +84,9 @@ class PKey: 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): """ @@ -100,15 +100,45 @@ class PKey: 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 @@ -139,7 +169,7 @@ class PKey: 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 @@ -148,3 +178,7 @@ 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) +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) + diff --git a/tests/testpkey.py b/tests/testpkey.py index 9560c1c..4b55603 100644 --- a/tests/testpkey.py +++ b/tests/testpkey.py @@ -1,9 +1,15 @@ 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 @@ -20,7 +26,7 @@ Ao6uTm8fnkD4C836wS4mYAPqwRBK1JvnEXEQee9irf+ip89BAg74ViTcGF9lwJwQ 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: @@ -33,17 +39,13 @@ Modulus: 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: @@ -52,45 +54,44 @@ pub: 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() -- 2.39.2