def test_get_text_digest_gost(self): self.assertEqual(crypto.get_text_digest(TEST_TEXT, "md_gost94"), TEST_MD5_DIGEST)
def verify_document(document, certificate): """ Check SOAP envelope signature according to SMEV recommendations :param document: etree.Element XML Document :type document: lxml.etree.Element :raises: ValueError, spyne_smev.crypto.InvalidSignature """ body = document.find("./{{{soapenv}}}Body".format(**_nsmap)) if body is None: raise ValueError("Incorrect soap envelope: " "`{{{soapenv}}}Body` tag not found".format(**_nsmap)) digest_value = document.find(".//{{{ds}}}DigestValue".format(**_nsmap)) if digest_value is None: raise ValueError( "Incorrect xmldsig structure: " "`{{{ds}}}DigestValue` tag not found".format(**_nsmap)) binary_security_token = document.find( ".//{{{wsse}}}BinarySecurityToken".format(**_nsmap)) if binary_security_token is None: raise ValueError( "Incorrect xmldsig structure: " "`{{{ds}}}BinarySecurityToken` tag not found".format(**_nsmap)) if not binary_security_token.text == _get_clean_cert_data(certificate): raise ValueError("Incorrect binary security token") signed_info = document.find(".//{{{ds}}}SignedInfo".format(**_nsmap)) if signed_info is None: raise ValueError("Incorrect xmldsig structure: " "`{{{ds}}}SignedInfo` tag not found".format(**_nsmap)) signature = document.find(".//{{{ds}}}SignatureValue".format(**_nsmap)) if signature is None: raise ValueError( "Incorrect xmldsig structure: " "`{{{ds}}}SignatureValue` tag not found".format(**_nsmap)) c14n = _partial(_etree.tostring, method="c14n") digest_method = document.find(".//{{{ds}}}DigestMethod".format(**_nsmap)) if digest_method is None: raise ValueError( "Incorrect xmldsig structure: " "`{{{ds}}}DigestMethod` tag not found".format(**_nsmap)) digest_name = _digest_method_names.get(digest_method.attrib["Algorithm"], None) if digest_name is None: raise ValueError( "Unsupported digest method algorithm: {0}".format(digest_name)) transform = document.find( ".//{{{ds}}}Reference/{{{ds}}}Transforms/{{{ds}}}Transform".format( **_nsmap)) if transform is None: raise ValueError("Incorrect xmldsig structure: " "`{{{ds}}}Transform` tag not found".format(**_nsmap)) c14n_method = transform.attrib["Algorithm"] exc_c14n, with_comments = _c14n_params.get(c14n_method) inc_ns = transform.find("{{{0}}}InclusiveNamespaces".format( _xmlns.exc_c14n)) if not inc_ns is None: inc_ns_prefixes = inc_ns.attrib["PrefixList"].split() inc_ns_map = dict((k, v) for k, v in document.nsmap.iteritems() if k in inc_ns_prefixes) else: inc_ns_map = None body_digest = _base64.b64encode( _crypto.get_text_digest( c14n(body, exclusive=exc_c14n, with_comments=with_comments, inclusive_ns_prefixes=inc_ns_map), digest_name)) if body_digest != digest_value.text: raise _crypto.InvalidSignature("Invalid `Body` digest!") signature_method = document.find( ".//{{{ds}}}SignatureMethod".format(**_nsmap)) if signature_method is None: raise ValueError( "Incorrect xmldsig structure: " "`{{{ds}}}SignatureMethod` tag not found".format(**_nsmap)) digest_name = _signature_method_names.get( signature_method.attrib["Algorithm"], None) if digest_name is None: raise ValueError("Unsupported signature method algorithm: {0}".format( signature_method.attrib["Algorithm"])) digest_name = _signature_method_exclusions.get(digest_name, digest_name) c14n_method_node = document.find( ".//{{{ds}}}CanonicalizationMethod".format(**_nsmap)) if c14n_method_node is None: raise ValueError( "Incorrect xmldsig structure: " "`{{{ds}}}CanonicalizationMethod` tag not found".format(**_nsmap)) c14n_method = c14n_method_node.attrib["Algorithm"] exc_c14n, with_comments = _c14n_params.get(c14n_method) inc_ns = c14n_method_node.find("{{{0}}}InclusiveNamespaces".format( _xmlns.exc_c14n)) if not inc_ns is None: inc_ns_prefixes = inc_ns.attrib["PrefixList"].split() inc_ns_map = dict((k, v) for k, v in document.nsmap.iteritems() if k in inc_ns_prefixes) else: inc_ns_map = None _crypto.verify( c14n(signed_info, exclusive=exc_c14n, with_comments=with_comments, inclusive_ns_prefixes=inc_ns_map), certificate, _base64.b64decode(signature.text), digest_name)
def test_get_text_digest_sha1(self): self.assertEqual(crypto.get_text_digest(TEST_TEXT, "sha1"), TEST_MD5_DIGEST)
def sign_document(document, cert_data, pkey_data, pkey_pass, digest_method="sha1", c14n_exclusive=True, c14n_with_comments=False): """ Soap envelope signing according to SMEV recommendations :param document: Document to sign :type document: lxml.etree.Element :param bytes pkey_data: Private key text data :param unicode pkey_pass: Private key password :param bytes cert_data: Certificate text data :return: Signed document :rtype: lxml.etree.Element """ _c14n = _partial(_etree.tostring, method="c14n", exclusive=c14n_exclusive, with_comments=c14n_with_comments) out_document = _deepcopy(document) header_node = out_document.find("./{{{soapenv}}}Header".format(**_nsmap)) if header_node is None: header_node = _etree.Element("{{{soapenv}}}Header".format(**_nsmap)) out_document.insert(0, header_node) security_node = out_document.find( "./{{{soapenv}}}Header/{{{wsse}}}Security".format(**_nsmap)) if not security_node: wsse_header_node = _construct_wsse_header(certificate=cert_data, digest_method=digest_method) header_node.append(wsse_header_node) body_node = out_document.find("./{{{soapenv}}}Body".format(**_nsmap)) body_id = "Id-%s" % str(_uuid.uuid4()) body_node.attrib["{{{0}}}Id".format(_xmlns.wsu)] = body_id reference_node = out_document.find( "./{{{soapenv}}}Header/{{{wsse}}}Security/" "{{{ds}}}Signature/{{{ds}}}SignedInfo/{{{ds}}}Reference".format( **_nsmap)) reference_node.attrib['URI'] = "#{0}".format(body_id) digest_value = _base64.b64encode( _crypto.get_text_digest(_c14n(body_node), digest_method)) digest_val_node = out_document.find( "./{{{soapenv}}}Header/{{{wsse}}}Security" "/{{{ds}}}Signature/{{{ds}}}SignedInfo/{{{ds}}}Reference" "/{{{ds}}}DigestValue".format(**_nsmap)) digest_val_node.text = digest_value sign_info_node = out_document.find( "./{{{soapenv}}}Header/{{{wsse}}}Security" "/{{{ds}}}Signature/{{{ds}}}SignedInfo".format(**_nsmap)) signature_algorithm = _crypto.get_signature_algorithm_name(cert_data) signature_algorithm = _signature_method_exclusions.get( signature_algorithm, signature_algorithm) signature_value = _base64.b64encode( _crypto.sign(_c14n(sign_info_node), pkey_data, pkey_pass, signature_algorithm)) sign_val_node = out_document.find( "./{{{soapenv}}}Header/{{{wsse}}}Security" "/{{{ds}}}Signature/{{{ds}}}SignatureValue".format(**_nsmap)) sign_val_node.text = signature_value return out_document