o
    vh`                     @   s  d dl Z d dlZd dlmZ d dlmZ d dlmZ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 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  d dl!m"Z" ddl#m$Z$ ddl%m&Z&m'Z' ddl(m)Z) g dZ*ddl+m,Z, ddl-m.Z. e/e0Z1eG dd dZ2dd Z3G dd dZ4	 d)d!e)d"e fd#d$Z5d d%d dd ej6d%fd!e)d"e d&e7fd'd(Z8dS )*    N)	dataclass)field)IterableOptional)crl)ocsp)x509)Certificate)genericmisc)pdf_name)IncrementalPdfFileWriter)get_and_apply)
PdfHandler)BasePdfFileWriter)CertificateValidatorValidationContext)ValidationPath   )extract_certificate_info   )NoDSSFoundErrorValidationInfoReadingError)EmbeddedPdfSignature)VRIDocumentSecurityStoreasync_add_validation_infocollect_validation_infoenumerate_ocsp_certs   )SerialisedCredential)PdfFileReaderc                   @   s^   e Zd ZU dZeedZeed< 	 eedZeed< 	 eedZ	eed< 	 de
jfddZd	S )
r   aA  
    VRI dictionary as defined in PAdES / ISO 32000-2.
    These dictionaries collect data that may be relevant for the validation of
    a specific signature.

    .. note::
        The data are stored as PDF indirect objects, not asn1crypto values.
        In particular, values are tied to a specific PDF handler.
    )default_factorycertsocspscrlsreturnc                 C   sb   t tdtdi}| jrt | j|td< | jr%t | j|td< t | j|td< |S )zT
        :return:
            A PDF dictionary representing this VRI entry.
        z/Type/VRIz/OCSPz/CRLz/Cert)r
   DictionaryObjectr   r$   ArrayObjectr%   r#   )selfvri r,   Y/var/www/html/hyperkenya/venv/lib/python3.10/site-packages/pyhanko/sign/validation/dss.pyas_pdf_objectB   s   zVRI.as_pdf_objectN)__name__
__module____qualname____doc__
data_fieldsetr#   __annotations__r$   r%   r
   r(   r.   r,   r,   r,   r-   r   '   s   
 
r   c                 c   sN    | d j }|dkr#| d }|d j dkr%|d j}|d E dH  dS dS dS )	zJ
    Essentially nabbed from _extract_ocsp_certs in ValidationContext
    response_status
successfulresponse_bytesresponse_typebasic_ocsp_responseresponser#   N)nativeparsed)ocsp_responsestatusr8   r;   r,   r,   r-   r   P   s   

r   c                   @   s&  e Zd ZdZ					d-dee fddZedd Zdd	 Z	d
d Z
dd Zdd ZedejfddZddddddZdd Zdeej fddZ	d.defddZededd fdd Zeddddddd!d"ed#edd fd$d%Zedddddd&dddd'	d(ed#ed)ee d*efd+d,ZdS )/r   z,
    Representation of a DSS in Python.
    Nwriterc                 C   s   |d ur|ni | _ |d ur|ni | _|d ur|ng | _|d ur!|ng | _|| _|d ur-|nt | _i }| jD ]}| j	}	|||	< q7|| _
i }
| jD ]}| j	}||
|< qK|
| _d| _d S )NF)vri_entriesr#   r$   r%   r@   r
   r(   backing_pdf_object
get_objectdata_ocsps_seen
_crls_seen	_modified)r*   r@   r#   r$   r%   rA   rB   
ocsps_seenocsp_ref
ocsp_bytes	crls_seencrl_ref	crl_bytesr,   r,   r-   __init__b   s(   	






zDocumentSecurityStore.__init__c                 C   s   | j S N)rG   r*   r,   r,   r-   modified   s   zDocumentSecurityStore.modifiedc                 C   s0   | j sd| _ | jd ur| j| j d S d S d S )NT)rG   rB   r@   update_containerrP   r,   r,   r-   _mark_modified   s   
z$DocumentSecurityStore._mark_modifiedc              	   c   sl    |D ]0}|  }z|| V  W q ty3   | jtj|d}|   |||< || |V  Y qw d S )Nstream_data)dumpKeyErrorr@   
add_objectr
   StreamObjectrS   append)r*   objsseendestobj	obj_bytesrefr,   r,   r-   _cms_objects_to_streams   s   


z-DocumentSecurityStore._cms_objects_to_streamsc                    s     fdd}fdd| D S )Nc                  3   s     D ]	} t | E d H  qd S rO   )r   )respr$   r,   r-   extra_certs   s   zADocumentSecurityStore._embed_certs_from_ocsp.<locals>.extra_certsc                    s   g | ]}  |qS r,   _embed_cert).0cert_rP   r,   r-   
<listcomp>       z@DocumentSecurityStore._embed_certs_from_ocsp.<locals>.<listcomp>r,   )r*   r$   rd   r,   )r$   r*   r-   _embed_certs_from_ocsp   s   z,DocumentSecurityStore._embed_certs_from_ocspc                 C   sd   | j d u r	tdz| j|j W S  ty   Y nw | j tj| d}| 	  || j|j< |S )N"This DSS does not support updates.rT   )
r@   	TypeErrorr#   issuer_serialrW   rX   r
   rY   rV   rS   )r*   certr`   r,   r,   r-   rf      s   
