def check_no_segfault():
    namespaces = {'soap': 'http://schemas.xmlsoap.org/soap/envelope/'}

    manager = xmlsec.KeysManager()
    key = xmlsec.Key.from_file(rsacert, format=consts.KeyDataFormatCertPem)
    manager.add_key(key)
    template = load_xml('enc-bad-in.xml')
    enc_data = xmlsec.template.encrypted_data_create(
        template,
        xmlsec.Transform.AES128,
        type=xmlsec.EncryptionType.CONTENT,
        ns='xenc')
    xmlsec.template.encrypted_data_ensure_cipher_value(enc_data)
    key_info = xmlsec.template.encrypted_data_ensure_key_info(enc_data,
                                                              ns='dsig')
    enc_key = xmlsec.template.add_encrypted_key(key_info,
                                                xmlsec.Transform.RSA_PKCS1)
    xmlsec.template.encrypted_data_ensure_cipher_value(enc_key)
    data = template.find('soap:Body', namespaces=namespaces)
    enc_ctx = xmlsec.EncryptionContext(manager)
    enc_ctx.key = xmlsec.Key.generate(xmlsec.KeyData.AES, 192,
                                      xmlsec.KeyDataType.SESSION)
    try:
        enc_ctx.encrypt_xml(enc_data, data)
    except Exception:
        pass
    else:
        print("exception not raised")
        exit(1)
Exemple #2
0
    def decrypt_element(encrypted_data, key, debug=False, inplace=False):
        """
        Decrypts an encrypted element.

        :param encrypted_data: The encrypted data.
        :type: lxml.etree.Element | DOMElement | basestring

        :param key: The key.
        :type: string

        :param debug: Activate the xmlsec debug
        :type: bool

        :param inplace: update passed data with decrypted result
        :type: bool

        :returns: The decrypted element.
        :rtype: lxml.etree.Element
        """

        if isinstance(encrypted_data, Element):
            encrypted_data = fromstring(str(encrypted_data.toxml()))
        if not inplace and isinstance(encrypted_data,
                                      OneLogin_Saml2_XML._element_class):
            encrypted_data = deepcopy(encrypted_data)
        elif isinstance(encrypted_data, OneLogin_Saml2_XML._text_class):
            encrypted_data = OneLogin_Saml2_XML._parse_etree(encrypted_data)

        xmlsec.enable_debug_trace(debug)
        manager = xmlsec.KeysManager()

        manager.add_key(xmlsec.Key.from_memory(key, xmlsec.KeyFormat.PEM,
                                               None))
        enc_ctx = xmlsec.EncryptionContext(manager)
        return enc_ctx.decrypt(encrypted_data)
Exemple #3
0
    def test_encrypt_binary(self):
        root = self.load_xml('enc2-in.xml')
        enc_data = xmlsec.template.encrypted_data_create(
            root, consts.TransformAes128Cbc, type=consts.TypeEncContent, ns="xenc", mime_type="binary/octet-stream"
        )
        xmlsec.template.encrypted_data_ensure_cipher_value(enc_data)
        ki = xmlsec.template.encrypted_data_ensure_key_info(enc_data, ns="dsig")
        ek = xmlsec.template.add_encrypted_key(ki, consts.TransformRsaOaep)
        xmlsec.template.encrypted_data_ensure_cipher_value(ek)

        manager = xmlsec.KeysManager()
        manager.add_key(xmlsec.Key.from_file(self.path("rsacert.pem"), format=consts.KeyDataFormatCertPem))

        ctx = xmlsec.EncryptionContext(manager)
        ctx.key = xmlsec.Key.generate(consts.KeyDataAes, 128, consts.KeyDataTypeSession)

        encrypted = ctx.encrypt_binary(enc_data, b'test')
        self.assertIsNotNone(encrypted)
        self.assertEqual("{%s}%s" % (consts.EncNs, consts.NodeEncryptedData), encrypted.tag)

        enc_method = xmlsec.tree.find_child(enc_data, consts.NodeEncryptionMethod, consts.EncNs)
        self.assertIsNotNone(enc_method)
        self.assertEqual("http://www.w3.org/2001/04/xmlenc#aes128-cbc", enc_method.get("Algorithm"))

        ki = xmlsec.tree.find_child(enc_data, consts.NodeKeyInfo, consts.DSigNs)
        self.assertIsNotNone(ki)
        enc_method2 = xmlsec.tree.find_node(ki, consts.NodeEncryptionMethod, consts.EncNs)
        self.assertIsNotNone(enc_method2)
        self.assertEqual("http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p", enc_method2.get("Algorithm"))
        cipher_value = xmlsec.tree.find_node(ki, consts.NodeCipherValue, consts.EncNs)
        self.assertIsNotNone(cipher_value)
