Beispiel #1
0
def sign_http_post(xmlstr, key, cert, message=False, assertion=True):
    logger.debug('http-post signing')

    signer = XMLSigner(
        signature_algorithm='rsa-sha256',
        digest_algorithm='sha256',
        c14n_algorithm='http://www.w3.org/2001/10/xml-exc-c14n#',
    )
    root = fromstring(xmlstr)

    if assertion:
        logger.debug('signing assertion')
        assertions = root.findall('{%s}Assertion' % SAML)
        for assertion in assertions:
            issuer = assertion.find('{%s}Issuer' % SAML)
            issuer.addnext(
                fromstring(
                    '<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="placeholder"></ds:Signature>'
                ))
            root = signer.sign(root,
                               reference_uri=assertion.attrib['ID'],
                               key=key,
                               cert=cert)
    if message:
        issuer = root.find('{%s}Issuer' % SAML)
        issuer.addnext(
            fromstring(
                '<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="placeholder"></ds:Signature>'
            ))
        root = signer.sign(root, key=key, cert=cert)
    return tostring(root, pretty_print=False)
Beispiel #2
0
    def assina_xml(self, xml_element, reference, key_name=None):
        cert, key = extract_cert_and_key_from_pfx(self.arquivo, self.senha)

        for element in xml_element.iter("*"):
            if element.text is not None and not element.text.strip():
                element.text = None

        signer = XMLSigner(
            method=signxml.methods.enveloped,
            signature_algorithm="rsa-sha1",
            digest_algorithm='sha1',
            c14n_algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')

        ns = {}
        ns[None] = signer.namespaces['ds']
        signer.namespaces = ns

        ref_uri = ('#%s' % reference) if reference else None
        signed_root = signer.sign(xml_element,
                                  key=key,
                                  cert=cert,
                                  reference_uri=ref_uri,
                                  key_name=key_name)
        if reference:
            element_signed = signed_root.find(".//*[@Id='%s']" % reference)
            signature = signed_root.find(
                ".//{http://www.w3.org/2000/09/xmldsig#}Signature")

            if element_signed is not None and signature is not None:
                parent = element_signed.getparent()
                parent.append(signature)
        return etree.tostring(signed_root)
Beispiel #3
0
    def assina_xml(self, xml_element, reference):
        cert, key = extract_cert_and_key_from_pfx(self.arquivo, self.senha)

        for element in xml_element.iter("*"):
            if element.text is not None and not element.text.strip():
                element.text = None

        signer = XMLSigner(
            method=signxml.methods.enveloped, signature_algorithm="rsa-sha1",
            digest_algorithm='sha1',
            c14n_algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')

        ns = {}
        ns[None] = signer.namespaces['ds']
        signer.namespaces = ns

        ref_uri = ('#%s' % reference) if reference else None
        signed_root = signer.sign(
            xml_element, key=key, cert=cert,
            reference_uri=ref_uri)
        if reference:
            element_signed = signed_root.find(".//*[@Id='%s']" % reference)
            signature = signed_root.find(
                ".//{http://www.w3.org/2000/09/xmldsig#}Signature")

            if element_signed is not None and signature is not None:
                parent = element_signed.getparent()
                parent.append(signature)
        return etree.tostring(signed_root)
Beispiel #4
0
    def assinar(self, xml, retorna_string=False):
        # busca tag que tem id(reference_uri), logo nao importa se tem namespace
        reference = xml.find(".//*[@Id]").attrib['Id']

        # retira acentos
        xml_str = remover_acentos(
            etree.tostring(xml, encoding="unicode", pretty_print=False))
        xml = etree.fromstring(xml_str)

        signer = XMLSigner(
            method=signxml.methods.enveloped,
            signature_algorithm="rsa-sha1",
            digest_algorithm='sha1',
            c14n_algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')

        ns = {None: signer.namespaces['ds']}
        signer.namespaces = ns

        ref_uri = ('#%s' % reference) if reference else None
        signed_root = signer.sign(xml,
                                  key=self.key,
                                  cert=self.cert,
                                  reference_uri=ref_uri)

        ns = {'ns': NAMESPACE_SIG}
        # coloca o certificado na tag X509Data/X509Certificate
        tagX509Data = signed_root.find('.//ns:X509Data', namespaces=ns)
        etree.SubElement(tagX509Data, 'X509Certificate').text = self.cert
        if retorna_string:
            return etree.tostring(signed_root,
                                  encoding="unicode",
                                  pretty_print=False)
        else:
            return signed_root
Beispiel #5
0
    def assina_xml(self, xml_element, reference):
        cert, key = extract_cert_and_key_from_pfx(self.arquivo, self.senha)

        for element in xml_element.iter("*"):
            if element.text is not None and not element.text.strip():
                element.text = None

        signer = XMLSigner(
            method=signxml.methods.enveloped, signature_algorithm=u"rsa-sha1",
            digest_algorithm=u'sha1',
            c14n_algorithm=u'http://www.w3.org/TR/2001/REC-xml-c14n-20010315')

        ns = {}
        ns[None] = signer.namespaces['ds']
        signer.namespaces = ns
        element_to_be_signed = xml_element.getchildren()[0].getchildren()[0]

        signed_root = signer.sign(
            element_to_be_signed, key=key.encode(), cert=cert.encode())
        if reference:
            element_signed = signed_root.find(".//*[@Id='%s']" % reference)

            signature = signed_root.find(
                ".//{http://www.w3.org/2000/09/xmldsig#}Signature")

            if element_signed is not None and signature is not None:
                parent = xml_element.getchildren()[0]
                parent.append(signature)
        return etree.tostring(xml_element, encoding=str)
Beispiel #6
0
    def test_x509_certs(self):
        from OpenSSL.crypto import load_certificate, FILETYPE_PEM, Error as OpenSSLCryptoError

        tree = etree.parse(self.example_xml_files[0])
        ca_pem_file = os.path.join(os.path.dirname(__file__), "example-ca.pem").encode("utf-8")
        with open(os.path.join(os.path.dirname(__file__), "example.pem"), "rb") as fh:
            crt = fh.read()
        with open(os.path.join(os.path.dirname(__file__), "example.key"), "rb") as fh:
            key = fh.read()
        for hash_alg in "sha1", "sha256":
            for method in methods.enveloped, methods.enveloping:
                print(hash_alg, method)
                data = tree.getroot()
                reset_tree(data, method)
                signer = XMLSigner(method=method, signature_algorithm="rsa-" + hash_alg)
                signed = signer.sign(data, key=key, cert=crt)
                signed_data = etree.tostring(signed)
                XMLVerifier().verify(signed_data, ca_pem_file=ca_pem_file)
                XMLVerifier().verify(signed_data, x509_cert=crt)
                XMLVerifier().verify(signed_data, x509_cert=load_certificate(FILETYPE_PEM, crt))

                with self.assertRaises(OpenSSLCryptoError):
                    XMLVerifier().verify(signed_data, x509_cert=crt[::-1])

                with self.assertRaisesRegexp(InvalidCertificate, "unable to get local issuer certificate"):
                    XMLVerifier().verify(signed_data)
    def assina_xml(self, xml_element):
        cert, key = extract_cert_and_key_from_pfx(self.arquivo, self.senha)

        for element in xml_element.iter("*"):
            if element.text is not None and not element.text.strip():
                element.text = None

        signer = XMLSigner(
            method=methods.enveloped,
            signature_algorithm=u"rsa-sha1",
            digest_algorithm=u"sha1",
            c14n_algorithm=u"http://www.w3.org/TR/2001/REC-xml-c14n-20010315",
        )

        ns = {}
        ns[None] = signer.namespaces["ds"]
        signer.namespaces = ns
        element_signed = xml_element.find(".//{http://nfse.goiania.go.gov.br/xsd/nfse_gyn_v02.xsd}Rps")
        signed_root = signer.sign(
            xml_element, key=key.encode(), cert=cert.encode()
        )
        signature = signed_root.find(
            ".//{http://www.w3.org/2000/09/xmldsig#}Signature"
        )

        if element_signed is not None and signature is not None:
            parent = xml_element.getchildren()[0]
            parent.append(signature)

        return etree.tostring(xml_element, encoding=str)
Beispiel #8
0
    def assinar(self, xml, retorna_string=False):
        # busca tag que tem id(reference_uri), logo nao importa se tem namespace
        reference = xml.find(".//*[@Id]").attrib['Id']
        #print('Referencia: ',reference)
        # retira acentos
        xml_str = remover_acentos(etree.tostring(xml, encoding="unicode", pretty_print=False))
        xml = etree.fromstring(xml_str)

        signer = XMLSigner(
            method=signxml.methods.enveloped, signature_algorithm="rsa-sha1",
            digest_algorithm='sha1',
            c14n_algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')

        ns = {None: signer.namespaces['ds']}
        signer.namespaces = ns
        #print('Chave......: ',self.key)
        #print('*',200)
        #print('Certificado: ',self.cert)
        ref_uri = ('#%s' % reference) if reference else None
        signed_root = signer.sign(
            xml, key=self.key, cert=self.cert, reference_uri=ref_uri)

        ns = {'ns': NAMESPACE_SIG}
        # coloca o certificado na tag X509Data/X509Certificate
        tagX509Data = signed_root.find('.//ns:X509Data', namespaces=ns)
        etree.SubElement(tagX509Data, 'X509Certificate').text = self.cert
        #print('Assinatura: ',etree.tostring(signed_root, encoding="unicode", pretty_print=False) )
        if retorna_string:
            return etree.tostring(signed_root, encoding="unicode", pretty_print=False)
        else:
            return signed_root
    def assina_xml(self, xml_element, reference):
        cert, key = extract_cert_and_key_from_pfx(self.arquivo, self.senha)

        for element in xml_element.iter("*"):
            if element.text is not None and not element.text.strip():
                element.text = None

        signer = XMLSigner(
            method=signxml.methods.enveloped,
            signature_algorithm="rsa-sha1",
            digest_algorithm="sha1",
            c14n_algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315",
        )

        ns = {}
        ns[None] = signer.namespaces["ds"]
        signer.namespaces = ns

        ref_uri = ("#%s" % reference) if reference else None
        signed_root = signer.sign(xml_element,
                                  key=key.encode(),
                                  cert=cert.encode(),
                                  reference_uri=ref_uri)
        if reference:
            element_signed = signed_root.find(".//*[@Id='%s']" % reference)
            signature = (signed_root.find(".//*[@URI='#%s']" %
                                          reference).getparent().getparent())

            if element_signed is not None and signature is not None:
                parent = element_signed.getparent()
                parent.append(signature)
        return etree.tostring(signed_root, encoding=str)
Beispiel #10
0
    def signWithCert(self, stringXml, key, returnString=True):

        xmlBuffer = etree.fromstring(stringXml)
        tree = etree.fromstring(stringXml)
        reference = tree.findall(".//*[@Id]")
        cert = self.extractCertContent()
        key = open(key, "rb").read()
        signer = XMLSigner(
            method=signxml.methods.enveloped, signature_algorithm="rsa-sha1",
            digest_algorithm='sha1',
            c14n_algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
        ns = {None: signer.namespaces['ds']}
        signer.namespaces = ns

        refUri = ('#%s' % reference) if reference else None
        signedRoot = signer.sign(
            xmlBuffer, key=key, cert=cert, reference_uri=refUri)

        ns = {'ns': NAMESPACE_SIG}
        # Insert the cert file buffered data (content) into specified tags X509Data/X509Certificate
        tagX509Data = signedRoot.find('.//ns:X509Data', namespaces=ns)
        etree.SubElement(tagX509Data, 'X509Certificate').text = cert

        if returnString:
            xmlEnvelope = etree.tostring(signedRoot, encoding="unicode",  pretty_print=False)
            return xmlEnvelope
        else:
            return signedRoot
Beispiel #11
0
    def test_x509_certs(self):
        from OpenSSL.crypto import load_certificate, FILETYPE_PEM, Error as OpenSSLCryptoError

        tree = etree.parse(self.example_xml_files[0])
        ca_pem_file = os.path.join(os.path.dirname(__file__), "example-ca.pem").encode("utf-8")
        with open(os.path.join(os.path.dirname(__file__), "example.pem"), "rb") as fh:
            crt = fh.read()
        with open(os.path.join(os.path.dirname(__file__), "example.key"), "rb") as fh:
            key = fh.read()
        for hash_alg in "sha1", "sha256":
            for method in methods.enveloped, methods.enveloping:
                for c14_transform_option in include_c14_transformation:
                    print(hash_alg, method)
                    data = tree.getroot()
                    reset_tree(data, method)
                    signer = XMLSigner(method=method, signature_algorithm="rsa-" + hash_alg,
                                       include_c14n_transform=c14_transform_option)
                    signed = signer.sign(data, key=key, cert=crt)
                    signed_data = etree.tostring(signed)
                    XMLVerifier().verify(signed_data, ca_pem_file=ca_pem_file)
                    XMLVerifier().verify(signed_data, x509_cert=crt)
                    XMLVerifier().verify(signed_data, x509_cert=load_certificate(FILETYPE_PEM, crt))
                    XMLVerifier().verify(signed_data, x509_cert=crt, cert_subject_name="*.example.com")

                    with self.assertRaises(OpenSSLCryptoError):
                        XMLVerifier().verify(signed_data, x509_cert=crt[::-1])

                    with self.assertRaises(InvalidSignature):
                        XMLVerifier().verify(signed_data, x509_cert=crt, cert_subject_name="test")

                    with self.assertRaisesRegexp(InvalidCertificate, "unable to get local issuer certificate"):
                        XMLVerifier().verify(signed_data)
Beispiel #12
0
    def sign(self, data, reference_uri):
        signer = XMLSigner(
            method=methods.detached,
            signature_algorithm="rsa-sha1",
            digest_algorithm="sha1",
            c14n_algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315",
        )

        return signer.sign(data=data, key=self.key, cert=self.cert, reference_uri="#{}".format(reference_uri))
Beispiel #13
0
 def test_signxml_changing_signature_namespace_prefix(self):
     data = etree.parse(self.example_xml_files[0]).getroot()
     signer = XMLSigner()
     signer.namespaces = dict(digi_sign=namespaces['ds'])
     signed = signer.sign(data, key=self.keys["rsa"])
     signed_data = etree.tostring(signed)
     expected_match = ("<digi_sign:Signature xmlns:"
                       "digi_sign=\"%s\">") % namespaces['ds']
     self.assertTrue(re.search(expected_match.encode('ascii'), signed_data))
Beispiel #14
0
 def test_signxml_changing_signature_namespace_prefix(self):
     data = etree.parse(self.example_xml_files[0]).getroot()
     signer = XMLSigner()
     signer.namespaces = dict(digi_sign=namespaces['ds'])
     signed = signer.sign(data, key=self.keys["rsa"])
     signed_data = etree.tostring(signed)
     expected_match = ("<digi_sign:Signature xmlns:"
                       "digi_sign=\"%s\">") % namespaces['ds']
     self.assertTrue(re.search(expected_match.encode('ascii'), signed_data))
Beispiel #15
0
def sign_http_post(xmlstr, key, cert, message=False, assertion=True):
    signer = XMLSigner(
        signature_algorithm='rsa-sha256',
        digest_algorithm='sha256',
    )
    root = fromstring(xmlstr)
    if message:
        root = signer.sign(root, key=key, cert=cert)
    if assertion:
        assertions = root.findall('{%s}Assertion' % SAML)
        for assertion in assertions:
            _assertion = signer.sign(assertion, key=key, cert=cert)
            issuer = _assertion.find('{%s}Issuer' % SAML)
            signature = _assertion.find('%sSignature' % SIG_NS)
            issuer.addnext(signature)
            assertion.getparent().replace(assertion, _assertion)
    response = tostring(root)
    return base64.b64encode(response).decode('ascii')
Beispiel #16
0
def sign_assertion(assertion, key, cert, reference_uri):

    signer = XMLSigner(signature_algorithm="rsa-sha1",
                       digest_algorithm="sha1",
                       c14n_algorithm="http://www.w3.org/2001/10/xml-exc-c14n#")

    signed_assertion_element = signer.sign(assertion,
                                           key=key,
                                           cert=cert,
                                           reference_uri=reference_uri)

    return signed_assertion_element
Beispiel #17
0
def sign(node, key_path, cert_path, get_object=False):
    key = import_key(key_path)
    cert = import_key(cert_path)
    signer = XMLSigner(
        method=methods.enveloped,
        signature_algorithm='rsa-sha1',
        digest_algorithm='sha1',
        c14n_algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
    signed_node = signer.sign(node, key=key, cert=cert)
    if get_object is True:
        return signed_node
    return etree.tostring(signed_node)
Beispiel #18
0
def sign_http_post(xmlstr, key, cert, message=False, assertion=True):
    # We have to use xml-exc-c14n# because when we isolate the Assertion
    # element below, a superfluous xmlns:samlp attribute gets added by etree.tostring()
    # which is not removed by xml-c14n11 (thus generating a wrong digest).
    signer = XMLSigner(
        signature_algorithm='rsa-sha256',
        digest_algorithm='sha256',
        c14n_algorithm='http://www.w3.org/2001/10/xml-exc-c14n#',
    )
    root = fromstring(xmlstr)
    if message:
        root = signer.sign(root, key=key, cert=cert)
    if assertion:
        assertions = root.findall('{%s}Assertion' % SAML)
        for assertion in assertions:
            _assertion = signer.sign(assertion, key=key, cert=cert)
            issuer = _assertion.find('{%s}Issuer' % SAML)
            signature = _assertion.find('%sSignature' % SIG_NS)
            issuer.addnext(signature)
            assertion.getparent().replace(assertion, _assertion)
    response = tostring(root)
    return base64.b64encode(response).decode('ascii')
Beispiel #19
0
def sign(xml, cert_data):
    signer = XMLSigner(
        method=signxml.methods.enveloped,
        signature_algorithm='rsa-sha256',
        digest_algorithm='sha256',
        c14n_algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315'
    )
    xml_root = None
    if not isinstance(xml, etree._ElementTree):
        xml = load_fromfile(xml)
    xml_root = xml.getroot()
    signed_root = signer.sign(xml_root, key=cert_data['key_str'], cert=cert_data['cert_str'])
    return etree.ElementTree(signed_root)
Beispiel #20
0
def sign_assertions(response_str):
    """ Return signed response string """
    response_element = etree.fromstring(response_str)
    cert = read_bytes("keys/cert.pem")
    key = read_bytes("keys/key.pem")
    for e in response_element.findall(
            '{urn:oasis:names:tc:SAML:2.0:assertion}Assertion'):
        signer = XMLSigner(
            c14n_algorithm="http://www.w3.org/2001/10/xml-exc-c14n#",
            signature_algorithm='rsa-sha1',
            digest_algorithm='sha1')
        signed_e = signer.sign(e, key=key, cert=cert)
        response_element.replace(e, signed_e)
    return etree.tostring(response_element, pretty_print=True)
Beispiel #21
0
def sign(element, reference_uri, certificate_data, key_data):

    signer = XMLSigner(
        signature_algorithm="rsa-sha1",
        digest_algorithm="sha1",
        c14n_algorithm="http://www.w3.org/2001/10/xml-exc-c14n#")

    # Sign XML.
    signed_element = signer.sign(element,
                                 key=key_data,
                                 cert=certificate_data,
                                 reference_uri=reference_uri)

    return signed_element
    def assina_xml(self, xml):
        ##Modificado para utilizar o signxml ao inves do libxml2 e xmlsec
        from signxml import XMLSigner
        from signxml import methods

        xml = self._prepara_doc_xml(xml)
        doc_xml = lxml.etree.fromstring(xml.encode('utf-8'))

        #buscando chave de acesso no documento e retiranto TAG Signature
        chave_de_acesso = self._ler_chave_acesso(doc_xml)
        if chave_de_acesso is None:
            raise ValueError(
                'Nao foi possivel encontrar a Tag para a assinatura.')

        #String para bytes para a leitura no signxml
        chave = self.chave.encode('utf-8')
        certificado = self.certificado.encode('utf-8')

        signer = XMLSigner(
            method=methods.enveloped,
            signature_algorithm='rsa-sha1',
            digest_algorithm='sha1',
            c14n_algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')

        #Retirar os prefixos ds: da assinatura
        ns = {}
        ns[None] = signer.namespaces['ds']
        signer.namespaces = ns

        #Assina o documento
        signed_doc = signer.sign(doc_xml,
                                 key=chave,
                                 cert=certificado,
                                 reference_uri='#{0}'.format(chave_de_acesso))

        #Selecionar apenas a tag Signature do documento.
        signature_tag = None
        for child in signed_doc:
            if 'Signature' in child.tag:
                signature_tag = child
        if signature_tag is None:
            raise ("Assinatura nao encontrada.")

        signature_tag = lxml.etree.tostring(signature_tag).decode('utf-8')

        signature_tag = self._finaliza_xml(signature_tag)

        return signature_tag
Beispiel #23
0
def make_request(binding, message, destination, key, cert):
    _binding, method, encoding = BINDINGS_TO_SAML2BINDINGS.get(binding)
    print('BINDING: {}'.format(binding))
    print('METHOD: {}'.format(binding))
    print('DESTINATION: {}'.format(destination))
    with open(message, 'rb') as fp:
        message = fp.read()
    if _binding == BINDING_HTTP_REDIRECT:
        encoded_message = encoding(message)
        print('ENCODED MESSAGE: {}'.format(encoded_message))
        arguments = {
            'SAMLRequest': encoded_message,
            'SigAlg': SIG_RSA_SHA256
        }
        args_list = [urlencode({k: arguments[k]}) for k in arguments]
        query_string = '&'.join(args_list).encode('ascii')
        digest = SHA256.new()
        digest.update(query_string)
        private_key = load_pkey_from_file(key)
        signer = PKCS1_v1_5.new(private_key)
        signed = signer.sign(digest)
        arguments['Signature'] = base64.b64encode(signed)
        query_string = urlencode(arguments)
        url = '{}?{}'.format(destination, query_string)
        print('URL: {}'.format(url))
        req_args = [url]
    elif _binding == BINDING_HTTP_POST:
        signer = XMLSigner(
            signature_algorithm='rsa-sha256',
            digest_algorithm='sha256',
        )
        root = etree.fromstring(message)
        _key = open(key, 'rb').read()
        _cert = open(cert, 'rb').read()
        print(_key, _cert)
        signed_root = signer.sign(root, key=_key, cert=_cert)
        message = etree.tostring(signed_root)
        print('SIGNED XML: {}'.format(message))
        encoded_message = encoding(message)
        print('ENCODED MESSAGE: {}'.format(encoded_message))
        url = destination
        print('URL: {}'.format(url))
        extra = {'SAMLRequest': encoded_message}
        req_args = [url, extra]
    response = getattr(requests, method)(*req_args, verify=False)
    print('RESPONSE: {}'. format(response.text))
Beispiel #24
0
    def sign_assertion(cls, root, key, cert):
        ''' Reads the certificate and private key to memory from the paths provided.
            uses signxml module to sign the root object provided.
            :param root: root object to sign
            :param : private RSA key to sign with
            :param : public certificate of the private key
            :return: a signed root object
        '''
        # Read the private key and certificate
        key = open(key, "r").read()
        cert = open(cert, "r").read()

        # Set up xml signer object
        signer = XMLSigner(c14n_algorithm=cls.C14_ALG)

        # Sign the Assertion
        return signer.sign(root, key=key, cert=cert)
Beispiel #25
0
def sign(xml, cert_data, reference_uri=None):
    signer = XMLSigner(
        method=signxml.methods.enveloped,
        signature_algorithm='rsa-sha1',
        digest_algorithm='sha1',
        c14n_algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
    xml_root = None
    if not isinstance(xml, etree._ElementTree):
        xml = load_fromfile(xml)
    xml_root = xml.getroot()
    # FIX: Isso eh uma gambiarra para poder tirar o prefixo da tag <Signature>, ja que o webservices da Betha
    # nao consegue achar a assinatura se ela tiver o prefixo do namespace padrao <ds:Signature>...
    ds = signer.namespaces['ds']
    del signer.namespaces['ds']
    signer.namespaces[None] = ds
    signed_root = signer.sign(xml_root,
                              key=cert_data['key_str'],
                              cert=cert_data['cert_str'],
                              reference_uri=reference_uri)
    return etree.ElementTree(signed_root)
Beispiel #26
0
    def assina_xml(self, xml_element, reference):
        cert, key = extract_cert_and_key_from_pfx(self.arquivo, self.senha)

        for element in xml_element.iter("*"):
            if element.text is not None and not element.text.strip():
                element.text = None

        signer = XMLSigner(
            method=signxml.methods.enveloped,
            signature_algorithm="rsa-sha1",
            digest_algorithm='sha1',
            c14n_algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')

        signed_root = signer.sign(xml_element,
                                  key=key,
                                  cert=cert,
                                  reference_uri=('#%s' % reference))
        if len(signed_root) > 3:
            signed_root[2].append(signed_root[3])
        return etree.tostring(signed_root)
Beispiel #27
0
 def test_elementtree_compat(self):
     data = stdlibElementTree.parse(self.example_xml_files[0]).getroot()
     signer = XMLSigner()
     signed = signer.sign(data, key=self.keys["rsa"])
Beispiel #28
0
 def test_elementtree_compat(self):
     data = stdlibElementTree.parse(self.example_xml_files[0]).getroot()
     signer = XMLSigner()
     signed = signer.sign(data, key=self.keys["rsa"])
Beispiel #29
0
    def test_basic_signxml_statements(self):
        with self.assertRaisesRegexp(InvalidInput, "Unknown signature method"):
            signer = XMLSigner(method=None)

        with self.assertRaisesRegexp(InvalidInput, "must be an XML element"):
            XMLSigner().sign("x")

        digest_algs = {"sha1", "sha224", "sha256", "sha384", "sha512"}
        sig_algs = {"hmac", "dsa", "rsa", "ecdsa"}
        hash_algs = {"sha1", "sha256"}
        c14n_algs = {"http://www.w3.org/2001/10/xml-exc-c14n#",
                     "http://www.w3.org/2001/10/xml-exc-c14n#WithComments",
                     XMLSignatureProcessor.default_c14n_algorithm}

        all_methods = itertools.product(digest_algs, sig_algs, hash_algs, methods, c14n_algs)
        for digest_alg, sig_alg, hash_alg, method, c14n_alg in all_methods:
            data = [etree.parse(f).getroot() for f in self.example_xml_files]
            # FIXME: data.extend(stdlibElementTree.parse(f).getroot() for f in (self.example_xml_files)
            data.append(stdlibElementTree.parse(self.example_xml_files[0]).getroot())
            data.append("x y \n z t\n я\n")
            for d in data:
                if isinstance(d, str) and method != methods.enveloping:
                    continue
                print(digest_alg, sig_alg, hash_alg, c14n_alg, method, type(d))
                reset_tree(d, method)
                signer = XMLSigner(method=method,
                                   signature_algorithm="-".join([sig_alg, hash_alg]),
                                   digest_algorithm=digest_alg,
                                   c14n_algorithm=c14n_alg)
                signed = signer.sign(d,
                                     key=self.keys[sig_alg],
                                     reference_uri="URI" if method == methods.detached else None)
                # print(etree.tostring(signed))
                hmac_key = self.keys["hmac"] if sig_alg == "hmac" else None
                verify_kwargs = dict(require_x509=False, hmac_key=hmac_key, validate_schema=True)

                if method == methods.detached:
                    def resolver(uri):
                        if isinstance(d, stdlibElementTree.Element):
                            return etree.fromstring(stdlibElementTree.tostring(d))
                        else:
                            return d
                    verify_kwargs["uri_resolver"] = resolver

                signed_data = etree.tostring(signed)
                XMLVerifier().verify(signed_data, **verify_kwargs)
                XMLVerifier().verify(signed_data, parser=parser, **verify_kwargs)
                (_d, _x, _s) = XMLVerifier().verify(signed_data, id_attribute="Id", **verify_kwargs)

                if _x is not None:
                    # Ensure the signature is not part of the signed data
                    self.assertIsNone(_x.find(".//{http://www.w3.org/2000/09/xmldsig#}Signature"))
                    self.assertNotEqual(_x.tag, "{http://www.w3.org/2000/09/xmldsig#}Signature")

                # Ensure the signature was returned
                self.assertEqual(_s.tag, "{http://www.w3.org/2000/09/xmldsig#}Signature")

                if method == methods.enveloping:
                    with self.assertRaisesRegexp(InvalidInput, "Unable to resolve reference URI"):
                        XMLVerifier().verify(signed_data, id_attribute="X", **verify_kwargs)

                with self.assertRaisesRegexp(InvalidInput, "Expected a X.509 certificate based signature"):
                    XMLVerifier().verify(signed_data, hmac_key=hmac_key, uri_resolver=verify_kwargs.get("uri_resolver"))

                if method != methods.detached:
                    with self.assertRaisesRegexp(InvalidSignature, "Digest mismatch"):
                        mangled_sig = signed_data.replace(b"Austria", b"Mongolia").replace(b"x y", b"a b")
                        XMLVerifier().verify(mangled_sig, **verify_kwargs)

                with self.assertRaises(cryptography.exceptions.InvalidSignature):
                    mangled_sig = signed_data.replace(b"<ds:DigestValue>", b"<ds:DigestValue>!")
                    XMLVerifier().verify(mangled_sig, **verify_kwargs)

                with self.assertRaises(cryptography.exceptions.InvalidSignature):
                    sig_value = re.search(b"<ds:SignatureValue>(.+?)</ds:SignatureValue>", signed_data).group(1)
                    mangled_sig = re.sub(
                        b"<ds:SignatureValue>(.+?)</ds:SignatureValue>",
                        b"<ds:SignatureValue>" + b64encode(b64decode(sig_value)[::-1]) + b"</ds:SignatureValue>",
                        signed_data
                    )
                    XMLVerifier().verify(mangled_sig, **verify_kwargs)

                with self.assertRaises(etree.XMLSyntaxError):
                    XMLVerifier().verify("", hmac_key=hmac_key, require_x509=False)

                if sig_alg == "hmac":
                    with self.assertRaisesRegexp(InvalidSignature, "Signature mismatch"):
                        verify_kwargs["hmac_key"] = b"SECRET"
                        XMLVerifier().verify(signed_data, **verify_kwargs)
Beispiel #30
0
    def generate_saml(self, post_data):
        '''Update all of the relevant fields in saml_template.xml with the form data'''
        parser = ET.XMLParser(remove_blank_text=True)
        now = datetime.datetime.utcnow()
        issue_instant = now.strftime('%Y-%m-%dT%H:%M:%S.%fZ')[:-4] + 'Z'
        tree = ET.parse('saml_post/static/saml_post/saml_template.xml', parser=parser)
        # if this ever breaks it might be easier to troubleshoot with the template as a string
        ## saml_template = '<samlp:Response ID="_4ba3eca7-7f9f-4a77-9006-4e1fae8bee1b" Version="2.0" IssueInstant="2020-01-10T13:09:52.256Z" Destination="https://secure-enroll.com/sso/saml" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"><Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">https://sts.windows.net/23e14383-b783-4c99-bf4f-5049cd014ec6/</Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="placeholder" /><samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status><Assertion ID="_fdaa4a4b-ffad-4d60-bb95-86bb6c312000" IssueInstant="2020-01-10T13:09:52.256Z" Version="2.0" xmlns="urn:oasis:names:tc:SAML:2.0:assertion"><Issuer>https://sts.windows.net/23e14383-b783-4c99-bf4f-5049cd014ec6/</Issuer><Subject><NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">0VFMNdkRdozsmj7W8PDmoCgje2almNSSeKSz1N2v1FM</NameID><SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><SubjectConfirmationData NotOnOrAfter="2020-01-10T14:09:51.974Z" Recipient="https://secure-enroll.com/sso/saml"/></SubjectConfirmation></Subject><Conditions NotBefore="2020-01-10T13:04:51.974Z" NotOnOrAfter="2020-01-10T14:09:51.974Z"><AudienceRestriction><Audience>https://secure-enroll.com/sso/saml</Audience></AudienceRestriction></Conditions><AttributeStatement><Attribute Name="http://schemas.microsoft.com/identity/claims/tenantid"><AttributeValue>23e14383-b783-4c99-bf4f-5049cd014ec6</AttributeValue></Attribute></AttributeStatement></Assertion></samlp:Response>'
        ## root = ET.fromstring(saml_template)
        root = tree.getroot()
        # namespaces are ew but you can use .find('saml:Assertion', saml) where the second parameter (saml) is this dictionary instead of indexing into each element
        saml = {'saml': 'urn:oasis:names:tc:SAML:2.0:assertion',
                'signature': 'http://www.w3.org/2000/09/xmldsig#}Signature'}
        root.find('saml:Issuer', saml).text = post_data['issuer_id']
        root.attrib['Destination'] = post_data['acs_endpoint']
        root.attrib['IssueInstant'] = issue_instant
        root.find('saml:Assertion', saml).attrib['IssueInstant'] = issue_instant
        root.find('saml:Assertion', saml).find('saml:Subject', saml).find('saml:NameID', saml).text = post_data[
            'saml_subject']
        root.find('saml:Assertion', saml).find('saml:Subject', saml).find('saml:SubjectConfirmation', saml).find(
            'saml:SubjectConfirmationData', saml).attrib['NotOnOrAfter'] = (now + timedelta(hours=1)).strftime(
            '%Y-%m-%dT%H:%M:%S.%fZ')[:-4] + 'Z'
        root.find('saml:Assertion', saml).find('saml:Subject', saml).find('saml:SubjectConfirmation', saml).find(
            'saml:SubjectConfirmationData', saml).attrib['Recipient'] = post_data['audience_id']
        root.find('saml:Assertion', saml).find('saml:Conditions', saml).attrib['NotBefore'] = (now - timedelta(
            minutes=10)).strftime('%Y-%m-%dT%H:%M:%S.%fZ')[:-4] + 'Z'
        root.find('saml:Assertion', saml).find('saml:Conditions', saml).attrib['NotOnOrAfter'] = (now + timedelta(
            hours=1)).strftime('%Y-%m-%dT%H:%M:%S.%fZ')[:-4] + 'Z'
        root.find('saml:Assertion', saml).find('saml:Conditions', saml).find('saml:AudienceRestriction', saml).find(
            'saml:Audience', saml).text = post_data['audience_id']
        #root.find('saml:Assertion', saml).find('saml:AttributeStatement', saml).find('saml:Attribute', saml).attrib[
        #    'Name'] = self.fields['attributes'][0]['attribute_name']  #post_data['attribute_name']
        #root.find('saml:Assertion', saml).find('saml:AttributeStatement', saml).find('saml:Attribute', saml).find(
        #    'saml:AttributeValue', saml).text = self.fields['attributes'][0]['attribute_value'] # post_data['attribute_value']
        root.find('saml:Assertion', saml).find('saml:Issuer', saml).text = post_data['issuer_id']

        attribute_element_copy = deepcopy(root.find('saml:Assertion', saml).find('saml:AttributeStatement', saml).find(
            'saml:Attribute', saml))
        element_to_remove = root.find('saml:Assertion', saml).find('saml:AttributeStatement', saml).find('saml:Attribute', saml)
        root.find('saml:Assertion', saml).find('saml:AttributeStatement', saml).remove(element_to_remove)
        for attribute in self.fields['attributes']:
            new_attribute = deepcopy(attribute_element_copy)
            new_attribute.attrib['Name'] = attribute['attribute_name']
            new_attribute.find('saml:AttributeValue', saml).text = attribute['attribute_value']
            root.find('saml:Assertion', saml).find('saml:AttributeStatement', saml).append(new_attribute)


        #test
        #a = deepcopy(root.find('saml:Assertion', saml).find('saml:AttributeStatement', saml).find('saml:Attribute', saml))
        #root.find('saml:Assertion', saml).find('saml:AttributeStatement', saml).append(a)

        # sign the newly created xml
        reference_uri = '_4ba3eca7-7f9f-4a77-9006-4e1fae8bee1b'
        with open("saml_post/static/saml_post/publickey.cer") as f:
            cert = f.read()
        with open("saml_post/static/saml_post/private.key") as f:
            key = f.read()
        '''
        From the SAML Oasis docs:
        Signatures in SAML messages SHOULD NOT contain transforms other than the enveloped signature transform 
        (with the identifier http://www.w3.org/2000/09/xmldsig#enveloped-signature) 
        or the exclusive canonicalization transforms 
        (with the identifier http://www.w3.org/2001/10/xml-exc-c14n# 
        or http://www.w3.org/2001/10/xml-exc-c14n#WithComments).
        The default behavior for XMLSigner uses some other transforms so we need to specify the c14n_algorithm.
        '''
        signer = XMLSigner(c14n_algorithm='http://www.w3.org/2001/10/xml-exc-c14n#', signature_algorithm="rsa-sha256",
                           digest_algorithm="sha256", method=signxml.methods.enveloped)
        signed_root = signer.sign(root, key=key, cert=cert, reference_uri=reference_uri)
        return ET.tostring(signed_root, encoding='utf-8')
Beispiel #31
0
    def test_reference_uris_and_custom_key_info(self):
        with open(os.path.join(os.path.dirname(__file__), "example.pem"),
                  "rb") as fh:
            crt = fh.read()
        with open(os.path.join(os.path.dirname(__file__), "example.key"),
                  "rb") as fh:
            key = fh.read()

        # Both ID and Id formats. XPath 1 doesn't have case insensitive attribute search
        for d in [
                '''<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
                                     xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="responseId">
                      <saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                                      xmlns:xs="http://www.w3.org/2001/XMLSchema" ID="assertionId">
                       <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="placeholder" />
                      </saml:Assertion>
                     </samlp:Response>''',
                '''<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
                                     xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Id="responseId">
                      <saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                                      xmlns:xs="http://www.w3.org/2001/XMLSchema" Id="assertionId">
                       <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="placeholder" />
                      </saml:Assertion>
                      <saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                                      xmlns:xs="http://www.w3.org/2001/XMLSchema" Id="assertion2">
                      </saml:Assertion>
                     </samlp:Response>'''
        ]:
            data = etree.fromstring(d)
            reference_uri = ["assertionId", "assertion2"
                             ] if "assertion2" in d else "assertionId"
            signed_root = XMLSigner().sign(data,
                                           reference_uri=reference_uri,
                                           key=key,
                                           cert=crt)
            signed_data_root = XMLVerifier().verify(
                etree.tostring(signed_root),
                x509_cert=crt,
                expect_references=True)[1]
            ref = signed_root.xpath(
                '/samlp:Response/saml:Assertion/ds:Signature/ds:SignedInfo/ds:Reference',
                namespaces={
                    "ds": "http://www.w3.org/2000/09/xmldsig#",
                    "saml": "urn:oasis:names:tc:SAML:2.0:assertion",
                    "samlp": "urn:oasis:names:tc:SAML:2.0:protocol"
                })
            self.assertEqual("assertionId", ref[0].attrib['URI'][1:])

            self.assertEqual(
                "{urn:oasis:names:tc:SAML:2.0:assertion}Assertion",
                signed_data_root.tag)

            # Also test with detached signing
            ref_xpath = "/ds:Signature/ds:SignedInfo/ds:Reference"
            signer = XMLSigner(method=methods.detached)
            s = signer.sign(data,
                            reference_uri=reference_uri,
                            key=key,
                            cert=crt)
            self.assertTrue(
                s.xpath(ref_xpath + "/ds:Transforms", namespaces=namespaces))
            self.assertTrue(
                s.xpath(ref_xpath + "/ds:DigestMethod", namespaces=namespaces))
            self.assertTrue(
                s.xpath(ref_xpath + "/ds:DigestValue", namespaces=namespaces))

            self.assertTrue(
                s.xpath("/ds:Signature/ds:KeyInfo/ds:X509Data",
                        namespaces=namespaces))
            self.assertFalse(
                s.xpath("/ds:Signature/ds:KeyInfo/ds:KeyValue",
                        namespaces=namespaces))
            s2 = signer.sign(data,
                             reference_uri=reference_uri,
                             key=key,
                             cert=crt,
                             always_add_key_value=True)
            self.assertTrue(
                s2.xpath("/ds:Signature/ds:KeyInfo/ds:X509Data",
                         namespaces=namespaces))
            self.assertTrue(
                s2.xpath("/ds:Signature/ds:KeyInfo/ds:KeyValue",
                         namespaces=namespaces))

            # Test setting custom key info
            wsse_ns = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
            with open(
                    os.path.join(os.path.dirname(__file__),
                                 "wsse_keyinfo.xml")) as fh:
                custom_key_info = etree.fromstring(fh.read())
            s3 = signer.sign(data,
                             reference_uri=reference_uri,
                             key=key,
                             cert=crt,
                             key_info=custom_key_info)
            self.assertTrue(
                s3.xpath(
                    "/ds:Signature/ds:KeyInfo/wsse:SecurityTokenReference",
                    namespaces=dict(namespaces, wsse=wsse_ns)))

            # Test setting both X509Data and KeyInfo
            s4 = XMLSigner().sign(data,
                                  reference_uri=reference_uri,
                                  key=key,
                                  cert=crt,
                                  always_add_key_value=True)
            with self.assertRaisesRegexp(InvalidInput,
                                         "Both X509Data and KeyValue found"):
                XMLVerifier().verify(s4, x509_cert=crt)
            expect_refs = etree.tostring(s4).decode().count("<ds:Reference")
            XMLVerifier().verify(s4,
                                 x509_cert=crt,
                                 ignore_ambiguous_key_info=True,
                                 expect_references=expect_refs)
Beispiel #32
0
class Assinatura:
    def __init__(self, certificado, chave, namespace):

        self.cert = certificado
        self.key = chave
        self.NAMESPACE = namespace

        self._assinador = XMLSigner(
            method=methods.detached,
            signature_algorithm="rsa-sha1",
            digest_algorithm='sha1',
            c14n_algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')

    def assinar_lote_rps(self, xml_lote_rps):

        root = etree.fromstring(xml_lote_rps.encode())
        lista_rps = root.findall('./{0}LoteRps/{0}ListaRps/*'.format(
            self.NAMESPACE))

        for rps in lista_rps:
            infrps = rps.find('{0}InfRps'.format(self.NAMESPACE))
            reference_uri = infrps.attrib.get('id')
            assinatura = self._assinatura_xml(rps, reference_uri)

            rps.append(assinatura)

        lote_rps = root.find('{0}LoteRps'.format(self.NAMESPACE))
        reference_uri = lote_rps.attrib.get('id')
        assinatura = self._assinatura_xml(root, reference_uri)

        root.append(assinatura)

        xml_lote_rps_assinado = etree.tostring(root, encoding='utf-8').decode()

        xml_lote_rps_assinado = xml_lote_rps_assinado.replace('ds:',
                                                              '').replace(
                                                                  ':ds', '')

        return xml_lote_rps_assinado

    def assinar_cancelamento_nfse(self, xml_cancelamento_nfse):

        root = etree.fromstring(xml_cancelamento_nfse.encode())
        pedido = root.find('{0}Pedido'.format(self.NAMESPACE))
        inf_pedido = pedido.find('{0}InfPedidoCancelamento'.format(
            self.NAMESPACE))
        reference_uri = inf_pedido.attrib.get('id')

        assinatura = self._assinatura_xml(pedido, reference_uri)

        pedido.append(assinatura)

        xml_pedido_cancelamento_assinado = etree.tostring(
            root, encoding='utf-8').decode()

        xml_pedido_cancelamento_assinado = xml_pedido_cancelamento_assinado.replace(
            'ds:', '').replace(':ds', '')

        return xml_pedido_cancelamento_assinado

    def _assinatura_xml(self, data, reference_uri):

        assinatura = self._assinador.sign(
            data=data,
            key=self.key,
            cert=self.cert,
            reference_uri='#{}'.format(reference_uri))

        return assinatura
Beispiel #33
0
    def test_basic_signxml_statements(self):
        with self.assertRaisesRegexp(InvalidInput, "Unknown signature method"):
            signer = XMLSigner(method=None)

        with self.assertRaisesRegexp(InvalidInput, "must be an XML element"):
            XMLSigner().sign("x")

        digest_algs = {"sha1", "sha224", "sha256", "sha384", "sha512"}
        sig_algs = {"hmac", "dsa", "rsa", "ecdsa"}
        hash_algs = {"sha1", "sha256"}
        c14n_algs = {
            "http://www.w3.org/2001/10/xml-exc-c14n#",
            "http://www.w3.org/2001/10/xml-exc-c14n#WithComments",
            XMLSignatureProcessor.default_c14n_algorithm
        }

        all_methods = itertools.product(digest_algs, sig_algs, hash_algs,
                                        methods, c14n_algs)
        for digest_alg, sig_alg, hash_alg, method, c14n_alg in all_methods:
            data = [etree.parse(f).getroot() for f in self.example_xml_files]
            # FIXME: data.extend(stdlibElementTree.parse(f).getroot() for f in (self.example_xml_files)
            data.append(
                stdlibElementTree.parse(self.example_xml_files[0]).getroot())
            data.append("x y \n z t\n я\n")
            for d in data:
                if isinstance(d, str) and method != methods.enveloping:
                    continue
                print(digest_alg, sig_alg, hash_alg, c14n_alg, method, type(d))
                reset_tree(d, method)
                signer = XMLSigner(method=method,
                                   signature_algorithm="-".join(
                                       [sig_alg, hash_alg]),
                                   digest_algorithm=digest_alg,
                                   c14n_algorithm=c14n_alg)
                signed = signer.sign(d,
                                     key=self.keys[sig_alg],
                                     reference_uri="URI"
                                     if method == methods.detached else None)
                # print(etree.tostring(signed))
                hmac_key = self.keys["hmac"] if sig_alg == "hmac" else None
                verify_kwargs = dict(require_x509=False,
                                     hmac_key=hmac_key,
                                     validate_schema=True)

                if method == methods.detached:

                    def resolver(uri):
                        if isinstance(d, stdlibElementTree.Element):
                            return etree.fromstring(
                                stdlibElementTree.tostring(d))
                        else:
                            return d

                    verify_kwargs["uri_resolver"] = resolver

                signed_data = etree.tostring(signed)
                XMLVerifier().verify(signed_data, **verify_kwargs)
                XMLVerifier().verify(signed_data,
                                     parser=parser,
                                     **verify_kwargs)
                (_d, _x, _s) = XMLVerifier().verify(signed_data,
                                                    id_attribute="Id",
                                                    **verify_kwargs)

                if _x is not None:
                    # Ensure the signature is not part of the signed data
                    self.assertIsNone(
                        _x.find(
                            ".//{http://www.w3.org/2000/09/xmldsig#}Signature")
                    )
                    self.assertNotEqual(
                        _x.tag,
                        "{http://www.w3.org/2000/09/xmldsig#}Signature")

                # Ensure the signature was returned
                self.assertEqual(
                    _s.tag, "{http://www.w3.org/2000/09/xmldsig#}Signature")

                if method == methods.enveloping:
                    with self.assertRaisesRegexp(
                            InvalidInput, "Unable to resolve reference URI"):
                        XMLVerifier().verify(signed_data,
                                             id_attribute="X",
                                             **verify_kwargs)

                with self.assertRaisesRegexp(
                        InvalidInput,
                        "Expected a X.509 certificate based signature"):
                    XMLVerifier().verify(
                        signed_data,
                        hmac_key=hmac_key,
                        uri_resolver=verify_kwargs.get("uri_resolver"))

                if method != methods.detached:
                    with self.assertRaisesRegexp(InvalidSignature,
                                                 "Digest mismatch"):
                        mangled_sig = signed_data.replace(
                            b"Austria", b"Mongolia").replace(b"x y", b"a b")
                        XMLVerifier().verify(mangled_sig, **verify_kwargs)

                with self.assertRaises(
                        cryptography.exceptions.InvalidSignature):
                    mangled_sig = signed_data.replace(b"<ds:DigestValue>",
                                                      b"<ds:DigestValue>!")
                    XMLVerifier().verify(mangled_sig, **verify_kwargs)

                with self.assertRaises(
                        cryptography.exceptions.InvalidSignature):
                    sig_value = re.search(
                        b"<ds:SignatureValue>(.+?)</ds:SignatureValue>",
                        signed_data).group(1)
                    mangled_sig = re.sub(
                        b"<ds:SignatureValue>(.+?)</ds:SignatureValue>",
                        b"<ds:SignatureValue>" +
                        b64encode(b64decode(sig_value)[::-1]) +
                        b"</ds:SignatureValue>", signed_data)
                    XMLVerifier().verify(mangled_sig, **verify_kwargs)

                with self.assertRaises(etree.XMLSyntaxError):
                    XMLVerifier().verify("",
                                         hmac_key=hmac_key,
                                         require_x509=False)

                if sig_alg == "hmac":
                    with self.assertRaisesRegexp(InvalidSignature,
                                                 "Signature mismatch"):
                        verify_kwargs["hmac_key"] = b"SECRET"
                        XMLVerifier().verify(signed_data, **verify_kwargs)
Beispiel #34
0
def get_feed():

    user_name_token = username_password()
    signature = binary_signature_timestamp()

    client = Client('tweaked_xml/wsdl.xml', wsse=[user_name_token, signature], plugins=[WsAddressingPlugin()])
    # client.set_ns_prefix('', 'http://information.gateway.ofsted.gov.uk/ispp')
    # client.set_ns_prefix('s', 'http://www.w3.org/2003/05/soap-envelope')
    client.set_ns_prefix('a', 'http://www.w3.org/2005/08/addressing')
    client.set_ns_prefix('u', 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd')
    parameters = {
        'LocalAuthorityCode': 825
      }
    
    # Add a "ReplyTo/Address"
    header = xsd.Element(
        '{http://www.w3.org/2005/08/addressing}ReplyTo',
        xsd.ComplexType([
            xsd.Element(
                '{http://www.w3.org/2005/08/addressing}Address',
                xsd.String()),
        ])
    )
    header_value = header(Address='http://www.w3.org/2005/08/addressing/anonymous')
    
    # Request document
    envelope = client.create_message(client.service, 'GetLocalAuthorityChildcareRegister', localAuthorityRequest=parameters, _soapheaders=[header_value])
    
    # # Update a few tricky values

    header_tag = envelope.find('{http://www.w3.org/2003/05/soap-envelope}Header')
    security_tag = header_tag.find('{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security')

    # Mark the Timestamp tag for signing:
    timestamp_tag = security_tag.find('{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp')
    timestamp_tag.attrib['{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Id']="_0"

    # De-duplicate and tweak the To tag for signing:
    for child_tag in header_tag:
        if child_tag.tag == '{http://www.w3.org/2005/08/addressing}To':
            to_tag = child_tag
            insert_index = header_tag.index(child_tag)
            header_tag.remove(child_tag)
    header_tag.insert(insert_index, to_tag)
    to_tag.attrib['{http://www.w3.org/2003/05/soap-envelope}mustUnderstand']="1"
    to_tag.attrib['{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Id']="_1"

    # Remove the standard signature so we can replace it with what's needed for this specific implementation:
    signature_tag = security_tag.find('{http://www.w3.org/2000/09/xmldsig#}Signature')
    signature_index = security_tag.index(signature_tag)
    binary_security_token_tag = security_tag.find('{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}BinarySecurityToken')
    security_tag.remove(signature_tag)
    security_tag.remove(binary_security_token_tag)

    # Re-sign in the way that's expected by this service:
    signer = XMLSigner(
        method=methods.detached,
        digest_algorithm='sha1',
        signature_algorithm='rsa-sha1',
        c14n_algorithm='http://www.w3.org/2001/10/xml-exc-c14n#'
        )
    private = get_secret('private_key')
    public = get_secret('certificate')
    signature = signer.sign(envelope, key=private, cert=public, reference_uri=['_0', '_1'])
    security_tag.insert(signature_index, signature)

    # Add the signature to the document:

    xmlstr = str(etree.tostring(envelope, encoding='unicode', pretty_print=True))
    print(f" *** Signed:\n {xmlstr}")

    for tag in security_tag:
        print(tag.tag)
        for subtag in tag:
            print(f' - {subtag.tag}')

    # header = envelope.find('{http://www.w3.org/2003/05/soap-envelope}Header')
    # security = header.find('{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security')
    # signature = security.find('{http://www.w3.org/2000/09/xmldsig#}Signature')
    # signature_value = signature.find('{http://www.w3.org/2000/09/xmldsig#}SignatureValue')
    # binary_security_token = security.find('{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}BinarySecurityToken')

    # # Reformat base-64 values without line-wrapping 
    # # # (possible the server isn't reading them correctly otherwise)
    # nowrapping(signature_value)
    # nowrapping(binary_security_token)

    # # Sprinkle in some 'mustUnderstand' just in case
    # mustunderstanders = [
    #         '{http://www.w3.org/2005/08/addressing}Action', 
    #         '{http://www.w3.org/2005/08/addressing}To', 
    #         '{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security'
    #         ]
    # for child in header:
    #     if child.tag in mustunderstanders:
    #         print(f"Adding mustUnderstand to {child.tag}")
    #         child.attrib['{http://www.w3.org/2003/05/soap-envelope}mustUnderstand']="1"

    # # Temp: c14n test
    # print("...")
    # for child in header:
    #     if child.tag == '{http://www.w3.org/2005/08/addressing}Action':
    #         print(f"C14nning: {child.tag}")
    # print("...")

    
    # # Pop in a couple of missing ids
    # signer = XMLSigner(
    #     method=methods.detached,
    #     digest_algorithm='sha1',
    #     signature_algorithm='rsa-sha1',
    #     c14n_algorithm='http://www.w3.org/2001/10/xml-exc-c14n#'
    #     )
    # ref = 0
    # for child in header:
    #     if child.tag == '{http://www.w3.org/2005/08/addressing}To':
    #         child.attrib['{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Id'] = "_1"
    #         private = get_secret('private_key')
    #         public = get_secret('certificate')
    #         signed_root = signer.sign(child, key=private, cert=public, key_info='ouagadougou', reference_uri=f'_{ref}')
    #         ref = ref + 1
    #         #signed_root = XMLSigner().sign(child, key=private, cert=public)
    # xmlstr = str(etree.tostring(signed_root, encoding='unicode', pretty_print=True))
    # print(f" *** Signed:\n {xmlstr}")
    # for child in security:
    #     if child.tag == '{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}UsernameToken':
    #         child.attrib['{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Id'] = "_2"
    
    # # Delete duplicated elements
    # duplicates = ['{http://www.w3.org/2005/08/addressing}Action', '{http://www.w3.org/2005/08/addressing}To', '{http://www.w3.org/2005/08/addressing}MessageID']
    # deduped = {}
    # insert_index = 0
    # for child in header:
    #     if child.tag in duplicates:
    #         deduped[child.tag] = child
    #         header.remove(child)
    #     if child.tag == '{http://www.w3.org/2005/08/addressing}ReplyTo':
    #         insert_index = header.index(child)

    # # Re-insert the de-duped elements
    # for child in deduped.values():
    #     insert_index = insert_index + 1
    #     header.insert(insert_index, child)

    # for child in header:
    #     print(f' - {child.tag[child.tag.rindex("}")+1:]}  {child.tag}  -->  {child.attrib}')
    #     if child.tag=='{http://www.w3.org/2005/08/addressing}ReplyTo':
    #         print(header.index(child))
    
    # xmlstr =  minidom.parseString(ET.tostring(node)).toprettyxml(indent="   ")
    #xmlstr = str(etree.tostring(signed, encoding='unicode', pretty_print=True))
    # print(type(xmlstr))

    # xmlstr=tweak(xmlstr)

    ##print(xmlstr)
    # if os.path.isdir('/output'):
    #     with open('/output/actual1.xml', 'w+') as f:
    #         f.write(xmlstr)
    #         print("Saved generated XML message.")
    if os.path.isdir('../secrets/compare'):
        with open('../secrets/compare/actual1.xml', 'w+') as f:
            f.write(xmlstr)
            print("Saved generated XML message..............................")

    response = call_proxy(envelope)

    if response.status_code != 200:
        print(f"{response.status_code}: {response.text}")

    #return minidom.parseString(response.text)
    #ET.tostring(feed, encoding='unicode').toprettyxml(indent="   ")

    #return Response(f"{response.status_code} -- {response.text}"), 200
    #return "Fin." 
    return Response(response.text, mimetype='text/xml'), response.status_code