def test_encrypt_xml_node_namespaces_declared(self): root = Element( Q_NAMES['saml2p:Response'], nsmap={ 'saml2': 'urn:oasis:names:tc:SAML:2.0:assertion', 'saml2p': 'urn:oasis:names:tc:SAML:2.0:protocol', # Not used in encrypted data }) # Create an encrypted document encrypted_assertion = SubElement(root, Q_NAMES['saml2:EncryptedAssertion']) assertion = SubElement(encrypted_assertion, Q_NAMES['saml2:Assertion']) SubElement(assertion, Q_NAMES['saml2:Issuer']).text = 'CZ.NIC' encrypt_xml_node(assertion, CERT_FILE, XmlBlockCipher.AES128_CBC, XmlKeyTransport.RSA_OAEP_MGF1P) # Transfer the encrypted data to a document with no namespaces container = Element('container') container.append(encrypted_assertion[0]) document = ElementTree(container) # If the decrypted element doesn't declare all necessary namespaces, no exception is raised, but # an error such as `namespace error : Namespace prefix saml2 on Assertion is not defined` is printed. # We need to check the namespace maps. self.assertEqual(decrypt_xml(document, KEY_FILE), 1) self.assertEqual(container.nsmap, {}) self.assertEqual(container[0].nsmap, {'saml2': 'urn:oasis:names:tc:SAML:2.0:assertion'})
def test_decrypt_xml_with_document_not_encrypted(self): with cast(BinaryIO, (DATA_DIR / 'saml_response.xml').open('rb')) as f: document = parse_xml(f.read()) expected = dump_xml(document).decode('utf-8') self.assertEqual(decrypt_xml(document, KEY_FILE), 0) actual = dump_xml(document).decode('utf-8') self.assertXMLEqual(expected, actual)
def test_encrypt_xml_node(self): supported_ciphers = set(XmlBlockCipher) # type: Set[XmlBlockCipher] if LIBXMLSEC_VERSION < (1, 2, 27): # pragma: no cover supported_ciphers -= { XmlBlockCipher.AES128_GCM, XmlBlockCipher.AES192_GCM, XmlBlockCipher.AES256_GCM } for cipher in supported_ciphers: with cast(BinaryIO, (DATA_DIR / 'saml_response_decrypted.xml').open('rb')) as f: document = parse_xml(f.read()) remove_extra_xml_whitespace(document.getroot()) original = dump_xml(document).decode() # Encrypt <Assertion> assertion = document.find(".//{}".format( Q_NAMES['saml2:Assertion'])) encrypt_xml_node(assertion, CERT_FILE, cipher, XmlKeyTransport.RSA_OAEP_MGF1P) # <Assertion> replaced with <EncryptedData> self.assertIsNone( document.find(".//{}".format(Q_NAMES['saml2:Assertion']))) enc_data = document.find(".//{}/{}".format( Q_NAMES['saml2:EncryptedAssertion'], Q_NAMES['xmlenc:EncryptedData'])) self.assertIsNotNone(enc_data) self.assertEqual(enc_data[0].get('Algorithm'), cipher.value) # Verify that the original and decrypted document match. self.assertEqual(decrypt_xml(document, KEY_FILE), 1) decrypted = dump_xml(document).decode() self.assertEqual(original, decrypted)
def decrypt(self, key_file: str) -> int: """Decrypt encrypted SAML response.""" return decrypt_xml(self.document, key_file)