def encrypt_xml_node(node: Element, cert_file: str, cipher: XmlBlockCipher, key_transport: XmlKeyTransport) -> None:
    """
    Encrypt a XML node.

    The node is removed from the parent element and replaced with <EncryptedData> element.

    :param node: A XML subtree.
    :param cert_file: A path to the certificate file.
    :param cipher: Encryption algorithm to use.
    :param key_transport: Key transport algorithm to use.
    """
    # Create a container without any XML namespace to force namespace declarations in the encrypted node.
    # The decrypted element may then exist as an independent XML document.
    container = Element('container')
    parent = node.getparent()
    node_index = parent.index(node)
    container.append(node)

    # Create a template for encryption. xmlsec.template functions don't cover all libxmlsec1 features yet.
    enc_data = SubElement(container,
                          '{%s}EncryptedData' % XML_ENC_NAMESPACE,
                          {'Type': xmlsec.constants.TypeEncElement},
                          nsmap={'xmlenc': XML_ENC_NAMESPACE})
    SubElement(enc_data, '{%s}EncryptionMethod' % XML_ENC_NAMESPACE, {'Algorithm': cipher.value})
    SubElement(enc_data, '{%s}CipherData' % XML_ENC_NAMESPACE)
    xmlsec.template.encrypted_data_ensure_cipher_value(enc_data)

    # Info about the generated encryption key.
    key_info = xmlsec.template.encrypted_data_ensure_key_info(enc_data, ns='ds')
    enc_key = SubElement(key_info, '{%s}EncryptedKey' % XML_ENC_NAMESPACE)
    SubElement(enc_key, '{%s}EncryptionMethod' % XML_ENC_NAMESPACE, {'Algorithm': key_transport.value})
    SubElement(enc_key, '{%s}CipherData' % XML_ENC_NAMESPACE)
    xmlsec.template.encrypted_data_ensure_cipher_value(enc_key)

    # Info about the certificate.
    key_info = xmlsec.template.encrypted_data_ensure_key_info(enc_key, ns='ds')
    x509_data = xmlsec.template.add_x509_data(key_info)
    xmlsec.template.x509_data_add_certificate(x509_data)
    xmlsec.template.x509_data_add_issuer_serial(x509_data)

    # xmlsec library adds unnecessary newlines to the signature template.
    remove_extra_xml_whitespace(enc_data)

    # Encrypt with a newly generated key
    key_type, key_length = XML_KEY_INFO[cipher]
    manager = xmlsec.KeysManager()
    manager.add_key(xmlsec.Key.from_file(cert_file, xmlsec.constants.KeyDataFormatCertPem))
    ctx = xmlsec.EncryptionContext(manager)
    ctx.key = xmlsec.Key.generate(key_type, key_length, xmlsec.constants.KeyDataTypeSession)

    try:
        ctx.encrypt_xml(enc_data, node)
    except xmlsec.Error:
        raise SecurityError('XML encryption failed. Invalid certificate, invalid or unsupported encryption method.')

    # xmlsec library adds unnecessary tail newlines again, so we remove them.
    remove_extra_xml_whitespace(enc_data)

    # Insert the encrypted data in the position of the original node.
    parent.insert(node_index, enc_data)
Exemple #5
0
    def decrypt_element(encrypted_data, key, debug=False):
        """
        Decrypts an encrypted element.

        :param encrypted_data: The encrypted data.
        :type: lxml.etree.Element | DOMElement | basestring

        :param key: The key.
        :type: string

        :param debug: Activate the xmlsec debug
        :type: bool

        :returns: The decrypted element.
        :rtype: lxml.etree.Element
        """
        encrypted_data = OneLogin_Saml2_XML.to_etree(encrypted_data)
        xmlsec.enable_debug_trace(debug)

        manager = xmlsec.KeysManager()

        manager.add_key(xmlsec.Key.from_memory(key, xmlsec.KeyFormat.PEM,
                                               None))
        enc_ctx = xmlsec.EncryptionContext(manager)
        return enc_ctx.decrypt(encrypted_data)
