o
    gQ2                     @   s  d Z ddlmZ ddlmZ ddlmZ ddlmZ ddl	m
Z
 ddlmZmZ zddlZW n ey9   dZY nw d	Zd
d Zdd Zdd ZG dd dZG dd deZG dd deZdd Z			d&ddZdd Zdd Zdd Zd d! Zd"d# Zd'd$d%ZdS )(av  Functions for WS-Security (WSSE) signature creation and verification.

Heavily based on test examples in https://github.com/mehcode/python-xmlsec as
well as the xmlsec documentation at https://www.aleksey.com/xmlsec/.

Reading the xmldsig, xmlenc, and ws-security standards documents, though
admittedly painful, will likely assist in understanding the code in this
module.

    )etree)QName)ns)SignatureVerificationFailed)detect_soap_env)	ensure_idget_security_headerNz)http://schemas.xmlsoap.org/soap/envelope/c                 C   s6   t | d}| W  d    S 1 sw   Y  d S )Nrb)openread)f_namef r   L/home/ubuntu/webapp/venv/lib/python3.10/site-packages/zeep/wsse/signature.py
_read_file   s   $r   c                 C   s(   t j| t jj|}||t jj |S N)xmlsecKeyfrom_memory	KeyFormatPEMload_cert_from_memory)key_data	cert_datapasswordkeyr   r   r   _make_sign_key#   s   r   c                 C   s   t j| t jjd }|S r   )r   r   r   r   CERT_PEM)r   r   r   r   r   _make_verify_key)   s   r   c                   @   s0   e Zd ZdZ			d	ddZdd Zdd ZdS )
MemorySignaturez@Sign given SOAP envelope with WSSE sig using given key and cert.Nc                 C   s(   t   || _|| _|| _|| _|| _d S r   )check_xmlsec_importr   r   r   digest_methodsignature_method)selfr   r   r   r"   r!   r   r   r   __init__1   s   
zMemorySignature.__init__c                 C   ,   t | j| j| j}t||| j| j ||fS r   )r   r   r   r   _sign_envelope_with_keyr"   r!   r#   envelopeheadersr   r   r   r   applyA   
   zMemorySignature.applyc                 C   s   t | j}t|| |S r   )r   r   _verify_envelope_with_key)r#   r(   r   r   r   r   verifyH   s   

zMemorySignature.verifyNNN)__name__
__module____qualname____doc__r$   r*   r-   r   r   r   r   r   .   s    
r   c                       s(   e Zd ZdZ			d fdd	Z  ZS )	SignaturezJSign given SOAP envelope with WSSE sig using given key file and cert file.Nc                    s    t  t|t|||| d S r   )superr$   r   )r#   key_filecertfiler   r"   r!   	__class__r   r   r$   Q   s   zSignature.__init__r.   )r/   r0   r1   r2   r$   __classcell__r   r   r7   r   r3   N   s    r3   c                   @   s   e Zd ZdZdd ZdS )BinarySignaturezSign given SOAP envelope with WSSE sig using given key file and cert file.

    Place the key information into BinarySecurityElement.c                 C   r%   r   )r   r   r   r   _sign_envelope_with_key_binaryr"   r!   r'   r   r   r   r*   g   r+   zBinarySignature.applyN)r/   r0   r1   r2   r*   r   r   r   r   r:   b   s    r:   c                   C   s   t d u rtdd S )NzThe xmlsec module is required for wsse.Signature()
