diff options
author | Jean-Paul Calderone <exarkun@divmod.com> | 2011-06-12 21:56:13 -0400 |
---|---|---|
committer | Jean-Paul Calderone <exarkun@divmod.com> | 2011-06-12 21:56:13 -0400 |
commit | 042b66d4834b493ff82c9f2dc16aca09f39c9d8a (patch) | |
tree | be63b6322b0a3a37825acede296483a5f38c47e1 | |
parent | eecb19801a9bd04f0993440711fa495eca07408a (diff) | |
parent | e81020e6e20988d97f1b7ad0f0d493b40a24dd09 (diff) | |
download | pyopenssl-042b66d4834b493ff82c9f2dc16aca09f39c9d8a.tar.gz |
Add PKey.check method
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | OpenSSL/crypto/pkey.c | 32 | ||||
-rw-r--r-- | OpenSSL/test/test_crypto.py | 38 | ||||
-rw-r--r-- | doc/pyOpenSSL.tex | 6 |
4 files changed, 82 insertions, 0 deletions
@@ -1,5 +1,11 @@ 2011-06-12 Jean-Paul Calderone <exarkun@twistedmatrix.com> + * OpenSSL/crypto/pkey.c: Add the PKey.check method, mostly + implemented by Rick Dean, to verify the internal consistency of a + PKey instance. + +2011-06-12 Jean-Paul Calderone <exarkun@twistedmatrix.com> + * OpenSSL/crypto/crypto.c: Fix the sign and verify functions so they handle data with embedded NULs. Fix by David Brodsky <lp:~lihalla>. diff --git a/OpenSSL/crypto/pkey.c b/OpenSSL/crypto/pkey.c index 0a13aa3..1f78682 100644 --- a/OpenSSL/crypto/pkey.c +++ b/OpenSSL/crypto/pkey.c @@ -107,6 +107,37 @@ crypto_PKey_type(crypto_PKeyObj *self, PyObject *args) return PyLong_FromLong(self->pkey->type); } +static char crypto_PKey_check_doc[] = "\n\ +Check the consistency of an RSA private key.\n\ +\n\ +@return: True if key is consistent.\n\ +@raise Error: if the key is inconsistent.\n\ +@raise TypeError: if the key is of a type which cannot be checked.\n\ + Only RSA keys can currently be checked.\n\ +"; + +static PyObject * +crypto_PKey_check(crypto_PKeyObj *self, PyObject *args) { + int r; + + if (!PyArg_ParseTuple(args, ":check")) { + return NULL; + } + + if (self->pkey->type == EVP_PKEY_RSA) { + RSA *rsa; + rsa = EVP_PKEY_get1_RSA(self->pkey); + r = RSA_check_key(rsa); + if (r == 1) { + return PyBool_FromLong(1L); + } else { + FAIL(); + } + } else { + PyErr_SetString(PyExc_TypeError, "key type unsupported"); + return NULL; + } +} /* * ADD_METHOD(name) expands to a correct PyMethodDef declaration @@ -120,6 +151,7 @@ static PyMethodDef crypto_PKey_methods[] = ADD_METHOD(generate_key), ADD_METHOD(bits), ADD_METHOD(type), + ADD_METHOD(check), { NULL, NULL } }; #undef ADD_METHOD diff --git a/OpenSSL/test/test_crypto.py b/OpenSSL/test/test_crypto.py index 71da5c3..5cdcefb 100644 --- a/OpenSSL/test/test_crypto.py +++ b/OpenSSL/test/test_crypto.py @@ -207,6 +207,7 @@ MbzjS007Oe4qqBnCWaFPSnJX6uLApeTbqAxAeyCql56ULW5x6vDMNC3dwjvS/CEh 11n8RkgFIQA0AhuKSIg3CbuartRsJnWOLwgLTzsrKYL4yRog1RJrtw== -----END RSA PRIVATE KEY----- """) + encryptedPrivateKeyPEMPassphrase = b("foobar") # Some PKCS#7 stuff. Generated with the openssl command line: @@ -250,6 +251,21 @@ vrzEeLDRiiPl92dyyWmu -----END X509 CRL----- """) + +# A broken RSA private key which can be used to test the error path through +# PKey.check. +inconsistentPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY----- +MIIBPAIBAAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh +5kwIzOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEaAQJBAIqm/bz4NA1H++Vx5Ewx +OcKp3w19QSaZAwlGRtsUxrP7436QjnREM3Bm8ygU11BjkPVmtrKm6AayQfCHqJoT +zIECIQDW0BoMoL0HOYM/mrTLhaykYAVqgIeJsPjvkEhTFXWBuQIhAM3deFAvWNu4 +nklUQ37XsCT2c9tmNt1LAT+slG2JOTTRAiAuXDtC/m3NYVwyHfFm+zKHRzHkClk2 +HjubeEgjpj32AQIhAJqMGTaZVOwevTXvvHwNeH+vRWsAYU/gbx+OQB+7VOcBAiEA +oolb6NMg/R3enNPvS1O4UU1H8wpaF77L4yiSWlE0p4w= +-----END RSA PRIVATE KEY----- +""") + + class X509ExtTests(TestCase): """ Tests for L{OpenSSL.crypto.X509Extension}. @@ -512,11 +528,13 @@ class PKeyTests(TestCase): def test_pregeneration(self): """ L{PKeyType.bits} and L{PKeyType.type} return C{0} before the key is + generated. L{PKeyType.check} raises L{TypeError} before the key is generated. """ key = PKey() self.assertEqual(key.type(), 0) self.assertEqual(key.bits(), 0) + self.assertRaises(TypeError, key.check) def test_failedGeneration(self): @@ -564,6 +582,7 @@ class PKeyTests(TestCase): key.generate_key(TYPE_RSA, bits) self.assertEqual(key.type(), TYPE_RSA) self.assertEqual(key.bits(), bits) + self.assertTrue(key.check()) def test_dsaGeneration(self): @@ -579,6 +598,7 @@ class PKeyTests(TestCase): key.generate_key(TYPE_DSA, bits) self.assertEqual(key.type(), TYPE_DSA) self.assertEqual(key.bits(), bits) + self.assertRaises(TypeError, key.check) def test_regeneration(self): @@ -593,6 +613,23 @@ class PKeyTests(TestCase): self.assertEqual(key.bits(), bits) + def test_inconsistentKey(self): + """ + L{PKeyType.check} returns C{False} if the key is not consistent. + """ + key = load_privatekey(FILETYPE_PEM, inconsistentPrivateKeyPEM) + self.assertRaises(Error, key.check) + + + def test_check_wrong_args(self): + """ + L{PKeyType.check} raises L{TypeError} if called with any arguments. + """ + self.assertRaises(TypeError, PKey().check, None) + self.assertRaises(TypeError, PKey().check, object()) + self.assertRaises(TypeError, PKey().check, 1) + + class X509NameTests(TestCase): """ @@ -2077,6 +2114,7 @@ class FunctionTests(TestCase): L{dump_privatekey} writes a PEM, DER, and text. """ key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM) + self.assertTrue(key.check()) dumped_pem = dump_privatekey(FILETYPE_PEM, key) self.assertEqual(dumped_pem, cleartextPrivateKeyPEM) dumped_der = dump_privatekey(FILETYPE_ASN1, key) diff --git a/doc/pyOpenSSL.tex b/doc/pyOpenSSL.tex index 4e00c14..6a49748 100644 --- a/doc/pyOpenSSL.tex +++ b/doc/pyOpenSSL.tex @@ -555,6 +555,12 @@ Generate a public/private key pair of the type \var{type} (one of Return the type of the key. \end{methoddesc} +\begin{methoddesc}[PKey]{check}{} +Check the consistency of this key, returning True if it is consistent and +raising an exception otherwise. This is only valid for RSA keys. See the +OpenSSL RSA_check_key man page for further limitations. +\end{methoddesc} + \subsubsection{PKCS7 objects \label{openssl-pkcs7}} PKCS7 objects have the following methods: |