Exemple #6
0
    def generate_name_id(value, sp_nq, sp_format=None, cert=None, debug=False, nq=None):
        """
        Generates a nameID.

        :param value: fingerprint
        :type: string

        :param sp_nq: SP Name Qualifier
        :type: string

        :param sp_format: SP Format
        :type: string

        :param cert: IdP Public Cert to encrypt the nameID
        :type: string

        :param debug: Activate the xmlsec debug
        :type: bool

        :returns: DOMElement | XMLSec nameID
        :rtype: string

        :param nq: IDP Name Qualifier
        :type: string
        """

        root = OneLogin_Saml2_XML.make_root("{%s}container" % OneLogin_Saml2_Constants.NS_SAML)
        name_id = OneLogin_Saml2_XML.make_child(root, '{%s}NameID' % OneLogin_Saml2_Constants.NS_SAML)
        if sp_nq is not None:
            name_id.set('SPNameQualifier', sp_nq)
        if sp_format is not None:
            name_id.set('Format', sp_format)
        if nq is not None:
            name_id.set('NameQualifier', nq)
        name_id.text = value

        if cert is not None:
            xmlsec.enable_debug_trace(debug)

            # Load the public cert
            manager = xmlsec.KeysManager()
            manager.add_key(xmlsec.Key.from_memory(cert, xmlsec.KeyFormat.CERT_PEM, None))

            # Prepare for encryption
            enc_data = xmlsec.template.encrypted_data_create(
                root, xmlsec.Transform.AES128, type=xmlsec.EncryptionType.ELEMENT, ns="xenc")

            xmlsec.template.encrypted_data_ensure_cipher_value(enc_data)
            key_info = xmlsec.template.encrypted_data_ensure_key_info(enc_data, ns="dsig")
            enc_key = xmlsec.template.add_encrypted_key(key_info, xmlsec.Transform.RSA_OAEP)
            xmlsec.template.encrypted_data_ensure_cipher_value(enc_key)

            # Encrypt!
            enc_ctx = xmlsec.EncryptionContext(manager)
            enc_ctx.key = xmlsec.Key.generate(xmlsec.KeyData.AES, 128, xmlsec.KeyDataType.SESSION)
            enc_data = enc_ctx.encrypt_xml(enc_data, name_id)
            return '<saml:EncryptedID>' + compat.to_string(OneLogin_Saml2_XML.to_string(enc_data)) + '</saml:EncryptedID>'
        else:
            return OneLogin_Saml2_XML.extract_tag_text(root, "saml:NameID")
Exemple #7
0
 def test_encrypt_xml_bad_template_bad_type_attribute(self):
     ctx = xmlsec.EncryptionContext()
     with self.assertRaisesRegex(
             xmlsec.Error,
             'unsupported `Type`, it should be `element` or `content`'):
         root = etree.Element('root')
         root.attrib['Type'] = 'foo'
         ctx.encrypt_xml(root, etree.Element('node'))
Exemple #8
0
    def check_decrypt(self, i):
        root = self.load_xml('enc%d-out.xml' % i)
        enc_data = xmlsec.tree.find_child(root, consts.NodeEncryptedData, consts.EncNs)
        self.assertIsNotNone(enc_data)

        manager = xmlsec.KeysManager()
        manager.add_key(xmlsec.Key.from_file(self.path("rsakey.pem"), format=consts.KeyDataFormatPem))
        ctx = xmlsec.EncryptionContext(manager)
        decrypted = ctx.decrypt(enc_data)
        self.assertIsNotNone(decrypted)
        self.assertEqual(self.load_xml("enc%d-in.xml" % i), root)
def test_encrypt_binary():
    # Load the public cert
    manager = xmlsec.KeysManager()
    filename = path.join(BASE_DIR, 'rsacert.pem')
    key = xmlsec.Key.from_memory(
        open(filename, 'rb').read(), xmlsec.KeyFormat.CERT_PEM, None)
    assert key is not None
    manager.add_key(key)
    template = etree.Element("root")
    assert template is not None
    # Prepare for encryption
    enc_data = xmlsec.template.encrypted_data_create(
        template,
        xmlsec.Transform.AES128,
        type=xmlsec.EncryptionType.CONTENT,
        ns="xenc",
        mime_type="binary/octet-stream")

    xmlsec.template.encrypted_data_ensure_cipher_value(enc_data)
    key_info = xmlsec.template.encrypted_data_ensure_key_info(enc_data,
                                                              ns="dsig")
    enc_key = xmlsec.template.add_encrypted_key(key_info,
                                                xmlsec.Transform.RSA_OAEP)
    xmlsec.template.encrypted_data_ensure_cipher_value(enc_key)

    # Encrypt!
    enc_ctx = xmlsec.EncryptionContext(manager)
    enc_ctx.key = xmlsec.Key.generate(xmlsec.KeyData.AES, 128,
                                      xmlsec.KeyDataType.SESSION)
    enc_data = enc_ctx.encrypt_binary(enc_data, b'test')
    assert enc_data is not None
    assert enc_data.tag == "{%s}%s" % (xmlsec.Namespace.ENC,
                                       xmlsec.Node.ENCRYPTED_DATA)
    print(xmlsec.Node.ENCRYPTION_METHOD)
    enc_method = xmlsec.tree.find_child(enc_data,
                                        xmlsec.Node.ENCRYPTION_METHOD,
                                        xmlsec.Namespace.ENC)
    assert enc_method is not None
    assert enc_method.get(
        "Algorithm") == "http://www.w3.org/2001/04/xmlenc#aes128-cbc"
    key_info = xmlsec.tree.find_child(enc_data, xmlsec.Node.KEY_INFO,
                                      xmlsec.Namespace.DS)
    assert key_info is not None
    enc_method = xmlsec.tree.find_node(key_info, xmlsec.Node.ENCRYPTION_METHOD,
                                       xmlsec.Namespace.ENC)
    assert enc_method is not None
    assert enc_method.get(
        "Algorithm") == "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"
    cipher_value = xmlsec.tree.find_node(key_info, xmlsec.Node.CIPHER_VALUE,
                                         xmlsec.Namespace.ENC)
    assert cipher_value is not None
