diff --git a/src/xmlsec/crypto.py b/src/xmlsec/crypto.py index 29f0264e..8101739f 100644 --- a/src/xmlsec/crypto.py +++ b/src/xmlsec/crypto.py @@ -19,6 +19,7 @@ def from_keyspec(keyspec, private=False, signature_element=None): Possible keyspecs, in evaluation order : + - XMLSECCrypto If keyspec is already a loaded key, just return it. - a callable. Return a partial dict with 'f_private' set to the keyspec. - a filename. Load a PEM X.509 certificate from the file. - a PKCS#11-URI (see xmlsec.pk11.parse_uri()). Return a dict with 'f_private' @@ -29,21 +30,12 @@ def from_keyspec(keyspec, private=False, signature_element=None): the fingerprint (provided as string). - X.509 string. An X.509 certificate as string. - Resulting dictionary (used except for 'callable') : - - {'keyspec': keyspec, - 'source': 'pkcs11' or 'file' or 'fingerprint' or 'keyspec', - 'data': X.509 certificate as string if source != 'pkcs11', - 'key': Parsed key from certificate if source != 'pkcs11', - 'keysize': Keysize in bits if source != 'pkcs11', - 'f_public': rsa_x509_pem.f_public(key) if private == False, - 'f_private': rsa_x509_pem.f_private(key) if private == True, - } - :param keyspec: Keyspec as string or callable. See above. :param private: True of False, is keyspec a private key or not? :param signature_element: - :returns: dict, see above. + :returns: Loaded keyspec + + :rtype: XMlSecCrypto """ thread_local = threading.local() cache = getattr(thread_local, 'keycache', {}) @@ -147,6 +139,8 @@ def __init__(self, signature_element, keyspec): def _load_keyspec(keyspec, private=False, signature_element=None): + if isinstance(keyspec, XMlSecCrypto): + return keyspec if private and hasattr(keyspec, '__call__'): return XMLSecCryptoCallable(keyspec) if isinstance(keyspec, basestring): diff --git a/src/xmlsec/test/sign_verify_test.py b/src/xmlsec/test/sign_verify_test.py index 00b87f9f..3fff8043 100644 --- a/src/xmlsec/test/sign_verify_test.py +++ b/src/xmlsec/test/sign_verify_test.py @@ -327,6 +327,22 @@ def test_verify_href(self): res = xmlsec.verify(t, href_signer) self.assertTrue(res) + def test_already_loaded_keyspec(self): + """ + Test signing a SAML assertion with an already loaded keyspec, and making sure we can verify it. + """ + case = self.cases['SAML_assertion1'] + print("XML input :\n{}\n\n".format(case.as_buf('in.xml'))) + + private_key = xmlsec.crypto.from_keyspec(self.private_keyspec, private = True) + public_key = xmlsec.crypto.from_keyspec(self.public_keyspec, private = False) + + signed = xmlsec.sign(case.as_etree('in.xml'), + key_spec=private_key, + cert_spec=self.public_keyspec) + res = xmlsec.verify(signed, public_key) + self.assertTrue(res) + def main(): unittest.main()