z!DocumentSecurityStore._embed_certr&   c                 C   s"   t |    }td| S )a  
        Hash the contents of a signature object to get the corresponding VRI
        identifier.

        This is internal API.

        :param contents:
            Signature contents.
        :return:
            A name object to put into the DSS.
        /)hashlibsha1digesthexupperr   )contentsidentr,   r,   r-   sig_content_identifier   s   z,DocumentSecurityStore.sig_content_identifierr,   r#   r$   r%   c          	         s    j du r	tdt|}t|}t }t } fdd|D }|r-t | j j}|r:t | j j}|	t 
| |dur`t|||d} j |  j|<    dS dS )a  
        Register validation information for a set of signing certificates
        associated with a particular signature.

        :param identifier:
            Identifier of the signature object (see `sig_content_identifier`).
            If ``None``, only embed the data into the DSS without associating
            it with any VRI.
        :param certs:
            Certificates to add.
        :param ocsps:
            OCSP responses to add.
        :param crls:
            CRLs to add.
        Nrl   c                    s   h | ]}  |qS r,   re   )rg   ro   rP   r,   r-   	<setcomp>   rj   z5DocumentSecurityStore.register_vri.<locals>.<setcomp>ry   )r@   rm   listr4   ra   rE   r$   rF   r%   updaterk   r   rX   r.   rA   rS   )	r*   
identifierr#   r$   r%   	ocsp_refscrl_refs	cert_refsr+   r,   rP   r-   register_vri   s2   


z"DocumentSecurityStore.register_vric                 C   sl   | j }tt| j |d< | jrt| j|d< | jr't| j|t	d< | j
r4t| j
|t	d< |S )z
        Convert the :class:`.DocumentSecurityStore` object to a python
        dictionary. This method also handles DSS updates.

        :return:
            A PDF object representing this DSS.
        /Certsr'   /OCSPs/CRLs)rB   r
   r)   r{   r#   valuesrA   r(   r$   r   r%   )r*   pdf_dictr,   r,   r-   r.      s   z#DocumentSecurityStore.as_pdf_objectc                 c   s0    | j  D ]}| }t|j}|V  qdS )z
        Return a generator that parses and yields all certificates in the DSS.

        :return:
            A generator yielding :class:`.Certificate` objects.
        N)r#   r   rC   r	   loadrD   )r*   cert_refcert_streamro   r,   r,   r-   
load_certs	  s   z DocumentSecurityStore.load_certsTc                 C   s   t |}|dg }t|  | }|rXt|dd}| jD ]}| }tj|j	}|
| q||d< t|dd}	| jD ]}
|
 }tj|j	}|	
| qA|	|d< tdd|i|S )ag  
        Construct a validation context from the data in this DSS.

        :param validation_context_kwargs:
            Extra kwargs to pass to the ``__init__`` function.
        :param include_revinfo:
            If ``False``, revocation info is skipped.
        :return:
            A validation context preloaded with information from this DSS.
        other_certsr$   r,   r%   )dictpopr{   r   r$   rC   	asn1_ocspOCSPResponser   rD   rZ   r%   asn1_crlCertificateListr   )r*   validation_context_kwargsinclude_revinford   r#   r$   rI   ocsp_streamrb   r%   rL   
crl_streamr   r,   r,   r-   as_validation_context  s"   

z+DocumentSecurityStore.as_validation_contexthandlerc              
   C   s<  z|j d }W n ty } zt |d}~ww i }t|dtg d}|D ]}| }t|j}|||j	< q$t|dtg d}	g }
|	D ]}| }t
j|j}|
| qBt|dtg d}g }|D ]}| }tj|j}|| qazt|d }W n ty   d}Y nw t|tr|}nd}| |||	|||d}|S )	a  
        Read a DSS record from a file and add the data to a validation context.

        :param handler:
            PDF handler from which to read the DSS.
        :return:
            A DocumentSecurityStore object describing the current state of the
            DSS.
        /DSSNr   )defaultr   r   r'   )r@   r#   r$   rA   r%   rB   )rootrW   r   r   r{   rC   r	   r   rD   rn   r   r   rZ   r   r   r   
isinstancer   )clsr   dss_dicter   cert_ref_listr   r   ro   r~   r$   rI   r   rb   r   r%   rL   r   r   rA   r@   dssr,   r,   r-   read_dss8  sR   
zDocumentSecurityStore.read_dssr#   r$   r%   pathsvalidation_contextembed_rootspdf_outr   c                   s   z	|  |}	d}
W n ty   d}
| |d}	Y nw |dur$t|}nd}dttj f fdd}fdd	}fd
d}|	j|| | | d |	 }|
rd|	|}||j
td< |  |	S )aD  
        Add or update a DSS, and optionally associate the new information with a
        VRI entry tied to a signature object.

        You can either specify the CMS objects to include directly, or
        pass them in as output from `pyhanko_certvalidator`.

        :param pdf_out:
            PDF writer to write to.
        :param sig_contents:
            Contents of the new signature (used to compute the VRI hash), as
            a hexadecimal string, including any padding.
            If ``None``, the information will not be added to any VRI
            dictionary.
        :param certs:
            Certificates to include in the VRI entry.
        :param ocsps:
            OCSP responses to include in the VRI entry.
        :param crls:
            CRLs to include in the VRI entry.
        :param paths:
            Validation paths that have been established, and need to be added
            to the DSS.
        :param validation_context:
            Validation context from which to draw OCSP responses and CRLs.
        :param embed_roots:
            .. versionadded:: 0.9.0

            Option that controls whether the root certificate of each validation
            path should be embedded into the DSS. The default is ``True``.

            .. note::
                Trust roots are configured by the validator, so embedding them
                typically does nothing in a typical validation process.
                Therefore they can be safely omitted in most cases.
                Nonetheless, embedding the roots can be useful for documentation
                purposes.

            .. warning::
                This only applies to paths, not the ``certs`` parameter.

        :return:
            a :class:`DocumentSecurityStore` object containing both the new
            and existing contents of the DSS (if any).
        FT)r@   Nr&   c                  3   s@     pdE d H  pdD ]} t | }st| |E d H  qd S Nr,   )iternext)path
path_parts)r#   r   r   r,   r-   _certs  s   z:DocumentSecurityStore.supply_dss_in_writer.<locals>._certsc                   3   ,     pdE d H  d urj E d H  d S d S r   rc   r,   )r$   r   r,   r-   _ocsps  
   z:DocumentSecurityStore.supply_dss_in_writer.<locals>._ocspsc                   3   r   r   )r%   r,   )r%   r   r,   r-   _crls  r   z9DocumentSecurityStore.supply_dss_in_writer.<locals>._crlsry   r   )r   r   r   rx   r   r   r	   r   r.   rX   r   r   update_root)r   r   sig_contentsr#   r$   r%   r   r   r   r   createdr}   r   r   r   r   dss_refr,   )r#   r%   r   r$   r   r   r-   supply_dss_in_writerv  s0   :


z*DocumentSecurityStore.supply_dss_in_writerF)	r#   r$   r%   r   r   force_writer   file_credentialstrictr   r   r   c       	      
   C   s^   t ||d}|jdur|
dur|j|
 | j||||||||	d}|s'|jr-|  dS dS )a  
        Wrapper around :meth:`supply_dss_in_writer`.

        The result is applied to the output stream as an incremental update.

        :param output_stream:
            Output stream to write to.
        :param sig_contents:
            Contents of the new signature (used to compute the VRI hash), as
            a hexadecimal string, including any padding.
            If ``None``, the information will not be added to any VRI
            dictionary.
        :param certs:
            Certificates to include in the VRI entry.
        :param ocsps:
            OCSP responses to include in the VRI entry.
        :param crls:
            CRLs to include in the VRI entry.
        :param paths:
            Validation paths that have been established, and need to be added
            to the DSS.
        :param force_write:
            Force a write even if the DSS doesn't have any new content.
        :param validation_context:
            Validation context from which to draw OCSP responses and CRLs.
        :param embed_roots:
            .. versionadded:: 0.9.0

            Option that controls whether the root certificate of each validation
            path should be embedded into the DSS. The default is ``True``.

            .. note::
                Trust roots are configured by the validator, so embedding them
                typically does nothing in a typical validation process.
                Therefore they can be safely omitted in most cases.
                Nonetheless, embedding the roots can be useful for documentation
                purposes.

            .. warning::
                This only applies to paths, not the ``certs`` parameter.
        :param file_credential:
            .. versionadded:: 0.13.0

            Serialised file credential, to update encrypted files.
        :param strict:
            If ``True``, enforce strict validation of the input stream.
            Default is ``True``.
        )r   Nr   )r   security_handlerauthenticater   rQ   write_in_place)r   output_streamr   r#   r$   r%   r   r   r   r   r   r   r   r   r,   r,   r-   add_dss  s    @

zDocumentSecurityStore.add_dss)NNNNN)T) r/   r0   r1   r2   r   r   rN   propertyrQ   rS   ra   rk   rf   staticmethodr
   
NameObjectrx   r   r.   r   r   r	   r   r   r   classmethodr   r   boolr   r    r   r,   r,   r,   r-   r   ]   sx    
"
1
#=
h
r   Fembedded_sigr   c                    s^   j j}|jstd g   fdd}|| jI dH  |s-| jdur-|| jI dH   S )a  
    Query revocation info for a PDF signature using a validation context,
    and store the results in a validation context.

    This works by validating the signer's certificate against the provided
    validation context, which causes revocation info to be cached for
    later retrieval.

    .. warning::
        This function does *not* actually validate the signature, but merely
        checks the signer certificate's chain of trust.

    :param embedded_sig:
        Embedded PDF signature to operate on.
    :param validation_context:
        Validation context to use.
    :param skip_timestamp:
        If the signature has a time stamp token attached to it, also collect
        revocation information for the timestamp.
    :return:
        A list of validation paths.
    zfRevocation mode is set to soft-fail/tolerant mode; collected revocation information may be incomplete.c                    sF   t | }|j}|j}t||d}|jt dI d H } | d S )N)intermediate_certsr   )	key_usage)r   signer_certr   r   async_validate_usager4   rZ   )signed_data	cert_inforo   r   	validatorr   r   r   r,   r-   _validate_signed_dataW  s   z6collect_validation_info.<locals>._validate_signed_dataN)revinfo_policyrevocation_checking_policy	essentialloggerwarningr   attached_timestamp_data)r   r   skip_timestamprevinfo_fetch_policyr   r,   r   r-   r   0  s   r   Tr   c	                    s   | j }	|r|	j }
}t| nt|}
t| ||dI dH }|r+| j d}nd}t	
|	}||_tj|||||d}|sD|jrQ|rK|  n||
 n|sc|	jd tt||	j|
 t||
S )aY  
    .. versionadded: 0.9.0

    Add validation info (CRLs, OCSP responses, extra certificates) for a
    signature to the DSS of a document in an incremental update.
    This is a wrapper around :func:`collect_validation_info`.

    :param embedded_sig:
        The signature for which the revocation information needs to be
        collected.
    :param validation_context:
        The validation context to use.
    :param skip_timestamp:
        If ``True``, do not attempt to validate the timestamp attached to
        the signature, if one is present.
    :param add_vri_entry:
        Add a ``/VRI`` entry for this signature to the document security store.
        Default is ``True``.
    :param output:
        Write the output to the specified output stream.
        If ``None``, write to a new :class:`.BytesIO` object.
        Default is ``None``.
    :param in_place:
        Sign the original input stream in-place.
        This parameter overrides ``output``.
    :param chunk_size:
        Chunk size parameter to use when copying output to a new stream
        (irrelevant if ``in_place`` is ``True``).
    :param force_write:
        Force a new revision to be written, even if not necessary (i.e.
        when all data in the validation context is already present in the DSS).
    :param embed_roots:
        Option that controls whether the root certificate of each validation
        path should be embedded into the DSS. The default is ``True``.

        .. note::
            Trust roots are configured by the validator, so embedding them
            typically does nothing in a typical validation process.
            Therefore they can be safely omitted in most cases.
            Nonetheless, embedding the roots can be useful for documentation
            purposes.
    :return:
        The (file-like) output object to which the result was written.
    )r   Nascii)r   r   r   r   )readerstreamr   !assert_writable_and_random_accessprepare_rw_output_streamr   pkcs7_contentrt   encoder   from_readerIO_CHUNK_SIZEr   r   rQ   r   writeseekchunked_write	bytearrayfinalise_output)r   r   r   add_vri_entryin_placeoutputr   
chunk_sizer   r   working_outputr   r   r   resulting_dssr,   r,   r-   r   k  s:   8




r   )F)9rq   loggingdataclassesr   r   r3   typingr   r   
asn1cryptor   r   r   r   r   asn1crypto.x509r	   pyhanko.pdf_utilsr
   r   pyhanko.pdf_utils.genericr   $pyhanko.pdf_utils.incremental_writerr   pyhanko.pdf_utils.miscr   pyhanko.pdf_utils.rw_commonr   pyhanko.pdf_utils.writerr   pyhanko_certvalidatorr   r   pyhanko_certvalidator.pathr   generalr   errorsr   r   pdf_embeddedr   __all__pdf_utils.cryptr    pdf_utils.readerr!   	getLoggerr/   r   r   r   r   r   DEFAULT_CHUNK_SIZEr   r   r,   r,   r,   r-   <module>   sf    
(   Y
>	