Exemple #10
0
def test_encrypt_xml():
    # Load the public cert
    manager = xmlsec.KeysManager()
    filename = path.join(BASE_DIR, 'rsacert.pem')
    key = xmlsec.Key.from_memory(read_from_file(filename),
                                 xmlsec.KeyFormat.CERT_PEM, None)
    assert key is not None
    manager.add_key(key)
    template = parse_xml('enc1-doc.xml')
    assert template is not None
    # Prepare for encryption
    enc_data = xmlsec.template.encrypted_data_create(
        template,
        xmlsec.Transform.AES128,
        type=xmlsec.EncryptionType.ELEMENT,
        ns="xenc")

    xmlsec.template.encrypted_data_ensure_cipher_value(enc_data)
    key_info = xmlsec.template.encrypted_data_ensure_key_info(enc_data,
                                                              ns="dsig")
    enc_key = xmlsec.template.add_encrypted_key(key_info,
                                                xmlsec.Transform.RSA_OAEP)
    xmlsec.template.encrypted_data_ensure_cipher_value(enc_key)

    data = template.find('./Data')

    assert data is not None
    # Encrypt!
    enc_ctx = xmlsec.EncryptionContext(manager)
    enc_ctx.key = xmlsec.Key.generate(xmlsec.KeyData.AES, 128,
                                      xmlsec.KeyDataType.SESSION)
    enc_datsa = enc_ctx.encrypt_xml(enc_data, data)
    assert enc_data is not None
    enc_method = xmlsec.tree.find_child(enc_data,
                                        xmlsec.Node.ENCRYPTION_METHOD,
                                        xmlsec.Namespace.ENC)
    assert enc_method is not None
    assert enc_method.get(
        "Algorithm") == "http://www.w3.org/2001/04/xmlenc#aes128-cbc"
    key_info = xmlsec.tree.find_child(enc_data, xmlsec.Node.KEY_INFO,
                                      xmlsec.Namespace.DS)
    assert key_info is not None
    enc_method = xmlsec.tree.find_node(key_info, xmlsec.Node.ENCRYPTION_METHOD,
                                       xmlsec.Namespace.ENC)
    assert enc_method is not None
    assert enc_method.get(
        "Algorithm") == "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"
    cipher_value = xmlsec.tree.find_node(key_info, xmlsec.Node.CIPHER_VALUE,
                                         xmlsec.Namespace.ENC)
    assert cipher_value is not None
def test_decrypt2():
    manager = xmlsec.KeysManager()
    filename = path.join(BASE_DIR, 'rsakey.pem')
    key = xmlsec.Key.from_memory(read_from_file(filename),
                                 xmlsec.KeyFormat.PEM, None)
    assert key is not None
    manager.add_key(key)

    enc_ctx = xmlsec.EncryptionContext(manager)

    root = parse_xml("enc2-res.xml")
    enc_data = xmlsec.tree.find_child(root, xmlsec.Node.ENCRYPTED_DATA,
                                      xmlsec.Namespace.ENC)
    assert enc_data is not None
    decrypted = enc_ctx.decrypt(enc_data)
    assert decrypted.text == "\ntest\n"
Exemple #12
0
    def test_decrypt_key(self):
        root = self.load_xml('enc3-out.xml')
        enc_key = xmlsec.tree.find_child(root, consts.NodeEncryptedKey, consts.EncNs)
        self.assertIsNotNone(enc_key)

        manager = xmlsec.KeysManager()
        manager.add_key(xmlsec.Key.from_file(self.path("rsakey.pem"), format=consts.KeyDataFormatPem))
        ctx = xmlsec.EncryptionContext(manager)
        keydata = ctx.decrypt(enc_key)
        ctx.reset()
        root.remove(enc_key)
        ctx.key = xmlsec.Key.from_binary_data(consts.KeyDataAes, keydata)
        enc_data = xmlsec.tree.find_child(root, consts.NodeEncryptedData, consts.EncNs)
        self.assertIsNotNone(enc_data)
        decrypted = ctx.decrypt(enc_data)
        self.assertIsNotNone(decrypted)
        self.assertEqual(self.load_xml("enc3-in.xml"), decrypted)
