|
|
ec8eba |
diff -up pyOpenSSL-0.13.1/OpenSSL/crypto/crypto.c.exception pyOpenSSL-0.13.1/OpenSSL/crypto/crypto.c
|
|
|
ec8eba |
--- pyOpenSSL-0.13.1/OpenSSL/crypto/crypto.c.exception 2018-05-04 18:56:35.946486574 +0200
|
|
|
ec8eba |
+++ pyOpenSSL-0.13.1/OpenSSL/crypto/crypto.c 2018-05-04 18:56:35.950486667 +0200
|
|
|
ec8eba |
@@ -45,26 +45,72 @@ global_passphrase_callback(char *buf, in
|
|
|
ec8eba |
|
|
|
ec8eba |
func = (PyObject *)cb_arg;
|
|
|
ec8eba |
argv = Py_BuildValue("(i)", rwflag);
|
|
|
ec8eba |
- if (argv == NULL)
|
|
|
ec8eba |
+ if (argv == NULL) {
|
|
|
ec8eba |
return 0;
|
|
|
ec8eba |
+ }
|
|
|
ec8eba |
ret = PyEval_CallObject(func, argv);
|
|
|
ec8eba |
Py_DECREF(argv);
|
|
|
ec8eba |
- if (ret == NULL)
|
|
|
ec8eba |
+ if (ret == NULL) {
|
|
|
ec8eba |
return 0;
|
|
|
ec8eba |
- if (!PyBytes_Check(ret))
|
|
|
ec8eba |
- {
|
|
|
ec8eba |
+ }
|
|
|
ec8eba |
+ if (!PyBytes_Check(ret)) {
|
|
|
ec8eba |
Py_DECREF(ret);
|
|
|
ec8eba |
PyErr_SetString(PyExc_ValueError, "String expected");
|
|
|
ec8eba |
return 0;
|
|
|
ec8eba |
}
|
|
|
ec8eba |
nchars = PyBytes_Size(ret);
|
|
|
ec8eba |
- if (nchars > len)
|
|
|
ec8eba |
- nchars = len;
|
|
|
ec8eba |
+ if (nchars > len) {
|
|
|
ec8eba |
+ Py_DECREF(ret);
|
|
|
ec8eba |
+ PyErr_SetString(PyExc_ValueError,
|
|
|
ec8eba |
+ "passphrase returned by callback is too long");
|
|
|
ec8eba |
+ return 0;
|
|
|
ec8eba |
+ }
|
|
|
ec8eba |
strncpy(buf, PyBytes_AsString(ret), nchars);
|
|
|
ec8eba |
Py_DECREF(ret);
|
|
|
ec8eba |
return nchars;
|
|
|
ec8eba |
}
|
|
|
ec8eba |
|
|
|
ec8eba |
+static PyObject *
|
|
|
ec8eba |
+raise_current_error(void)
|
|
|
ec8eba |
+{
|
|
|
ec8eba |
+ if (PyErr_Occurred()) {
|
|
|
ec8eba |
+ /*
|
|
|
ec8eba |
+ * The python exception from callback is more informative than
|
|
|
ec8eba |
+ * OpenSSL's error.
|
|
|
ec8eba |
+ */
|
|
|
ec8eba |
+ flush_error_queue();
|
|
|
ec8eba |
+ return NULL;
|
|
|
ec8eba |
+ }
|
|
|
ec8eba |
+ exception_from_error_queue(crypto_Error);
|
|
|
ec8eba |
+ return NULL;
|
|
|
ec8eba |
+}
|
|
|
ec8eba |
+
|
|
|
ec8eba |
+static int
|
|
|
ec8eba |
+setup_callback(int type, PyObject *pw, pem_password_cb **cb, void **cb_arg) {
|
|
|
ec8eba |
+ if (pw == NULL) {
|
|
|
ec8eba |
+ *cb = NULL;
|
|
|
ec8eba |
+ *cb_arg = NULL;
|
|
|
ec8eba |
+ return 1;
|
|
|
ec8eba |
+ }
|
|
|
ec8eba |
+ if (type != X509_FILETYPE_PEM) {
|
|
|
ec8eba |
+ PyErr_SetString(PyExc_ValueError,
|
|
|
ec8eba |
+ "only FILETYPE_PEM key format supports encryption");
|
|
|
ec8eba |
+ return 0;
|
|
|
ec8eba |
+ }
|
|
|
ec8eba |
+ if (PyBytes_Check(pw)) {
|
|
|
ec8eba |
+ *cb = NULL;
|
|
|
ec8eba |
+ *cb_arg = PyBytes_AsString(pw);
|
|
|
ec8eba |
+ } else if (PyCallable_Check(pw)) {
|
|
|
ec8eba |
+ *cb = global_passphrase_callback;
|
|
|
ec8eba |
+ *cb_arg = pw;
|
|
|
ec8eba |
+ } else {
|
|
|
ec8eba |
+ PyErr_SetString(PyExc_TypeError,
|
|
|
ec8eba |
+ "Last argument must be string or callable");
|
|
|
ec8eba |
+ return 0;
|
|
|
ec8eba |
+ }
|
|
|
ec8eba |
+ return 1;
|
|
|
ec8eba |
+}
|
|
|
ec8eba |
+
|
|
|
ec8eba |
static char crypto_load_privatekey_doc[] = "\n\
|
|
|
ec8eba |
Load a private key from a buffer\n\
|
|
|
ec8eba |
\n\
|
|
|
ec8eba |
@@ -89,31 +135,20 @@ crypto_load_privatekey(PyObject *spam, P
|
|
|
ec8eba |
BIO *bio;
|
|
|
ec8eba |
EVP_PKEY *pkey;
|
|
|
ec8eba |
|
|
|
ec8eba |
- if (!PyArg_ParseTuple(args, "is#|O:load_privatekey", &type, &buffer, &len, &pw))
|
|
|
ec8eba |
+ if (!PyArg_ParseTuple(args, "is#|O:load_privatekey",
|
|
|
ec8eba |
+ &type, &buffer, &len, &pw)) {
|
|
|
ec8eba |
+ return NULL;
|
|
|
ec8eba |
+ }
|
|
|
ec8eba |
+ if (!setup_callback(type, pw, &cb, &cb_arg)) {
|
|
|
ec8eba |
return NULL;
|
|
|
ec8eba |
-
|
|
|
ec8eba |
- if (pw != NULL)
|
|
|
ec8eba |
- {
|
|
|
ec8eba |
- if (PyBytes_Check(pw))
|
|
|
ec8eba |
- {
|
|
|
ec8eba |
- cb = NULL;
|
|
|
ec8eba |
- cb_arg = PyBytes_AsString(pw);
|
|
|
ec8eba |
- }
|
|
|
ec8eba |
- else if (PyCallable_Check(pw))
|
|
|
ec8eba |
- {
|
|
|
ec8eba |
- cb = global_passphrase_callback;
|
|
|
ec8eba |
- cb_arg = pw;
|
|
|
ec8eba |
- }
|
|
|
ec8eba |
- else
|
|
|
ec8eba |
- {
|
|
|
ec8eba |
- PyErr_SetString(PyExc_TypeError, "Last argument must be string or callable");
|
|
|
ec8eba |
- return NULL;
|
|
|
ec8eba |
- }
|
|
|
ec8eba |
}
|
|
|
ec8eba |
|
|
|
ec8eba |
bio = BIO_new_mem_buf(buffer, len);
|
|
|
ec8eba |
- switch (type)
|
|
|
ec8eba |
- {
|
|
|
ec8eba |
+ if (bio == NULL) {
|
|
|
ec8eba |
+ exception_from_error_queue(crypto_Error);
|
|
|
ec8eba |
+ return NULL;
|
|
|
ec8eba |
+ }
|
|
|
ec8eba |
+ switch (type) {
|
|
|
ec8eba |
case X509_FILETYPE_PEM:
|
|
|
ec8eba |
pkey = PEM_read_bio_PrivateKey(bio, NULL, cb, cb_arg);
|
|
|
ec8eba |
break;
|
|
|
ec8eba |
@@ -129,10 +164,8 @@ crypto_load_privatekey(PyObject *spam, P
|
|
|
ec8eba |
}
|
|
|
ec8eba |
BIO_free(bio);
|
|
|
ec8eba |
|
|
|
ec8eba |
- if (pkey == NULL)
|
|
|
ec8eba |
- {
|
|
|
ec8eba |
- exception_from_error_queue(crypto_Error);
|
|
|
ec8eba |
- return NULL;
|
|
|
ec8eba |
+ if (pkey == NULL) {
|
|
|
ec8eba |
+ return raise_current_error();
|
|
|
ec8eba |
}
|
|
|
ec8eba |
|
|
|
ec8eba |
return (PyObject *)crypto_PKey_New(pkey, 1);
|
|
|
ec8eba |
@@ -168,49 +201,32 @@ crypto_dump_privatekey(PyObject *spam, P
|
|
|
ec8eba |
crypto_PKeyObj *pkey;
|
|
|
ec8eba |
|
|
|
ec8eba |
if (!PyArg_ParseTuple(args, "iO!|sO:dump_privatekey", &type,
|
|
|
ec8eba |
- &crypto_PKey_Type, &pkey, &cipher_name, &pw))
|
|
|
ec8eba |
+ &crypto_PKey_Type, &pkey, &cipher_name, &pw)) {
|
|
|
ec8eba |
return NULL;
|
|
|
ec8eba |
-
|
|
|
ec8eba |
- if (cipher_name != NULL && pw == NULL)
|
|
|
ec8eba |
- {
|
|
|
ec8eba |
+ }
|
|
|
ec8eba |
+ if (cipher_name != NULL && pw == NULL) {
|
|
|
ec8eba |
PyErr_SetString(PyExc_ValueError, "Illegal number of arguments");
|
|
|
ec8eba |
return NULL;
|
|
|
ec8eba |
}
|
|
|
ec8eba |
- if (cipher_name != NULL)
|
|
|
ec8eba |
- {
|
|
|
ec8eba |
+ if (cipher_name != NULL) {
|
|
|
ec8eba |
cipher = EVP_get_cipherbyname(cipher_name);
|
|
|
ec8eba |
- if (cipher == NULL)
|
|
|
ec8eba |
- {
|
|
|
ec8eba |
+ if (cipher == NULL) {
|
|
|
ec8eba |
PyErr_SetString(PyExc_ValueError, "Invalid cipher name");
|
|
|
ec8eba |
return NULL;
|
|
|
ec8eba |
}
|
|
|
ec8eba |
- if (PyBytes_Check(pw))
|
|
|
ec8eba |
- {
|
|
|
ec8eba |
- cb = NULL;
|
|
|
ec8eba |
- cb_arg = PyBytes_AsString(pw);
|
|
|
ec8eba |
- }
|
|
|
ec8eba |
- else if (PyCallable_Check(pw))
|
|
|
ec8eba |
- {
|
|
|
ec8eba |
- cb = global_passphrase_callback;
|
|
|
ec8eba |
- cb_arg = pw;
|
|
|
ec8eba |
- }
|
|
|
ec8eba |
- else
|
|
|
ec8eba |
- {
|
|
|
ec8eba |
- PyErr_SetString(PyExc_TypeError, "Last argument must be string or callable");
|
|
|
ec8eba |
+ if (!setup_callback(type, pw, &cb, &cb_arg)) {
|
|
|
ec8eba |
return NULL;
|
|
|
ec8eba |
}
|
|
|
ec8eba |
}
|
|
|
ec8eba |
|
|
|
ec8eba |
bio = BIO_new(BIO_s_mem());
|
|
|
ec8eba |
- switch (type)
|
|
|
ec8eba |
- {
|
|
|
ec8eba |
+ if (bio == NULL) {
|
|
|
ec8eba |
+ exception_from_error_queue(crypto_Error);
|
|
|
ec8eba |
+ return NULL;
|
|
|
ec8eba |
+ }
|
|
|
ec8eba |
+ switch (type) {
|
|
|
ec8eba |
case X509_FILETYPE_PEM:
|
|
|
ec8eba |
ret = PEM_write_bio_PrivateKey(bio, pkey->pkey, cipher, NULL, 0, cb, cb_arg);
|
|
|
ec8eba |
- if (PyErr_Occurred())
|
|
|
ec8eba |
- {
|
|
|
ec8eba |
- BIO_free(bio);
|
|
|
ec8eba |
- return NULL;
|
|
|
ec8eba |
- }
|
|
|
ec8eba |
break;
|
|
|
ec8eba |
|
|
|
ec8eba |
case X509_FILETYPE_ASN1:
|
|
|
ec8eba |
@@ -219,8 +235,12 @@ crypto_dump_privatekey(PyObject *spam, P
|
|
|
ec8eba |
|
|
|
ec8eba |
case X509_FILETYPE_TEXT:
|
|
|
ec8eba |
rsa = EVP_PKEY_get1_RSA(pkey->pkey);
|
|
|
ec8eba |
+ if (rsa == NULL) {
|
|
|
ec8eba |
+ ret = 0;
|
|
|
ec8eba |
+ break;
|
|
|
ec8eba |
+ }
|
|
|
ec8eba |
ret = RSA_print(bio, rsa, 0);
|
|
|
ec8eba |
- RSA_free(rsa);
|
|
|
ec8eba |
+ RSA_free(rsa);
|
|
|
ec8eba |
break;
|
|
|
ec8eba |
|
|
|
ec8eba |
default:
|
|
|
ec8eba |
@@ -229,11 +249,9 @@ crypto_dump_privatekey(PyObject *spam, P
|
|
|
ec8eba |
return NULL;
|
|
|
ec8eba |
}
|
|
|
ec8eba |
|
|
|
ec8eba |
- if (ret == 0)
|
|
|
ec8eba |
- {
|
|
|
ec8eba |
+ if (ret == 0) {
|
|
|
ec8eba |
BIO_free(bio);
|
|
|
ec8eba |
- exception_from_error_queue(crypto_Error);
|
|
|
ec8eba |
- return NULL;
|
|
|
ec8eba |
+ return raise_current_error();
|
|
|
ec8eba |
}
|
|
|
ec8eba |
|
|
|
ec8eba |
buf_len = BIO_get_mem_data(bio, &temp);
|
|
|
ec8eba |
@@ -513,8 +531,8 @@ crypto_load_pkcs7_data(PyObject *spam, P
|
|
|
ec8eba |
if (!PyArg_ParseTuple(args, "is#:load_pkcs7_data", &type, &buffer, &len))
|
|
|
ec8eba |
return NULL;
|
|
|
ec8eba |
|
|
|
ec8eba |
- /*
|
|
|
ec8eba |
- * Try to read the pkcs7 data from the bio
|
|
|
ec8eba |
+ /*
|
|
|
ec8eba |
+ * Try to read the pkcs7 data from the bio
|
|
|
ec8eba |
*/
|
|
|
ec8eba |
bio = BIO_new_mem_buf(buffer, len);
|
|
|
ec8eba |
switch (type)
|
|
|
ec8eba |
diff -up pyOpenSSL-0.13.1/OpenSSL/test/test_crypto.py.exception pyOpenSSL-0.13.1/OpenSSL/test/test_crypto.py
|
|
|
ec8eba |
--- pyOpenSSL-0.13.1/OpenSSL/test/test_crypto.py.exception 2018-05-04 18:56:35.948486620 +0200
|
|
|
ec8eba |
+++ pyOpenSSL-0.13.1/OpenSSL/test/test_crypto.py 2018-05-04 18:57:16.363420609 +0200
|
|
|
ec8eba |
@@ -7,7 +7,7 @@ Unit tests for L{OpenSSL.crypto}.
|
|
|
ec8eba |
|
|
|
ec8eba |
from unittest import main
|
|
|
ec8eba |
|
|
|
ec8eba |
-import os, re
|
|
|
ec8eba |
+import os, re, sys
|
|
|
ec8eba |
from subprocess import PIPE, Popen
|
|
|
ec8eba |
from datetime import datetime, timedelta
|
|
|
ec8eba |
|
|
|
ec8eba |
@@ -2038,6 +2038,18 @@ class FunctionTests(TestCase):
|
|
|
ec8eba |
load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, b("quack"))
|
|
|
ec8eba |
|
|
|
ec8eba |
|
|
|
ec8eba |
+ def test_load_privatekey_passphraseWrongType(self):
|
|
|
ec8eba |
+ """
|
|
|
ec8eba |
+ :py:obj:`load_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
|
|
|
ec8eba |
+ with a private key encoded in a format, that doesn't support
|
|
|
ec8eba |
+ encryption.
|
|
|
ec8eba |
+ """
|
|
|
ec8eba |
+ key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
|
|
|
ec8eba |
+ blob = dump_privatekey(FILETYPE_ASN1, key)
|
|
|
ec8eba |
+ self.assertRaises(ValueError,
|
|
|
ec8eba |
+ load_privatekey, FILETYPE_ASN1, blob, "secret")
|
|
|
ec8eba |
+
|
|
|
ec8eba |
+
|
|
|
ec8eba |
def test_load_privatekey_passphrase(self):
|
|
|
ec8eba |
"""
|
|
|
ec8eba |
L{load_privatekey} can create a L{PKey} object from an encrypted PEM
|
|
|
ec8eba |
@@ -2058,7 +2070,7 @@ class FunctionTests(TestCase):
|
|
|
ec8eba |
called = []
|
|
|
ec8eba |
def cb(*a):
|
|
|
ec8eba |
called.append(None)
|
|
|
ec8eba |
- return "quack"
|
|
|
ec8eba |
+ return b("quack")
|
|
|
ec8eba |
self.assertRaises(
|
|
|
ec8eba |
Error,
|
|
|
ec8eba |
load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
|
|
|
ec8eba |
@@ -2083,25 +2095,36 @@ class FunctionTests(TestCase):
|
|
|
ec8eba |
def test_load_privatekey_passphrase_exception(self):
|
|
|
ec8eba |
"""
|
|
|
ec8eba |
An exception raised by the passphrase callback passed to
|
|
|
ec8eba |
- L{load_privatekey} causes L{OpenSSL.crypto.Error} to be raised.
|
|
|
ec8eba |
-
|
|
|
ec8eba |
- This isn't as nice as just letting the exception pass through. The
|
|
|
ec8eba |
- behavior might be changed to that eventually.
|
|
|
ec8eba |
+ L{load_privatekey} is propagated.
|
|
|
ec8eba |
"""
|
|
|
ec8eba |
def broken(ignored):
|
|
|
ec8eba |
raise RuntimeError("This is not working.")
|
|
|
ec8eba |
self.assertRaises(
|
|
|
ec8eba |
- Error,
|
|
|
ec8eba |
+ RuntimeError,
|
|
|
ec8eba |
load_privatekey,
|
|
|
ec8eba |
FILETYPE_PEM, encryptedPrivateKeyPEM, broken)
|
|
|
ec8eba |
|
|
|
ec8eba |
|
|
|
ec8eba |
+ def test_load_privatekey_passphrase_wrong_return_type(self):
|
|
|
ec8eba |
+ """
|
|
|
ec8eba |
+ :py:obj:`load_privatekey` raises :py:obj:`ValueError` if the passphrase
|
|
|
ec8eba |
+ callback returns something other than a byte string.
|
|
|
ec8eba |
+ """
|
|
|
ec8eba |
+ self.assertRaises(
|
|
|
ec8eba |
+ ValueError,
|
|
|
ec8eba |
+ load_privatekey,
|
|
|
ec8eba |
+ FILETYPE_PEM, encryptedPrivateKeyPEM, lambda *args: 3)
|
|
|
ec8eba |
+
|
|
|
ec8eba |
+
|
|
|
ec8eba |
def test_dump_privatekey_wrong_args(self):
|
|
|
ec8eba |
"""
|
|
|
ec8eba |
L{dump_privatekey} raises L{TypeError} if called with the wrong number
|
|
|
ec8eba |
of arguments.
|
|
|
ec8eba |
"""
|
|
|
ec8eba |
self.assertRaises(TypeError, dump_privatekey)
|
|
|
ec8eba |
+ # If cipher name is given, password is required.
|
|
|
ec8eba |
+ self.assertRaises(
|
|
|
ec8eba |
+ ValueError, dump_privatekey, FILETYPE_PEM, PKey(), "foo")
|
|
|
ec8eba |
|
|
|
ec8eba |
|
|
|
ec8eba |
def test_dump_privatekey_unknown_cipher(self):
|
|
|
ec8eba |
@@ -2138,6 +2161,18 @@ class FunctionTests(TestCase):
|
|
|
ec8eba |
self.assertRaises(ValueError, dump_privatekey, 100, key)
|
|
|
ec8eba |
|
|
|
ec8eba |
|
|
|
ec8eba |
+ def test_load_privatekey_passphraseCallbackLength(self):
|
|
|
ec8eba |
+ """
|
|
|
ec8eba |
+ :py:obj:`crypto.load_privatekey` should raise an error when the passphrase
|
|
|
ec8eba |
+ provided by the callback is too long, not silently truncate it.
|
|
|
ec8eba |
+ """
|
|
|
ec8eba |
+ def cb(ignored):
|
|
|
ec8eba |
+ return "a" * 1025
|
|
|
ec8eba |
+
|
|
|
ec8eba |
+ self.assertRaises(ValueError,
|
|
|
ec8eba |
+ load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
|
|
|
ec8eba |
+
|
|
|
ec8eba |
+
|
|
|
ec8eba |
def test_dump_privatekey_passphrase(self):
|
|
|
ec8eba |
"""
|
|
|
ec8eba |
L{dump_privatekey} writes an encrypted PEM when given a passphrase.
|
|
|
ec8eba |
@@ -2152,6 +2187,17 @@ class FunctionTests(TestCase):
|
|
|
ec8eba |
self.assertEqual(loadedKey.bits(), key.bits())
|
|
|
ec8eba |
|
|
|
ec8eba |
|
|
|
ec8eba |
+ def test_dump_privatekey_passphraseWrongType(self):
|
|
|
ec8eba |
+ """
|
|
|
ec8eba |
+ :py:obj:`dump_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
|
|
|
ec8eba |
+ with a private key encoded in a format, that doesn't support
|
|
|
ec8eba |
+ encryption.
|
|
|
ec8eba |
+ """
|
|
|
ec8eba |
+ key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
|
|
|
ec8eba |
+ self.assertRaises(ValueError,
|
|
|
ec8eba |
+ dump_privatekey, FILETYPE_ASN1, key, "blowfish", "secret")
|
|
|
ec8eba |
+
|
|
|
ec8eba |
+
|
|
|
ec8eba |
def test_dump_certificate(self):
|
|
|
ec8eba |
"""
|
|
|
ec8eba |
L{dump_certificate} writes PEM, DER, and text.
|
|
|
ec8eba |
@@ -2230,6 +2276,32 @@ class FunctionTests(TestCase):
|
|
|
ec8eba |
self.assertEqual(loadedKey.bits(), key.bits())
|
|
|
ec8eba |
|
|
|
ec8eba |
|
|
|
ec8eba |
+ def test_dump_privatekey_passphrase_exception(self):
|
|
|
ec8eba |
+ """
|
|
|
ec8eba |
+ :py:obj:`dump_privatekey` should not overwrite the exception raised
|
|
|
ec8eba |
+ by the passphrase callback.
|
|
|
ec8eba |
+ """
|
|
|
ec8eba |
+ def cb(ignored):
|
|
|
ec8eba |
+ raise ArithmeticError
|
|
|
ec8eba |
+
|
|
|
ec8eba |
+ key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
|
|
|
ec8eba |
+ self.assertRaises(ArithmeticError,
|
|
|
ec8eba |
+ dump_privatekey, FILETYPE_PEM, key, "blowfish", cb)
|
|
|
ec8eba |
+
|
|
|
ec8eba |
+
|
|
|
ec8eba |
+ def test_dump_privatekey_passphraseCallbackLength(self):
|
|
|
ec8eba |
+ """
|
|
|
ec8eba |
+ :py:obj:`crypto.dump_privatekey` should raise an error when the passphrase
|
|
|
ec8eba |
+ provided by the callback is too long, not silently truncate it.
|
|
|
ec8eba |
+ """
|
|
|
ec8eba |
+ def cb(ignored):
|
|
|
ec8eba |
+ return "a" * 1025
|
|
|
ec8eba |
+
|
|
|
ec8eba |
+ key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
|
|
|
ec8eba |
+ self.assertRaises(ValueError,
|
|
|
ec8eba |
+ dump_privatekey, FILETYPE_PEM, key, "blowfish", cb)
|
|
|
ec8eba |
+
|
|
|
ec8eba |
+
|
|
|
ec8eba |
def test_load_pkcs7_data(self):
|
|
|
ec8eba |
"""
|
|
|
ec8eba |
L{load_pkcs7_data} accepts a PKCS#7 string and returns an instance of
|