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 _get_verified_data(token, cert): secondary_cert = os.getenv('TMA_CERTIFICATE_SECONDARY', None) try: return XMLVerifier().verify(b64decode(token), x509_cert=cert).signed_xml except Exception as e: if secondary_cert: return XMLVerifier().verify(b64decode(token), x509_cert=secondary_cert).signed_xml else: raise e from None # `from None` reraise without the current context. py3.5+
def test_soap_request_with_inclusive_namespaces(self): with open(os.path.join(interop_dir, "soap", "request.xml")) as req_fh: with self.assertRaises(etree.DocumentInvalid): XMLVerifier().verify(req_fh.read(), ca_pem_file=os.path.join(interop_dir, "soap", "ca.pem"), expect_references=False) req_fh.seek(0) XMLVerifier().verify(req_fh.read(), ca_pem_file=os.path.join(interop_dir, "soap", "ca.pem"), expect_references=False, validate_schema=False)
def test_ws_security(self): wsse_dir = os.path.join(interop_dir, "ws-security", "ws.js") with open(os.path.join(wsse_dir, "examples", "server_public.pem"), "rb") as fh: crt = fh.read() data = etree.parse(os.path.join(wsse_dir, "test", "unit", "client", "files", "valid wss resp.xml")) XMLVerifier().verify(data, x509_cert=crt, validate_schema=False, expect_references=2) data = etree.parse(os.path.join(wsse_dir, "test", "unit", "client", "files", "invalid wss resp - changed content.xml")) with self.assertRaisesRegexp(InvalidDigest, "Digest mismatch for reference 0"): XMLVerifier().verify(data, x509_cert=crt, validate_schema=False, expect_references=2)
def verify(element, certificate_data): # Verify XML signature. verified_data = XMLVerifier().verify(element, x509_cert=certificate_data).signed_xml # Return verified data. return verified_data
def test_xmldsig_interop_examples(self): ca_pem_file = os.path.join(os.path.dirname(__file__), "interop", "cacert.pem").encode("utf-8") for signature_file in glob(os.path.join(os.path.dirname(__file__), "interop", "*.xml")): print("Verifying", signature_file) with open(signature_file, "rb") as fh: with self.assertRaisesRegexp(InvalidCertificate, "certificate has expired"): XMLVerifier().verify(fh.read(), ca_pem_file=ca_pem_file)
def test_xml_attacks(self): for filename in glob( os.path.join(os.path.dirname(__file__), "defusedxml-test-data", "*.xml")): with open(filename, "rb") as fh: with self.assertRaises((InvalidInput, etree.XMLSyntaxError)): XMLVerifier().verify(fh.read())
def process(): saml_response = request.form['SAMLResponse'] assertion_data = XMLVerifier().verify(base64.b64decode(saml_response), x509_cert=cert).signed_xml if assertion_data.find( '{urn:oasis:names:tc:SAML:2.0:assertion}LogoutRequest' ) is not None: response = make_response('You have been logged out') response.set_cookie('auth_session', '', expires=0) return response username = assertion_data.find('{urn:oasis:names:tc:SAML:2.0:assertion}Assertion')\ .find('{urn:oasis:names:tc:SAML:2.0:assertion}Subject')\ .find('{urn:oasis:names:tc:SAML:2.0:assertion}NameID').text key = 'secret' expiry = int(time.time()) + timeout signature = hashlib.sha256( f'{username}|{expiry}|{key}'.encode('UTF-8')).hexdigest() if 'RelayState' in request.form: return_path = request.form['RelayState'] response = redirect(return_path, 302) else: response = redirect('/', 302) response.set_cookie('auth_session', f'{username}|{expiry}|{signature}') return response
class TestGetUsername(unittest.TestCase): response_etree = etree.fromstring(test_constants.sample_response_xml) verified_signed_xml = XMLVerifier().verify( response_etree, x509_cert=test_constants.x509_cert).signed_xml def test_get_username_from_saml_doc(self): a = SAMLAuthenticator() assert 'Bluedata' == a._get_username_from_saml_etree( self.verified_signed_xml) assert 'Bluedata' == a._get_username_from_saml_etree( self.response_etree) assert 'Bluedata' == a._get_username_from_saml_doc( self.verified_signed_xml, self.response_etree) def test_get_username_no_nameid(self): tampered_assertion_etree = etree.fromstring( test_constants.tampered_assertion_no_nameid) tampered_response_etree = etree.fromstring( test_constants.tampered_response_no_nameid) a = SAMLAuthenticator() assert a._get_username_from_saml_etree( tampered_assertion_etree) is None assert a._get_username_from_saml_etree(tampered_response_etree) is None assert a._get_username_from_saml_doc(tampered_assertion_etree, tampered_response_etree) is None assert 'Bluedata' == a._get_username_from_saml_doc( tampered_assertion_etree, self.response_etree)
def test_xmldsig_interop_TR2012(self): def get_x509_cert(**kwargs): from cryptography.x509 import load_der_x509_certificate from OpenSSL.crypto import X509 with open(os.path.join(interop_dir, "TR2012", "rsa-cert.der"), "rb") as fh: return [ X509.from_cryptography( load_der_x509_certificate(fh.read(), backend=default_backend())) ] signature_files = glob( os.path.join(interop_dir, "TR2012", "signature*.xml")) for signature_file in signature_files: print("Verifying", signature_file) with open(signature_file, "rb") as fh: try: sig = fh.read() XMLVerifier().verify( sig, require_x509=False, hmac_key="testkey", validate_schema=True, cert_resolver=get_x509_cert if "x509digest" in signature_file else None) decoded_sig = sig.decode("utf-8") except Exception as e: if "keyinforeference" in signature_file: print("Unsupported test case:", type(e), e) elif "x509digest" in signature_file: assert isinstance(e, InvalidCertificate) else: raise
def verify_and_get_user(xml): try: to_xml = fromstring(xml) XMLVerifier().verify(to_xml, x509_cert=cert).signed_xml return to_xml.text except: return
def parse_signed(self, xml_tree, certificate): """ Passes ignore_ambiguous_key_info=True to ignore KeyValue and validate using X509Data only. """ return (XMLVerifier().verify( xml_tree, x509_cert=certificate, ignore_ambiguous_key_info=True).signed_xml)
def verify_sign(signed_data, public_key): to_verify = ETL.fromstring(signed_data) report = XMLVerifier().verify(data=to_verify, require_x509=True, x509_cert=public_key, ignore_ambiguous_key_info=True) return report
def verify(signed_data, cert_path): cert = import_key(cert_path) verifier = XMLVerifier() try: # noinspection PyTypeChecker result = verifier.verify(signed_data, x509_cert=cert) except InvalidSignature as exc: raise Exception('signature verification failed', exc) return result.signed_data
def test_example_multi(self): with open(os.path.join(os.path.dirname(__file__), "example.pem")) as fh: cert = fh.read() example_file = os.path.join(os.path.dirname(__file__), "example-125.xml") verify_results = XMLVerifier().verify( data=etree.parse(example_file), x509_cert=cert, expect_references=2, )
def parse_signed(self, xml_tree: XmlNode, certificate: X509) -> XmlNode: """ Replaces all parameters with only the signed parameters. You should provide an x509 certificate obtained out-of-band, usually via the SAML metadata. Otherwise the signed data will be verified with only the certificate provided in the request. This is INSECURE and more-or-less only useful for testing. """ return XMLVerifier().verify(xml_tree, x509_cert=certificate).signed_xml
def verifySigniature(signiautreString): xmlData = None try: signedXml = fromstring(signiautreString) xmlData = XMLVerifier().verify( signedXml, x509_cert=readCertificate()).signed_data.decode() PrintUserInfo(xmlData) except: print("\033[91m ***VALIDIMI DESHTOJ*** \033[0m") return
def verifyCert(self, signedRoot=signWithCert): from base64 import b64decode cert = self.extractCertContent() #assertion_data = XMLVerifier().verify(b64decode(signedRoot), x509_cert=cert) #print(assertion_data) try: ver = XMLVerifier().verify(signedRoot, x509_cert=cert) print(ver) except: print_exc()
def sign(self): _logger.debug('Firma de XML : ') cert = open(templateXML+ os.sep +'myr.cer').read() privkey = open(templateXML+ os.sep +'myr.key').read() root = etree.fromstring(self._xml.encode('ISO-8859-1'), parser=etree.XMLParser(encoding='ISO-8859-1')) _logger.debug(root) signed_root = XMLSigner(method=methods.enveloped, signature_algorithm='rsa-sha1', digest_algorithm='sha1', c14n_algorithm=u'http://www.w3.org/TR/2001/REC-xml-c14n-20010315').sign(root, key=privkey, cert=cert) self._xml = etree.tostring(signed_root,encoding='ISO-8859-1') assertion_data = XMLVerifier().verify(signed_root,x509_cert=cert).signed_xml _logger.debug(assertion_data) _logger.debug(self._xml)
def verify_x509(tree, certificate=None, ca_pem_file=None): """Verify signature in PSKC data against a trusted X.509 certificate. If a certificate is supplied it is used to validate the signature, otherwise any embedded certificate is used and validated against a certificate in ca_pem_file if it specified and otherwise the operating system CA certificates. """ from signxml import XMLVerifier return XMLVerifier().verify(tree, x509_cert=certificate, ca_pem_file=ca_pem_file).signed_xml
def validate_signature(self, raw_saml_response): cert = self.certificate try: verified = XMLVerifier().verify(raw_saml_response, x509_cert=cert, ignore_ambiguous_key_info=True) except Exception as e: # TODO - Need to handle this would-be exception properly but Im not sure what exception type this will throw print('\nFailed to Verify Signature. Exception:\n') print(e) # if the signature validation failed then we'll just return None so that the entity can try the next cert return None else: # if the signature validation worked then we'll return the verified saml return verified.signed_xml
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 for c14_transform_option in include_c14_transformation: XMLSigner(method=methods.detached, include_c14n_transform=c14_transform_option ).sign(data, reference_uri=reference_uri, key=key, cert=crt) # Test setting custom key info custom_key_info = etree.fromstring(''' <wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> <wsse:Reference ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" URI="#uuid-639b8970-7644-4f9e-9bc4-9c2e367808fc-1"/> </wsse:SecurityTokenReference>''') XMLSigner().sign(data, reference_uri=reference_uri, key=key, cert=crt, key_info=custom_key_info)
def verifiyXML(self, xml): """ verifies xml document Returns (ElementTree): verified xml if it can verify signature of message, or None if not """ root = xml rvalue = None rvalue = XMLVerifier().verify(root, ca_pem_file=self.CAs, validate_schema=False) if(rvalue.signed_xml != None): rvalue = rvalue.signed_xml else: rvalue = None return rvalue
class TestGetManyRoles(unittest.TestCase): response_etree = etree.fromstring( test_constants.sample_response_xml_with_many_roles) verified_signed_xml = XMLVerifier().verify( response_etree, x509_cert=test_constants.x509_cert).signed_xml sorted_roles = sorted(['Default', 'Role_1']) def test_get_roles_from_saml_doc(self): a = SAMLAuthenticator() a.xpath_role_location = '//saml:AttributeStatement/saml:Attribute[@Name="Roles"]/saml:AttributeValue/text()' assert self.sorted_roles == sorted( a._get_roles_from_saml_etree(self.verified_signed_xml)) assert self.sorted_roles == sorted( a._get_roles_from_saml_etree(self.response_etree)) assert self.sorted_roles == sorted( a._get_roles_from_saml_doc(self.verified_signed_xml, self.response_etree))
def extractSigData(data): """ Taken from signxml's XMLVerifier, and slightly modified to provide what's needed :param data: SOAP envelope with signature and signed info :return: signedinfo, signature tuple """ require_x509 = True x509_cert = None hmac_key = None validate_schema = True parser = None id_attribute = None ver = XMLVerifier() ver.hmac_key = hmac_key ver.require_x509 = require_x509 ver.x509_cert = x509_cert ver._parser = parser if x509_cert: XMLVerifier.require_x509 = True if id_attribute is not None: ver.id_attributes = (id_attribute, ) root = ver.get_root(data) if root.tag == signxml.ds_tag("Signature"): signature_ref = root else: signature_ref = ver._find(root, "Signature", anywhere=True) # HACK: deep copy won't keep root's namespaces signature = fromstring(etree.tostring(signature_ref), parser=parser) if validate_schema: ver.schema().assertValid(signature) signed_info = ver._find(signature, "SignedInfo") c14n_method = ver._find(signed_info, "CanonicalizationMethod") c14n_algorithm = c14n_method.get("Algorithm") signature_value = ver._find(signature, "SignatureValue") raw_signature = base64.b64decode(signature_value.text) signed_info_c14n = ver._c14n(signed_info, algorithm=c14n_algorithm) return signed_info_c14n, raw_signature
def signature(): private_key = getPrivateKey() certificate = getCertificate() data_to_sign = open("/var/www/app/test.xml").read() root = etree.fromstring(data_to_sign) signed_root = XMLSigner().sign(root, key=private_key, cert=certificate) verified_data = XMLVerifier().verify(etree.tostring(signed_root), x509_cert=certificate, expect_references=True).signed_xml txml = "/var/www/app/write.xml" f_xml = open(txml, 'wb') f_xml.write(etree.tostring(signed_root)) #verified_data.write(txml, pretty_print = True, xml_declaration = True, encoding = "utf-8" ) return "OK"
def ParseSAMLResponse(strACSUrl, strEncodedSAMLResponse): message_list = [] cert = open("static/certificates/SignCertFromIdaptive.cer").read() strDecodedSAMLResponse = b64decode(strEncodedSAMLResponse) try: XMLVerifier().verify(strDecodedSAMLResponse, x509_cert=cert) root = etree.fromstring(b64decode(strEncodedSAMLResponse)) strNameIdNode = root.xpath('//saml2p:Response/xmlns:Assertion/xmlns:Subject/xmlns:NameID', namespaces={'saml2p': 'urn:oasis:names:tc:SAML:2.0:protocol', 'xmlns': 'urn:oasis:names:tc:SAML:2.0:assertion'}) strNameId = etree.tostring(strNameIdNode[0], method="text") message_list.append(True) message_list.append(str(strNameId)[1:]) except: message_list.append(False) return message_list
def verify_signature(envelope_element, certificate_data): # # Verification of XML signature. # try: nodes = envelope_element.xpath( "//saml:Assertion", namespaces={pyseal.xml.prefix_saml: pyseal.xml.uri_saml}) if len(nodes) > 0: # deepcopy(nodes[0]) assertion_element_copy = nodes[0] verified_data = XMLVerifier().verify( assertion_element_copy, x509_cert=certificate_data).signed_xml return verified_data else: raise Exception("No saml:Assertion element found.") except: raise Exception("XML signature verification failed.")
def test_signature_properties_with_detached_method(self): doc = etree.Element('Test', attrib={'Id': 'mytest'}) sigprop = etree.Element('{http://somenamespace}MyCustomProperty') sigprop.text = 'Some Text' with open(os.path.join(os.path.dirname(__file__), "example.key"), "rb") as file: key = file.read() with open(os.path.join(os.path.dirname(__file__), "example.pem"), "rb") as file: cert = file.read() signature = XMLSigner(method=methods.detached).sign( doc, cert=cert, key=key, reference_uri="#mytest", signature_properties=sigprop) fulldoc = b'<root>' + etree.tostring(signature) + etree.tostring( doc) + b'</root>' XMLVerifier().verify(etree.fromstring(fulldoc), x509_cert=cert, expect_references=2)
def _verify_saml_signature(self, saml_metadata, decoded_saml_doc): xpath_with_namespaces = self._make_xpath_builder() find_cert = xpath_with_namespaces( '//ds:KeyInfo/ds:X509Data/ds:X509Certificate/text()') cert_value = None try: cert_value = find_cert(saml_metadata)[0] except Exception as e: self.log.warning('Could not get cert value from saml metadata') self._log_exception_error(e) return None signed_xml = None try: signed_xml = XMLVerifier().verify(decoded_saml_doc, x509_cert=cert_value).signed_xml except Exception as e: self.log.warning('Failed to verify signature on SAML Response') self._log_exception_error(e) return signed_xml