Exemple #13
0
def decrypt(envelope, keyfile):
    """Decrypt all EncryptedData, using EncryptedKey from Security header.

    EncryptedKey should be a session key encrypted for given ``keyfile``.

    Expects XML similar to the example in the ``encrypt`` docstring.

    """
    # Create a key manager and load our key into it.
    manager = xmlsec.KeysManager()
    key = xmlsec.Key.from_file(keyfile, xmlsec.KeyFormat.PEM)
    manager.add_key(key)

    doc = etree.fromstring(envelope)
    header = doc.find(ns(SOAP_NS, 'Header'))
    security = header.find(ns(WSSE_NS, 'Security'))
    enc_key = security.find(ns(ENC_NS, 'EncryptedKey'))

    # Find each referenced encrypted block (each DataReference in the
    # ReferenceList of the EncryptedKey) and decrypt it.
    ref_list = enc_key.find(ns(ENC_NS, 'ReferenceList'))
    for ref in ref_list:
        # Find the EncryptedData node referenced by this DataReference.
        ref_uri = ref.get('URI')
        referenced_id = ref_uri[1:]
        enc_data = doc.xpath(
            "//enc:EncryptedData[@Id='%s']" % referenced_id,
            namespaces={'enc': ENC_NS},
        )[0]

        # XMLSec doesn't understand WSSE, therefore it doesn't understand
        # SecurityTokenReference. It expects to find EncryptedKey within the
        # KeyInfo of the EncryptedData. So we get rid of the
        # SecurityTokenReference and replace it with the EncryptedKey before
        # trying to decrypt.
        key_info = enc_data.find(ns(DS_NS, 'KeyInfo'))
        key_info.remove(key_info[0])
        key_info.append(enc_key)

        # When XMLSec decrypts, it automatically replaces the EncryptedData
        # node with the decrypted contents.
        ctx = xmlsec.EncryptionContext(manager)
        ctx.decrypt(enc_data)

    return etree.tostring(doc)
Exemple #14
0
def test_decrypt1():
    manager = xmlsec.KeysManager()
    filename = path.join(BASE_DIR, 'rsakey.pem')
    key = xmlsec.Key.from_memory(read_from_file(filename),
                                 xmlsec.KeyFormat.PEM, None)
    assert key is not None
    manager.add_key(key)

    enc_ctx = xmlsec.EncryptionContext(manager)

    root = parse_xml("enc1-res.xml")
    enc_data = xmlsec.tree.find_child(root, "EncryptedData",
                                      xmlsec.Namespace.ENC)
    assert enc_data is not None
    decrypted = enc_ctx.decrypt(enc_data)
    assert decrypted.tag == "Data"

    compare("enc1-doc.xml", root)
def decrypt_xml(tree: ElementTree, key_file: str) -> int:
    """
    Decrypt a XML document.

    :param tree: The XML document to decrypt.
    :param key_file: A path to an encryption key file.
    :return: The number of decrypted elements
    """
    encrypted_elements = tree.findall(".//{%s}EncryptedData" % XML_ENC_NAMESPACE)
    if encrypted_elements:
        manager = xmlsec.KeysManager()
        manager.add_key(xmlsec.Key.from_file(key_file, xmlsec.constants.KeyDataFormatPem))
        enc_ctx = xmlsec.EncryptionContext(manager)
        for elm in encrypted_elements:
            enc_ctx.decrypt(elm)

        remove_extra_xml_whitespace(tree.getroot())
    return len(encrypted_elements)
Exemple #16
0
    def decrypt(self, encrypted_data, get_object=False):
        # load private key in pem format (assuming that there is no password)
        key = xmlsec.Key.from_file(self.key_path,
                                   xmlsec.constants.KeyDataFormatPem)

        # create key manager
        manager = xmlsec.KeysManager()
        manager.add_key(key)

        # create encryption context
        enc_ctx = xmlsec.EncryptionContext(manager=manager)

        decrypted_data = enc_ctx.decrypt(encrypted_data)

        if get_object is True:
            return decrypted_data

        return etree.tostring(decrypted_data)