You can install xmlsec with: pip install xmlsec
or install zeep via: pip install zeep[xmlsec]
)r   ImportErrorr   r   r   r   r    o   s
   r    c                 C   s"   t t|t||}t| |||S )a  Sign given SOAP envelope with WSSE sig using given key and cert.

    Sign the wsu:Timestamp node in the wsse:Security header and the soap:Body;
    both must be present.

    Add a ds:Signature node in the wsse:Security header containing the
    signature.

    Use EXCL-C14N transforms to normalize the signed XML (so that irrelevant
    whitespace or attribute ordering changes don't invalidate the
    signature). Use SHA1 signatures.

    Expects to sign an incoming document something like this (xmlns attributes
    omitted for readability):

    <soap:Envelope>
      <soap:Header>
        <wsse:Security mustUnderstand="true">
          <wsu:Timestamp>
            <wsu:Created>2015-06-25T21:53:25.246276+00:00</wsu:Created>
            <wsu:Expires>2015-06-25T21:58:25.246276+00:00</wsu:Expires>
          </wsu:Timestamp>
        </wsse:Security>
      </soap:Header>
      <soap:Body>
        ...
      </soap:Body>
    </soap:Envelope>

    After signing, the sample document would look something like this (note the
    added wsu:Id attr on the soap:Body and wsu:Timestamp nodes, and the added
    ds:Signature node in the header, with ds:Reference nodes with URI attribute
    referencing the wsu:Id of the signed nodes):

    <soap:Envelope>
      <soap:Header>
        <wsse:Security mustUnderstand="true">
          <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
            <SignedInfo>
              <CanonicalizationMethod
                  Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
              <SignatureMethod
                  Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
              <Reference URI="#id-d0f9fd77-f193-471f-8bab-ba9c5afa3e76">
                <Transforms>
                  <Transform
                      Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                </Transforms>
                <DigestMethod
                    Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                <DigestValue>nnjjqTKxwl1hT/2RUsBuszgjTbI=</DigestValue>
              </Reference>
              <Reference URI="#id-7c425ac1-534a-4478-b5fe-6cae0690f08d">
                <Transforms>
                  <Transform
                      Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                </Transforms>
                <DigestMethod
                    Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                <DigestValue>qAATZaSqAr9fta9ApbGrFWDuCCQ=</DigestValue>
              </Reference>
            </SignedInfo>
            <SignatureValue>Hz8jtQb...bOdT6ZdTQ==</SignatureValue>
            <KeyInfo>
              <wsse:SecurityTokenReference>
                <X509Data>
                  <X509Certificate>MIIDnzC...Ia2qKQ==</X509Certificate>
                  <X509IssuerSerial>
                    <X509IssuerName>...</X509IssuerName>
                    <X509SerialNumber>...</X509SerialNumber>
                  </X509IssuerSerial>
                </X509Data>
              </wsse:SecurityTokenReference>
            </KeyInfo>
          </Signature>
          <wsu:Timestamp wsu:Id="id-7c425ac1-534a-4478-b5fe-6cae0690f08d">
            <wsu:Created>2015-06-25T22:00:29.821700+00:00</wsu:Created>
            <wsu:Expires>2015-06-25T22:05:29.821700+00:00</wsu:Expires>
          </wsu:Timestamp>
        </wsse:Security>
      </soap:Header>
      <soap:Body wsu:Id="id-d0f9fd77-f193-471f-8bab-ba9c5afa3e76">
        ...
      </soap:Body>
    </soap:Envelope>

    )r   r   r&   )r(   keyfiler6   r   r"   r!   r   r   r   r   sign_envelopex   s   `r>   c                 C   s   t | }tj| tjj|ptjj}tj|}tj|}tj	| tj
| t| }|d| t }	||	_t|	|| t|d| |ttjd}
|
dkr\t|	||
| |	| t|ttjd}|||fS )zPrepare envelope and sign.r   Body	TimestampNSecurityTokenReference)r   r   templatecreate	Transform	EXCL_C14NRSA_SHA1ensure_key_infoadd_x509_datax509_data_add_issuer_serialx509_data_add_certificater   insertSignatureContextr   
_sign_nodefindr   r   WSUsignr   
SubElementWSSE)r(   r   r"   r!   soap_env	signaturekey_info	x509_datasecurityctx	timestampsec_token_refr   r   r   _signature_prepare   s*   


r[   c                 C   s"   t | |||\}}}|| d S r   )r[   append)r(   r   r"   r!   _rZ   rV   r   r   r   r&     s   
r&   c           	      C   s   t | |||\}}}t|ttjdddi}tttjdddd}dt| |jd< |	ttj
d	j|_|d
| | | d S )N	Reference	ValueTypezUhttp://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3BinarySecurityTokenz^http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary)r_   EncodingType#URIX509Certificate   )r[   r   rQ   r   r   rR   Elementr   attribrN   DStextrK   	getparentremove)	r(   r   r"   r!   rW   rZ   rV   refbintokr   r   r   r;   
  s&   


	r;   c                 C   s   t t|}t| |S )zVerify WS-Security signature on given SOAP envelope with given cert.

    Expects a document like that found in the sample XML in the ``sign()``
    docstring.

    Raise SignatureVerificationFailed on failure, silent on success.

    )r   r   r,   )r(   r6   r   r   r   r   verify_envelope%  s   	
rn   c                 C   s   t | }| t|d}|d u rt |ttjd}|ttjd}t }|j	ddtjid}|D ]!}|
ddd  }	| j	d	|	 d
tjidd }
||
dtj q5||_z|| W d S  tjym   t w )NHeaderSecurityr3   zds:SignedInfo/ds:Referenceds)
namespacesrc   re   z//*[@wsu:Id='%s']wsur   Id)r   rN   r   r   r   rR   rh   r   rL   xpathgetrO   register_idr   r-   Error)r(   r   rS   headerrW   rT   rX   refsrl   referenced_id
referencedr   r   r   r,   2  s,   r,   c                 C   sL   t |}| |dtj tjj||ptjjd| d}tj	|tjj
 dS )a  Add sig for ``target`` in ``signature`` node, using ``ctx`` context.

    Doesn't actually perform the signing; ``ctx.sign(signature)`` should be
    called later to do that.

    Adds a Reference node to the signature with URI attribute pointing to the
    target node, and registers the target node's ID so XMLSec will be able to
    find the target node by ID when it signs.

    rt   rb   )uriN)r   rw   r   rO   r   rB   add_referencerD   SHA1add_transformrE   )rX   rT   targetr!   node_idrl   r   r   r   rM   R  s   rM   r.   r   )r2   lxmlr   
lxml.etreer   zeepr   zeep.exceptionsr   
zeep.utilsr   zeep.wsse.utilsr   r   r   r<   SOAP_NSr   r   r   r   r3   r:   r    r>   r[   r&   r;   rn   r,   rM   r   r   r   r   <module>   s<     
d' 