]> www.wagner.pp.ru Git - oss/ctypescrypto.git/commitdiff
callback implemented
authorVictor Wagner <wagner@atlas-card.ru>
Thu, 5 Jun 2014 13:41:25 +0000 (17:41 +0400)
committerVictor Wagner <wagner@atlas-card.ru>
Thu, 5 Jun 2014 13:41:25 +0000 (17:41 +0400)
README.md
ctypescrypto/pkey.py
tests/testpkey.py [new file with mode: 0644]

index 91336ba4cd81f9e5c200b4378828a8f538af15ac..9abd63b5d14175d49d7c4e11c4e36fda71bcef6e 100644 (file)
--- a/README.md
+++ b/README.md
@@ -11,11 +11,45 @@ It is aimed to provide Python interface to OpenSSL libcrypto function
 
 Now supported:
 
-Digests
-Ciphers
-Low-level private key operations (like pkey and pkeyutl command line ops)
-(all via algorithm-agnostic EVP interface).
-Engine loading
-OpenSSL error stack to python exception conversion
-X509 certificates partially
+bio.py - interfase to OpenSSL stream abstraction BIO. Now supports
+       memory BIOs this module intended to use for parsing/serializing
+       various ASN.1 based formats like private keys or certificates
+       Status: bare minimum functionality is implemented and covered by
+       rests
+
+oid.py - interface to OpenSSL ASN.1 Object Identifier databsase.
+       Allows to convert numeric identifier (NIDs) returned by various
+       OpenSSL function to readable names or dotted-decimal OIDs and back
+       Status: Fully implemented and covered by tests.
+
+engine.py - interface to loadable modules with alternate implementations
+    of cryptoalgorithms.
+       Status: Bare minumum, neccessary to use GOST algorithms is
+       implemented.
+
+rand.py - interface to pseudo-random number generator.
+       Status: Implemented. Tests now only ensure that no segfault occurs
+       if arugments are passed correctly
+
+digests.py  - Interface  to EVP\_Digest\* family of functions. 
+       Really does almost same as hashlib, which even is able to take
+       advantage of loaded engines if compiled against dynamic libcrypto
+       Status: fully implemented and covered by tests
+
+ciphers.py - Interface to EVP\_Cipher family of function. 
+       Status: Needs complete rewriting and test coverage. Idea to keep
+       cleartext in python variable until entire text would be passed to
+       update is EVIL.
+
+pkey.py - Low-level private key operations (like pkey, genpkey and p
+    keyutl command line ops), all via algorithm-agnostic EVP interface.
+       Status: Designed and mostly implemented but not yet covered by tests
+
+exception.py OpenSSL error stack to python exception conversion
+       Implemented.
+
+x509 X509 certificates. Support parsing of X509 certificates,
+       verification and extracting of field values. Possible extnesion -
+       support creattion of PKCS10 certificate requests.
+       Status: Interface designed and partially implemented
 
index d5e09ced0797d479dc18e40424c41a81baef86e1..676d324fb1cda61eb885f677189da3f010f3a9f0 100644 (file)
@@ -6,6 +6,16 @@ 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)
+       cnt=len(u)
+       if length<cnt:
+               cnt=length
+       memmove(buf,u,cnt)
+       return cnt
+
+_cb=CALLBACK_FUNC(password_callback)
+
 class PKey:
        def __init__(self,ptr,cansign)
                self.key=ptr:
@@ -27,7 +37,7 @@ class PKey:
        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))
+               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 """
@@ -49,9 +59,9 @@ class PKey:
                """
                ctx=libcrypto.EVP_PKEY_CTX_new(self.key,None)
                if ctx is None:
-                       raise PkeyError("Initailizing sign context")
+                       raise PKeyError("Initailizing sign context")
                if libcrypto.EVP_PKEY_sign_init(ctx)<1:
-                       raise PkeyError("sign_init")
+                       raise PKeyError("sign_init")
                for oper in kwargs:
                        rv=libcrypto.EVP_PKEY_CTX_ctrl_str(ctx,oper,kwargs[oper])
                        if rw=-2:
@@ -61,7 +71,7 @@ class PKey:
                # Find out signature size
                siglen=c_long(0)
                if libcrypto.EVP_PKEY_sign(ctx,None,byref(siglen),digest,len(digest))<1:
-                       raise PkeyError("signing")      
+                       raise PKeyError("signing")      
                sig=create_string_buffer(siglen.value)
                libcrypto.EVP_PKEY_sign(ctx,sig,byref(signlen),digest,len(digest)
                libcrypto.EVP_PKEY_CTX_free(ctx)
@@ -74,9 +84,9 @@ class PKey:
                """
                ctx=libcrypto.EVP_PKEY_CTX_new(self.key,None)
                if ctx is None:
-                       raise PkeyError("Initailizing verify context")
+                       raise PKeyError("Initailizing verify context")
                if libcrypto.EVP_PKEY_verify_init(ctx)<1:
-                       raise PkeyError("verify_init")
+                       raise PKeyError("verify_init")
                for oper in kwargs:
                        rv=libcrypto.EVP_PKEY_CTX_ctrl_str(ctx,oper,kwargs[oper])
                        if rw=-2:
diff --git a/tests/testpkey.py b/tests/testpkey.py
new file mode 100644 (file)
index 0000000..3dd1d61
--- /dev/null
@@ -0,0 +1,90 @@
+from ctypescrypto.pkey import PKey
+import unittest
+
+class TestReadPkey(unittest.TestCase):
+       test_unencrypted_pem(self):
+               rsa="""-----BEGIN PRIVATE KEY-----
+MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAL9CzVZu9bczTmB8
+776pPUoPo6WbAfwQqqiGrj91bk2mYE+MNLo4yIQH45IcwGzkyS8+YyQJf8Bux5BC
+oZ2nwzXm5+JZkxkN1mtMzit2D7/hHmrZLoSbr0sxXFrD4a35RI4hXnSK9Sk01sXA
+Te2OgHzm5nk1sG97G6SFq7CHe3gvAgMBAAECgYAgGV8K7Y5xk7vIt88oyZCOuHc3
+mP9JRabOp+PgpJ3BjHXHg/lpc5Q7jHNmF0s4O2GEe0z6RFnbevwlOvmS0xAQ1hpg
+5TnVVkiZvcJeQaZqWIlEOaLqA12YdhSyorfB6p3tfQ7ZmQusg3SCsru5kPJV4sm0
+I+MuRCQZWSzIqelloQJBAPbtScJI0lXx8sktntZi69cAVvLtz5z1T7bZwFakNkNE
+SUCjNc/hEEI6/1LScV8Kx9kgQ0+W8smu+GyUDceyVFECQQDGSeS7cTmojkiPQxPB
+zb0vS+Nfpq6oYsx+gn5TBgMeWIZZrtMEaUU2o+rwsjKBP/gy6D1zC2b4W5O/A/7a
+1GR/AkBUQhYoKKc1UpExGtMXfrvRKrmAvatZeM/Rqi4aooAtpfCFEOw82iStJOqY
+/VxYPRqCuaKeVvjT31O/4SlumihxAkBahRU0NKYbuoiJThfQ23lIBB7SZadKG4A7
+KJs+j3oQ+lyqyFJwqxX7sazpIJBJzMgjhT24LTZenn++LbbEcz1FAkBmDmxoq7qO
+Ao6uTm8fnkD4C836wS4mYAPqwRBK1JvnEXEQee9irf+ip89BAg74ViTcGF9lwJwQ
+gOM+X5Db+3pK
+-----END PRIVATE KEY-----
+"""
+               keytext="""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:
+    6e:4d:a6:60:4f:8c:34:ba:38:c8:84:07:e3:92:1c:
+    c0:6c:e4:c9:2f:3e:63:24:09:7f:c0:6e:c7:90:42:
+    a1:9d:a7:c3:35:e6:e7:e2:59:93:19:0d:d6:6b:4c:
+    ce:2b:76:0f:bf:e1:1e:6a:d9:2e:84:9b:af:4b:31:
+    5c:5a:c3:e1:ad:f9:44:8e:21:5e:74:8a:f5:29:34:
+    d6:c5:c0:4d:ed:8e:80:7c:e6:e6:79:35:b0:6f:7b:
+    1b:a4:85:ab:b0:87:7b:78:2f
+Exponent: 65537 (0x10001)
+"""
+               key=PKey.privpem(rsa)
+               self.assertEqual(str(key),keytext)
+       def test_unencrypted_pem_ec(self):
+               pem="""-----BEGIN EC PRIVATE KEY-----
+MHQCAQEEICpxup3qmbwffBBLrsZx7H7/i/+Wm7jTRttMM1KkaZ3DoAcGBSuBBAAK
+oUQDQgAEVil1nlGelogimdpB8fO45icsdBt2QdYkAvhqdgCWLMG0D4Rj4oCqJcyG
+2WH8J5+0DnGujfEA4TwJ90ECvLa2SA==
+-----END EC PRIVATE KEY-----
+"""
+               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
+"""
+               
+               key=PKey.privpem(pem)
+               self.assertEqual(str(key),keytext)
+       def test_pubkey_pem(self):
+               pubkey="-----BEGIN PUBLIC KEY-----
+MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEVil1nlGelogimdpB8fO45icsdBt2QdYk
+AvhqdgCWLMG0D4Rj4oCqJcyG2WH8J5+0DnGujfEA4TwJ90ECvLa2SA==
+-----END PUBLIC KEY-----
+"""
+               key=PKey.pubpem(pem)
+               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
+"""
+               
+               self.assertEqual(str(key),keytext)
+       def test_compare(self):
+               pem="""-----BEGIN EC PRIVATE KEY-----
+MHQCAQEEICpxup3qmbwffBBLrsZx7H7/i/+Wm7jTRttMM1KkaZ3DoAcGBSuBBAAK
+oUQDQgAEVil1nlGelogimdpB8fO45icsdBt2QdYkAvhqdgCWLMG0D4Rj4oCqJcyG
+2WH8J5+0DnGujfEA4TwJ90ECvLa2SA==
+-----END EC PRIVATE KEY-----
+"""
+               pubkey="-----BEGIN PUBLIC KEY-----
+MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEVil1nlGelogimdpB8fO45icsdBt2QdYk
+AvhqdgCWLMG0D4Rj4oCqJcyG2WH8J5+0DnGujfEA4TwJ90ECvLa2SA==
+-----END PUBLIC KEY-----
+"""
+               key1=Pkey.privpem(pem)
+               key2=Pkey.pubpem(pubkey)
+               self.assertEqual(key1,key2)
+