def test_encrypt_uri():
    root = load_xml('enc2-in.xml')
    enc_data = xmlsec.template.encrypted_data_create(
        root,
        consts.TransformAes128Cbc,
        type=consts.TypeEncContent,
        ns="xenc",
        mime_type="binary/octet-stream")
    xmlsec.template.encrypted_data_ensure_cipher_value(enc_data)
    ki = xmlsec.template.encrypted_data_ensure_key_info(enc_data, ns="dsig")
    ek = xmlsec.template.add_encrypted_key(ki, consts.TransformRsaOaep)
    xmlsec.template.encrypted_data_ensure_cipher_value(ek)

    manager = xmlsec.KeysManager()
    manager.add_key(
        xmlsec.Key.from_file(rsacert, format=consts.KeyDataFormatCertPem))

    ctx = xmlsec.EncryptionContext(manager)
    ctx.key = xmlsec.Key.generate(consts.KeyDataAes, 128,
                                  consts.KeyDataTypeSession)

    with tempfile.NamedTemporaryFile(delete=False) as tmpfile:
        tmpfile.write(b'test')

    encrypted = ctx.encrypt_binary(enc_data, 'file://' + tmpfile.name)
    assert encrypted is not None
    assert "{%s}%s" % (consts.EncNs, consts.NodeEncryptedData) == encrypted.tag

    enc_method = xmlsec.tree.find_child(enc_data, consts.NodeEncryptionMethod,
                                        consts.EncNs)
    assert enc_method is not None
    assert "http://www.w3.org/2001/04/xmlenc#aes128-cbc" == enc_method.get(
        "Algorithm")

    ki = xmlsec.tree.find_child(enc_data, consts.NodeKeyInfo, consts.DSigNs)
    assert ki is not None
    enc_method2 = xmlsec.tree.find_node(ki, consts.NodeEncryptionMethod,
                                        consts.EncNs)
    assert enc_method2 is not None
    assert "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" == enc_method2.get(
        "Algorithm")
    cipher_value = xmlsec.tree.find_node(ki, consts.NodeCipherValue,
                                         consts.EncNs)
    assert cipher_value is not None
def check_decrypt(i):
    enc_out = load_xml('enc%d-out.xml' % i)
    enc_data = xmlsec.tree.find_child(enc_out, consts.NodeEncryptedData,
                                      consts.EncNs)
    assert enc_data is not None

    manager = xmlsec.KeysManager()
    manager.add_key(
        xmlsec.Key.from_file(rsakey, format=consts.KeyDataFormatPem))
    ctx = xmlsec.EncryptionContext(manager)
    decrypted = ctx.decrypt(enc_data)
    assert decrypted is not None
    enc_in = load_xml("enc%d-in.xml" % i)
    #print(1, etree.tostring(enc_in))
    #print(2, etree.tostring(enc_out))
    #print(3, etree.tostring(decrypted))
    enc_in_s = etree.tostring(enc_in)
    enc_out_s = etree.tostring(enc_out)
    assert enc_in_s == enc_out_s, "{!r} != {!r}".format(enc_in_s, enc_out_s)
Exemple #19
0
    def encrypt(self, node, get_object=False):
        options = self.encryption_options

        # load the certificate in pem format
        cert = xmlsec.Key.from_file(self.cert_path,
                                    xmlsec.constants.KeyDataFormatCertPem)

        # create key manager
        manager = xmlsec.KeysManager()
        manager.add_key(cert)

        # create a encryption context
        enc_ctx = xmlsec.EncryptionContext(manager=manager)
        enc_ctx.key = xmlsec.Key.generate(options.key_data_type,
                                          options.key_size,
                                          xmlsec.constants.KeyDataTypeSession)

        # create encrypted data template
        enc_data = xmlsec.template.encrypted_data_create(
            node,
            method=options.encryption_method,
            type=xmlsec.constants.TypeEncElement)
        # ensure cipher value
        xmlsec.template.encrypted_data_ensure_cipher_value(enc_data)
        # ensure key info
        key_info = xmlsec.template.encrypted_data_ensure_key_info(enc_data)
        if options.session_key is not None:
            xmlsec.template.add_key_name(key_info, name=options.session_key)
        # add encrypted key
        enc_key = xmlsec.template.add_encrypted_key(
            key_info, method=options.key_encryption_method)
        # ensure key info's cipher value
        xmlsec.template.encrypted_data_ensure_cipher_value(enc_key)

        enc_data = enc_ctx.encrypt_xml(enc_data, node)

        if get_object is True:
            return enc_data

        return etree.tostring(enc_data)
