コード例 #1
0
 def test_get_text_digest_gost(self):
     self.assertEqual(crypto.get_text_digest(TEST_TEXT, "md_gost94"),
                      TEST_MD5_DIGEST)
コード例 #2
0
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)
コード例 #3
0
 def test_get_text_digest_sha1(self):
     self.assertEqual(crypto.get_text_digest(TEST_TEXT, "sha1"),
                      TEST_MD5_DIGEST)
コード例 #4
0
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