def test_encrypt_xml():
    root = load_xml('enc1-in.xml')
    enc_data = xmlsec.template.encrypted_data_create(
        root, consts.TransformAes128Cbc, type=consts.TypeEncElement, ns="xenc")
    xmlsec.template.encrypted_data_ensure_cipher_value(enc_data)
    ki = xmlsec.template.encrypted_data_ensure_key_info(enc_data, ns="dsig")
    ek = xmlsec.template.add_encrypted_key(ki, consts.TransformRsaOaep)
    xmlsec.template.encrypted_data_ensure_cipher_value(ek)
    data = root.find('./Data')
    assert data is not None

    manager = xmlsec.KeysManager()
    manager.add_key(
        xmlsec.Key.from_file(rsacert, format=consts.KeyDataFormatCertPem))

    ctx = xmlsec.EncryptionContext(manager)
    ctx.key = xmlsec.Key.generate(consts.KeyDataAes, 128,
                                  consts.KeyDataTypeSession)

    encrypted = ctx.encrypt_xml(enc_data, data)
    assert encrypted is not None

    enc_method = xmlsec.tree.find_child(enc_data, consts.NodeEncryptionMethod,
                                        consts.EncNs)
    assert enc_method is not None
    assert enc_method.get(
        "Algorithm") == "http://www.w3.org/2001/04/xmlenc#aes128-cbc"
    ki = xmlsec.tree.find_child(enc_data, consts.NodeKeyInfo, consts.DSigNs)
    assert ki is not None
    enc_method2 = xmlsec.tree.find_node(ki, consts.NodeEncryptionMethod,
                                        consts.EncNs)
    assert enc_method2 is not None
    assert enc_method2.get(
        "Algorithm") == "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"
    cipher_value = xmlsec.tree.find_node(ki, consts.NodeCipherValue,
                                         consts.EncNs)
    assert cipher_value is not None
def test_decrypt_key():
    root = load_xml('enc3-out.xml')
    enc_key = xmlsec.tree.find_child(root, consts.NodeEncryptedKey,
                                     consts.EncNs)
    assert enc_key is not None

    manager = xmlsec.KeysManager()
    manager.add_key(
        xmlsec.Key.from_file(rsakey, format=consts.KeyDataFormatPem))
    ctx = xmlsec.EncryptionContext(manager)
    keydata = ctx.decrypt(enc_key)
    ctx.reset()
    root.remove(enc_key)
    ctx.key = xmlsec.Key.from_binary_data(consts.KeyDataAes, keydata)
    enc_data = xmlsec.tree.find_child(root, consts.NodeEncryptedData,
                                      consts.EncNs)
    assert enc_data is not None
    decrypted = ctx.decrypt(enc_data)
    assert decrypted is not None
    enc_in = load_xml("enc3-in.xml")
    enc_in_s = etree.tostring(enc_in)
    decrypted_s = etree.tostring(decrypted)
    assert enc_in_s == decrypted_s, "{!r} != {!r}".format(
        enc_in_s, decrypted_s)
Exemple #22
0
 def test_init(self):
     ctx = xmlsec.EncryptionContext(manager=xmlsec.KeysManager())
     del ctx
Exemple #23
0
 def test_key(self):
     ctx = xmlsec.EncryptionContext(manager=xmlsec.KeysManager())
     self.assertIsNone(ctx.key)
     ctx.key = xmlsec.Key.from_file(self.path("rsacert.pem"), format=consts.KeyDataFormatCertPem)
     self.assertIsNotNone(ctx.key)
Exemple #24
0
 def test_set_key_bad_type(self):
     ctx = xmlsec.EncryptionContext(manager=xmlsec.KeysManager())
     with self.assertRaisesRegex(TypeError,
                                 r'instance of \*xmlsec.Key\* expected.'):
         ctx.key = ''
Exemple #25
0
 def test_no_key(self):
     ctx = xmlsec.EncryptionContext(manager=xmlsec.KeysManager())
     self.assertIsNone(ctx.key)
Exemple #26
0
 def test_set_invalid_key(self):
     ctx = xmlsec.EncryptionContext(manager=xmlsec.KeysManager())
     with self.assertRaisesRegex(TypeError, 'empty key.'):
         ctx.key = xmlsec.Key()
Exemple #27
0
#samlp_response = authn_response.signature_check(xmlstr, must=0, require_response_signature=0)

# ea = samlp_response.encrypted_assertion[0]
# ea.encrypted_data.cipher_data.cipher_value.text

# consulta python-xmlsec
# https://github.com/mehcode/python-xmlsec/issues/22

from lxml import etree
import xmlsec

xmlsec.enable_debug_trace(True)
km = xmlsec.KeysManager()

km.add_key(xmlsec.Key.from_file(conf.key_file, xmlsec.KeyFormat.PEM))
enc_ctx = xmlsec.EncryptionContext(km)

# root = etree.parse("response.xml").getroot()
root = etree.XML(xmlstr.encode('ascii'))
node = root.xpath(
    "//enc:EncryptedData",
    namespaces={'enc': 'http://www.w3.org/2001/04/xmlenc#'},
)
enc_data = node[0]

print()
print(etree.tostring(enc_data))
print()
decrypted = enc_ctx.decrypt(enc_data)

print()
Exemple #28
0
 def test_encrypt_uri_fail(self):
     ctx = xmlsec.EncryptionContext()
     with self.assertRaisesRegex(xmlsec.Error, 'failed to encrypt URI'):
         ctx.encrypt_uri(etree.Element('root'), '')
Exemple #29
0
 def decrypt_saml(self, verified_saml):
     '''
     1) First we determine the encryption method and set the key_data_constant appropriately
     '''
     encryption_method_node = verified_saml.find(
         '{*}EncryptedAssertion').find('{*}EncryptedData').find(
             '{*}EncryptionMethod')
     if encryption_method_node is not None:
         """
         Supported Encryption Algorithms are:
             Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"
             Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"
             Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"
         """
         encryption_method = encryption_method_node.attrib['Algorithm']
         encryption_method = encryption_method.split('#')[-1]
         if 'DES' in encryption_method.upper():
             key_data_constant = xmlsec.constants.KeyDataDes
         else:
             key_data_constant = xmlsec.constants.KeyDataAes
     # TODO - This assert should be an exception
     assert encryption_method in self.allowed_decryption_methods
     '''
     2) Next we Locate the EncryptedKey element 
         The EncryptedKey element will either be embedded inside the KeyInfo element
         OR the RetrievalMethod will Reference the EncryptedKey element ID
         Search 'RetrievalMethod' here for more info:
             http://docs.oasis-open.org/security/saml/v2.0/sstc-saml-errata-2.0-cd-04.html
     '''
     key_info = verified_saml.find('{*}EncryptedAssertion').find(
         '{*}EncryptedData').find('{*}KeyInfo')
     if key_info.find('{*}EncryptedKey') is not None:
         # If the EncryptedKey is embedded inside KeyInfo then just grab it and move on.
         encrypted_key = key_info.find('{*}EncryptedKey')
     elif key_info.find('{*}RetrievalMethod') is not None:
         # If there is a RetrievalMethod then we need to search for the EncryptedKey
         enc_assertion = verified_saml.find('{*}EncryptedAssertion')
         reference_uri = key_info.find(
             '{*}RetrievalMethod').attrib['URI'].strip('#')
         namespaces = {'enc': 'http://www.w3.org/2001/04/xmlenc#'}
         # TODO - Need to make sure this nonsense with the id casing is necessary.. it might not be.
         id_alternatives = ['Id', 'id', 'ID']
         for id_case in id_alternatives:
             xpath_expression = "//enc:EncryptedKey[@{0} = '{1}']".format(
                 id_case, reference_uri)
             enc_key = enc_assertion.xpath(xpath_expression,
                                           namespaces=namespaces)
             if enc_key is not None:
                 encrypted_key = enc_key
                 break
     assert encrypted_key is not None
     '''
     3) Now we add our private key to the encryption context so that we can decrypt the encrypted_key
     '''
     try:
         key_manager = xmlsec.KeysManager()
         '''
         This can be changed to load the key from a file like so if necessary:
             key_manager.add_key(xmlsec.Key.from_file(key, xmlsec.KeyFormat.PEM))
         '''
         key_manager.add_key(
             xmlsec.Key.from_data(self.key, xmlsec.KeyFormat.PEM))
         encryption_context = xmlsec.EncryptionContext(key_manager)
         key_data = encryption_context.decrypt(encrypted_key)
         assert key_data is not None
     except Exception as e:
         # TODO - This exception needs to be more specific but I don't know what kind of exception it will throw yet
         print('Failed decryption with key: ')
         print(e)
         # We failed to decrypt key_data so we should return None so that Entity knows to try the next key.
         return None
     '''
     4) Now that we decrypted encrypted_key we clear the encryption context and use that key to decrypt the assertion
     '''
     encryption_context.reset()
     encryption_context.key = xmlsec.Key.from_binary_data(
         self.key_data_constant, key_data)
     encrypted_data = verified_saml.find('{*}EncryptedAssertion').find(
         '{*}EncryptedData')
     decrypted_assertion = encryption_context.decrypt(encrypted_data)
     encryption_context.reset()
     encrypted_assertion = verified_saml.find('{*}EncryptedAssertion')
     verified_saml.remove(encrypted_assertion)
     verified_saml.append(decrypted_assertion)
     return verified_saml
Exemple #30
0
 def test_decrypt_bad_args(self):
     ctx = xmlsec.EncryptionContext()
     with self.assertRaises(TypeError):
         ctx.decrypt('')