U
    g                    @   s  d Z ddlZddlZddlZddlZddlZddlmZmZ ddl	m	Z	 ddl
mZmZmZmZmZmZmZmZmZ ddlZddlmZmZmZmZ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%m&Z& ddl'm(Z( ddl)m*Z*m+Z+ ddl,m-Z-m.Z. ddl/m0Z0 ddl1m2Z2 ddl3m4Z4 ddl5m6Z6 ddl7m8Z8 ddl9m:Z: ddl;m<Z< ddl=m>Z>m?Z?m@Z@mAZAmBZBmCZCmDZDmEZEmFZFmGZG ddlHmIZImJZJmKZKmLZLmMZM ddlNmOZO ddlPmQZQ ddlRmSZS ddlTmUZUmVZVmWZWmXZXmYZY ddlZm[Z[m\Z\m]Z]m^Z^ ddl_m`Z`maZambZb dd d!d"d#d$d%d&d'd(d)d*gZcd+d,ldmeZe d-d.l:mfZf egehZied/d0G d1d" d"ZjG d2d# d#ejkZled/d0G d3d! d!ejZmed/d0G d4d  d ejZned/d0G d5d dZoe8d6d7d8ZpdTe8eqejresd:d;d<Zte8d6d=d>Zue8d6d?d@ZvejwdAdBdCZxG dDd$ d$ZydEdF ZzG dGd% d%Z{ed/d0G dHd) d)Z|e8e-j}dIdJdKZ~G dLd& d&Zed/d0G dMd* d*ZG dNdO dOe:jfZG dPdQ dQe:jZG dRd' d'ZG dSd( d(ZdS )UzH
This module implements support for PDF-specific signing functionality.
    N)	dataclassfield)datetime)	IOAnyDictIterableListOptionalSetTupleUnion)algoscmscrlkeysocsp)pdf)VOID)hashes)CertificateValidatorValidationContext)PathBuildingErrorPathValidationError)ValidationPath)ACValidationResultasync_validate_ac)genericmisc)pdfmac)pdf_name)IncrementalPdfFileWriter)PdfFileReader)BasePdfFileWriter)
attributes)CAdESSignedAttrSpec)
FieldMDPSpecInvisSigSettingsMDPPermSeedLockDocumentSigAuthTypeSigFieldSpecSigSeedSubFilterSigSeedValFlagsSigSeedValueSpecenumerate_sig_fields)SigningErrorfind_unique_cms_attributeget_cms_hash_algo_for_mechanismget_pyca_cryptography_hashsimple_cms_attribute)TimeStamper)BaseStampStyle   )	constants)PdfCMSEmbedderSigAppearanceSetup
SigIOSetupSigMDPSetupSigObjSetup)
BuildPropsDocumentTimestampPreparedByteRangeDigestSignatureObject)PdfCMSSignedAttributesSignerselect_suitable_signing_mdPdfSignatureMetadataDSSContentSettingsTimestampDSSContentSettingsGeneralDSSContentSettingsSigDSSPlacementPreferencePdfTimeStamper	PdfSignerPdfSigningSessionPdfTBSDocumentPdfPostSignatureDocumentPreSignValidationStatusPostSignInstructions   )SerialisedCredential   )CMSAttributeProviderT)frozenc                   @   s*   e Zd ZU dZdZeed< dZeed< dS )rH   za
    .. versionadded:: 0.8.0

    Settings that govern DSS creation and updating in general.
    Tinclude_vriskip_if_unneededN)__name__
__module____qualname____doc__rV   bool__annotations__rW    r^   r^   C/tmp/pip-unpacked-wheel-owvgwkas/pyhanko/sign/signers/pdf_signer.pyrH   [   s   
c                   @   s(   e Zd ZdZe Ze Ze ZdS )rI   z
    .. versionadded:: 0.8.0

    Preference for where to perform a DSS update with validation information
    for a specific signature.
    N)	rX   rY   rZ   r[   enumautoTOGETHER_WITH_SIGNATURESEPARATE_REVISIONTOGETHER_WITH_NEXT_TSr^   r^   r^   r_   rI   ~   s
   	c                   @   s&   e Zd ZU dZdZeed< dd ZdS )rG   aY  
    .. versionadded:: 0.8.0

    Settings for a DSS update with validation information for a document
    timestamp.

    .. note::
        In most workflows, adding a document timestamp doesn't trigger any DSS
        updates beyond VRI additions, because the same TSA is used for signature
        timestamps and for document timestamps.
    Fupdate_before_tsc                 C   s   | j r| jrtddS )e
        Check settings for consistency, and raise :class:`.SigningError`
        otherwise.
        zqIf VRI entries are to be included, DSS updates can only be performed after the timestamp in question was created.N)rV   re   r0   selfr^   r^   r_   assert_viable   s    z)TimestampDSSContentSettings.assert_viableN)rX   rY   rZ   r[   re   r\   r]   ri   r^   r^   r^   r_   rG      s   
c                   @   sF   e Zd ZU dZejZeed< dZe	e
 ed< e
dddZdd	 ZdS )
rF   zm
    .. versionadded:: 0.8.0

    Settings for a DSS update with validation information for a signature.
    	placementNnext_ts_settingsreturnc                 C   s0   | j }|dk	r|S | jtjk}t| j| j|dS )z
        Retrieve DSS update settings for document timestamps that are
        part of our signing workflow, if there are any.
        N)rV   rW   re   )rk   rj   rI   rb   rG   rV   rW   )rh   Zts_settingsre   r^   r^   r_   get_settings_for_ts   s    
z&DSSContentSettings.get_settings_for_tsc                 C   s.   | j tjk}| jr|rtd|    dS )rf   zqIf VRI entries are to be included, DSS updates can only be performed after the signature in question was created.N)rj   rI   rb   rV   r0   rn   ri   )rh   Zpre_signr^   r^   r_   ri     s    

z DSSContentSettings.assert_viable)rX   rY   rZ   r[   rI   rd   rj   r]   rk   r
   rG   rn   ri   r^   r^   r^   r_   rF      s   


c                   @   sX  e Zd ZU dZdZee ed< dZee ed< dZ	ee ed< dZ
ee ed< dZee ed< dZee ed< dZee ed	< dZee ed
< dZee ed< dZeed< dZee ed< dZeed< dZeed< dZee ed< dZee ed< ejZeed< edd dZ e!e ed< dZ"ee# ed< e$ Z%e$ed< dZ&eed< dZ'ee ed< dS )rE   z,
    Specification for a PDF signature.
    N
field_namemd_algorithmlocationreasoncontact_infonameapp_build_propsprop_auth_timeprop_auth_typeFcertify	subfilterembed_validation_infouse_pades_ltatimestamp_field_namevalidation_contextdocmdp_permissionsc                   C   s   t jS N)r8   ZDEFAULT_SIGNER_KEY_USAGEr^   r^   r^   r_   <lambda>      zPdfSignatureMetadata.<lambda>default_factorysigner_key_usagecades_signed_attr_specdss_settingstight_size_estimatesac_validation_context)(rX   rY   rZ   r[   ro   r
   strr]   rp   rq   rr   rs   rt   ru   r>   rv   intrw   r*   rx   r\   ry   r,   rz   r{   r|   r}   r   r(   
FILL_FORMSr~   r   r   r   r   r%   rF   r   r   r   r^   r^   r^   r_   rE     s2   
		Z
pdf_writerc                 C   s&   | j dd | jdk r"| tj dS )z
    Helper function to ensure that the output PDF is at least PDF 1.7, and that
    the relevant ESIC extension for PAdES is enabled if the version lower than
    2.0.
    )r7      versionrS   r   N)ensure_output_versionZoutput_versionregister_extensionr8   ZESIC_EXTENSION_1r   r^   r^   r_   _ensure_esic_ext  s    
r   F)pdf_outrp   signed_datadocument_digestc                 C   s   |  |}|d d }|d j}tt|}|| | }	|rH|	}|j||	|d}
|d }|tkrrt	
g }|td|
 ||d< dS )a  
    Utility function to add a MAC token to an externally generated CMS
    payload. The payload is modified in-place.

    :param pdf_out:
        Writer to contain output.
    :param md_algorithm:
        The message digest algorithm to use for the MAC.
    :param document_digest:
        The document digest that should go into the MAC token.
    :param signed_data:
        A CMS signed data value.
    :param dry_run:
        Whether this is considered a dry run for size estimation purposes.
    Zsigner_infosr   	signaturer   signature_digestdry_runZunsigned_attrspdf_mac_dataN)_init_mac_handlernativer   Hashr3   updatefinalizebuild_pdfmac_tokenr   r   CMSAttributesappendr4   )r   rp   r   r   r   mac_handlersiZsignature_bytesmd
sig_digestZ	mac_tokenZuar^   r^   r_   add_mac_to_external_cms  s$    



r   c                 C   s   | j dd | tj d S Nr   r   )r   r   r8   ZISO32001r   r^   r^   r_   _ensure_iso32001_ext  s    r   c                 C   s   | j dd | tj d S r   )r   r   r8   ZISO32002r   r^   r^   r_   _ensure_iso32002_ext  s    r   )pubkeyc                 C   s   | j \}}|dko|tjkS )Nnamed)Zcurver8   ZISO32002_CURVE_NAMES)r   kindZcurve_idr^   r^   r_   _is_iso32002_curve  s    
r   c                   @   s   e Zd ZdZde dfeee eedddZe	eddd	Z
dd
de ejd
deee eedddZdd
de ejd
ddeee eeedddZddejejfedddZddejejdfeedddZdS )rJ   z]
    Class to encapsulate the process of appending document timestamps to
    PDF files.
    NZ	Timestamp)timestamperro   invis_settingsreadable_field_namec                 C   s   || _ || _|| _|| _d S r   )default_timestamper_field_name_readable_field_name_invis_settings)rh   r   ro   r   r   r^   r^   r_   __init__&  s    zPdfTimeStamper.__init__rl   c                 C   s   | j pdtt  S )z
        Retrieve or generate the field name for the signature field to contain
        the document timestamp.

        :return:
            The field name, as a (Python) string.
        z
Timestamp-)r   r   uuidZuuid4rg   r^   r^   r_   ro   2  s    	zPdfTimeStamper.field_nameF)in_placeoutputr   
chunk_sizer   )r   r   r   r   c                C   s*   t | j|||||||||
|	|d}|S )a	  
        .. versionchanged:: 0.9.0
            Wrapper around :meth:`async_timestamp_pdf`.

        Timestamp the contents of ``pdf_out``.
        Note that ``pdf_out`` should not be written to after this operation.

        :param pdf_out:
            An :class:`.IncrementalPdfFileWriter`.
        :param md_algorithm:
            The hash algorithm to use when computing message digests.
        :param validation_context:
            The :class:`.pyhanko_certvalidator.ValidationContext`
            against which the TSA response should be validated.
            This validation context will also be used to update the DSS.
        :param bytes_reserved:
            Bytes to reserve for the CMS object in the PDF file.
            If not specified, make an estimate based on a dummy signature.

            .. warning::
                Since the CMS object is written to the output file as a
                hexadecimal string, you should request **twice** the (estimated)
                number of bytes in the DER-encoded version of the CMS object.
        :param validation_paths:
            If the validation path(s) for the TSA's certificate are already
            known, you can pass them using this parameter to avoid having to
            run the validation logic again.
        :param timestamper:
            Override the default :class:`.TimeStamper` associated with this
            :class:`.PdfTimeStamper`.
        :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:
            Size of the internal buffer (in bytes) used to feed data to the
            message digest function if the input stream does not support
            ``memoryview``.
        :param dss_settings:
            DSS output settings. See :class:`.TimestampDSSContentSettings`.
        :param tight_size_estimates:
            When estimating the size of a document timestamp container,
            do not add safety margins.

            .. note::
                External TSAs cannot be relied upon to always produce the
                exact same output length, which makes this option risky to use.
        :return:
            The output stream containing the signed output.
        )	r}   bytes_reservedvalidation_pathsr   r   r   r   r   r   )asynciorunasync_timestamp_pdf)rh   r   rp   r}   r   r   r   r   r   r   r   r   resultr^   r^   r_   timestamp_pdfB  s     DzPdfTimeStamper.timestamp_pdfT)r   r   r   r   r   embed_roots)r   r   r   r   r   c             	      s  t | |jdk	o|jj}ddlm} |p.| j}|dk	r||}|dkrNg }|2 z3 dH W }|| qR6 |	  |	j	r|j
j|d|||d | j}|dkr||I dH }|rt|||d ddd t| d	 }|r|}n|d	|d
   }t|d}t|| j| jd}t|dj||dd}t| |t|d}|rLt|| t||||
d}||\}}||j|I dH }|rt|||d |jd ||}|dk	r|	j	s|	jsd}d}|jr|j }|r|  }|j
j!|||||	j" ||d t#$||S )au  
        .. versionadded:: 0.9.0

        Timestamp the contents of ``pdf_out``.
        Note that ``pdf_out`` should not be written to after this operation.

        :param pdf_out:
            An :class:`.IncrementalPdfFileWriter`.
        :param md_algorithm:
            The hash algorithm to use when computing message digests.
        :param validation_context:
            The :class:`.pyhanko_certvalidator.ValidationContext`
            against which the TSA response should be validated.
            This validation context will also be used to update the DSS.
        :param bytes_reserved:
            Bytes to reserve for the CMS object in the PDF file.
            If not specified, make an estimate based on a dummy signature.

            .. warning::
                Since the CMS object is written to the output file as a
                hexadecimal string, you should request **twice** the (estimated)
                number of bytes in the DER-encoded version of the CMS object.
        :param validation_paths:
            If the validation path(s) for the TSA's certificate are already
            known, you can pass them using this parameter to avoid having to
            run the validation logic again.
        :param timestamper:
            Override the default :class:`.TimeStamper` associated with this
            :class:`.PdfTimeStamper`.
        :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:
            Size of the internal buffer (in bytes) used to feed data to the
            message digest function if the input stream does not support
            ``memoryview``.
        :param dss_settings:
            DSS output settings. See :class:`.TimestampDSSContentSettings`.
        :param tight_size_estimates:
            When estimating the size of a document timestamp container,
            do not add safety margins.

            .. note::
                External TSAs cannot be relied upon to always produce the
                exact same output length, which makes this option risky to use.
        :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 output stream containing the signed output.
        Nr   
validation)sig_contentspathsr}   r   contentr   T)rp   r   r   r   rS      )r   )sig_field_nameZinvis_sig_settingsr   new_field_specFro   writerexisting_fields_only)sig_placeholder)rp   r   r   r   )rp   r   r   )output_streamr   r   r}   force_writer   file_credential)%r   security_handlerpdf_mac_enabledpyhanko.signr   r   r   r   ri   re   DocumentSecurityStoresupply_dss_in_writerro   Zasync_dummy_responser   lendumpr?   r+   r   r   r9   	write_cmsnextsendr=   _register_mac_on_sigr;   Zasync_timestampr   rV   extract_credential	serialiseadd_dssrW   r   finalise_output)rh   r   rp   r}   r   r   r   r   r   r   r   r   r   Zneed_macr   Z
paths_coropathro   Ztest_tsttest_lenZtimestamp_obj
field_spec
cms_writersig_obj_refZsig_ioZprep_digest
res_outputZtimestamp_cmsr   credential_ser
credentialr^   r^   r_   r     s    O




	
 



z"PdfTimeStamper.async_timestamp_pdfreaderc                 C   s    | j ||||||d}t|S )a  
        .. versionchanged:: 0.9.0
            Wrapper around :meth:`async_update_archival_timestamp_chain`.

        Validate the last timestamp in the timestamp chain on a PDF file, and
        write an updated version to an output stream.

        :param reader:
            A :class:`PdfReader` encapsulating the input file.
        :param validation_context:
            :class:`.pyhanko_certvalidator.ValidationContext` object to validate
            the last timestamp.
        :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:
            Size of the internal buffer (in bytes) used to feed data to the
            message digest function if the input stream does not support
            ``memoryview``.
        :param default_md_algorithm:
            Message digest to use if there are no preceding timestamps in the
            file.
        :return:
            The output stream containing the signed output.
        )r   r}   r   r   r   default_md_algorithm)%async_update_archival_timestamp_chainr   r   )rh   r   r}   r   r   r   r   coror^   r^   r_   update_archival_timestamp_chainU  s    &z.PdfTimeStamper.update_archival_timestamp_chain)r   r   c                    s(  ddl m} ddlm}	 ||}
zt|
}W n" tk
rP   td d}Y nX d}|dkrd|}n.|	 }|j
}|j|||I dH }|j}|}|r|j}n*t|}|jd tt||j| t|}|dk	r|dk	st|jj||j|jf||d | j|||d|d	I dH  t||S )
a  
        .. versionadded:: 0.9.0

        Validate the last timestamp in the timestamp chain on a PDF file, and
        write an updated version to an output stream.

        :param reader:
            A :class:`PdfReader` encapsulating the input file.
        :param validation_context:
            :class:`.pyhanko_certvalidator.ValidationContext` object to validate
            the last timestamp.
        :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:
            Size of the internal buffer (in bytes) used to feed data to the
            message digest function if the input stream does not support
            ``memoryview``.
        :param default_md_algorithm:
            Message digest to use if there are no preceding timestamps in the
            file.
        :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 output stream containing the signed output.
        rS   r   )TimestampSignatureStatuszVDocument does not have any document timestamps yet. This may cause unexpected results.Nr   )r   r}   r   T)r   r   ) r   Zvalidation.statusr   get_timestamp_chainr   StopIterationloggerwarningZcompute_digestr   ZltvZestablish_timestamp_trustrp   streamr   prepare_rw_output_streamseekZchunked_write	bytearrayr!   AssertionErrorr   r   Zpkcs7_contentvalidation_pathr   r   )rh   r   r}   r   r   r   r   r   r   r   Z
timestampsZlast_timestampZ
tst_statusrp   Zexpected_imprintZ	tst_tokenZlast_tst_statusr   r   r^   r^   r_   r     sZ    7

  


	z4PdfTimeStamper.async_update_archival_timestamp_chain)NNNN)NNNN)rX   rY   rZ   r[   r'   r5   r
   r   r   propertyro   rG   r   DEFAULT_CHUNK_SIZEr!   r\   r   r   r8   
DEFAULT_MDr"   r   r   r^   r^   r^   r_   rJ      s~       	Y    	 C4c                 C   s2   zt t| dd W dS  tk
r,   Y dS X d S )NT)Zfilled_statusF)r   r/   r   )handlerr^   r^   r_   _signatures_exist  s
    r  c                   @   s<  e Zd ZdZdZddddeeee ee	 ee
 dddZeee dd	d
ZedddZee dddZee edddZeedddZd%eddddZd&dddejdeeedef dddZd'dddejdeeedef dddZd(dddejded d!d"Zd)dddejded d#d$ZdS )*rK   a  
    .. versionchanged: 0.7.0
        This class is no longer a subclass of :class:`.PdfTimeStamper`.

    Class to handle PDF signatures in general.

    :param signature_meta:
        The specification of the signature to add.
    :param signer:
        :class:`.Signer` object to use to produce the signature object.
    :param timestamper:
        :class:`.TimeStamper` object to use to produce any time stamp tokens
        that might be required.
    :param stamp_style:
        Stamp style specification to determine the visible style of the
        signature, typically an object of type :class:`.TextStampStyle` or
        :class:`.QRStampStyle`. Defaults to
        :const:`constants.DEFAULT_SIGNING_STAMP_STYLE`.
    :param new_field_spec:
        If a new field is to be created, this parameter allows the caller
        to specify the field's properties in the form of a
        :class:`.SigFieldSpec`. This parameter is only meaningful if
        ``existing_fields_only`` is ``False``.
    FN)r   stamp_styler   )signature_metasignerr   r  r   c                C   s   || _ |d k	r"|j|jkr"td|| _|p0tj}|| _|  z| jd }t	|| _
W n tk
rp   d | _
Y nX || _|| _d S )NzLField names specified in SigFieldSpec and PdfSignatureMetadata do not agree.)r  r   ro   r0   r  r8   ZDEFAULT_SIGNING_STAMP_STYLEr  "get_signature_mechanism_for_digestr2   signer_hash_algo
ValueErrorr   r   )rh   r  r  r   r  r   Zmechr^   r^   r_   r     s&    	

zPdfSigner.__init__rl   c                 C   s   | j jp| jS )a  
        Name of the default message digest algorithm for this signer, if there
        is one.
        This method will try the :attr:`~.PdfSignatureMetadata.md_algorithm`
        attribute on the signer's :attr:`signature_meta`, or try to retrieve
        the digest algorithm associated with the underlying
        :class:`~pyhanko.sign.signers.pdf_cms.Signer`.

        :return:
            The name of the message digest algorithm, or ``None``.
        )r  rp   r  rg   r^   r^   r_   default_md_for_signer>  s    zPdfSigner.default_md_for_signerr   c                 C   sP   | j jrt|rtdddlm} ||}|d kr8d S |jtjkrLtdd S )NzICertification signatures must be the first signature in a given document.r   )read_certification_dataz$Author signature forbids all changes)	r  rx   r  r0   pyhanko.sign.validationr	  Z
permissionr(   
NO_CHANGES)rh   r   r	  Zcdr^   r^   r_   "_enforce_certification_constraintsM  s    z,PdfSigner._enforce_certification_constraintsc                 C   s*   | j r
d S |d}|d kr d S t|S )Nz/SV)
_ignore_svgetr.   from_pdf_object)rh   	sig_fieldZsv_dictr^   r^   r_   _retrieve_seed_value_spec`  s    
z#PdfSigner._retrieve_seed_value_spec)sv_specrm   c                 C   s   | j }|d k	r |jr |jd }nd }| jd k	r6| j}n2|d k	rD|}n$| jjd k	r`t| jjj}ntd|jd k	rz|jj	nd }|d k	rt
 }td|i}|||std| d|jj d|S )Nr   zCould not select a default digest algorithm. Please supply a value in the signature settings, or configure the signer with an explicit signature mechanism that includes a digest algorithm specification.	algorithmzThe hash algorithm zJ is not allowed in the specified validation context (usage policy of type z).)r  digest_methodsr  r  signing_certrD   
public_keyr0   r}   algorithm_policyr   nowr   ZDigestAlgorithmZdigest_algorithm_allowed	__class__rX   )rh   r  r  Zsv_md_algorithmrp   r  r  Zmd_algo_objr^   r^   r_   _select_md_algorithmk  s6    
	
zPdfSigner._select_md_algorithm)r   rp   c             
   C   s   | j jtjkrt| |jd k	r4|jjr4|tj	 z| j
|}|j}W nB ttfk
r } z tdt| d W Y d S d }~X Y nX |dkrt| nZ|dkrt| t| n@|ds|dkrt| | j
j}|r|dkrt|jrt| d S )Nz*Failed to introspect signature mechanism: z>. Will forgo algorithm-based automatic extension registration.Zed25519Zed448Zsha3Zshake256Zecdsa)r  ry   r,   PADESr   r   r   r   r   ZISO32004r  r  Zsignature_algor0   r  r   debugr   r   r   
startswithr  r   r  )rh   r   rp   Zsig_mechZsig_algoecertr^   r^   r_   register_extensions  s@    


zPdfSigner.register_extensionsrL   r   rm   c              
   C   s   t |tr&|j}|jr&|jjr&td| j}| j}t	| j
dj|j||d}t|}| }| |}	t |tr|| |j | |	}
| j||
d |	dk	r|	jr|dkr|	 }|j}|dkr|	dk	r|	jr|	jd }ntj}t| ||||
|||	d}|S )a  
        Initialise a signing session with this :class:`.PdfSigner` for a
        specified PDF file writer.

        This step in the signing process handles all field-level operations
        prior to signing: it creates the target form field if necessary, and
        makes sure the seed value dictionary gets processed.

        See also :meth:`digest_doc_for_signing` and :meth:`sign_pdf`.

        :param pdf_out:
            The writer containing the PDF file to be signed.
        :param existing_fields_only:
            If ``True``, never create a new empty signature field to contain
            the signature.
            If ``False``, a new field may be created if no field matching
            :attr:`~.PdfSignatureMetadata.field_name` exists.
        :return:
            A :class:`.PdfSigningSession` object modelling the signing session
            in its post-setup stage.
        z`Attempting to sign document with hybrid cross-reference sections while hybrid xrefs are disabledr   r   )rp   Nr   )r  )
isinstancer!   prevstrictZxrefsZhybrid_xrefs_presentr0   r   r  r9   r   r   ro   r   Z
get_objectr  r  r  r   Ztimestamp_requiredZbuild_timestamperry   
subfiltersr,   ADOBE_PKCS7_DETACHEDrL   )rh   r   r   r#  r   r  r   Zsig_field_refr  r  rp   ry   sessionr^   r^   r_   init_signing_session  sZ    
	


zPdfSigner.init_signing_session)appearance_text_paramsr   r   r   rM   c          	      C   s.   t dt t| j|||||||d}|S )a	  
        .. deprecated:: 0.9.0
            Use :meth:`async_digest_doc_for_signing` instead.

        Set up all stages of the signing process up to and including the point
        where the signature placeholder is allocated, and the document's
        ``/ByteRange`` digest is computed.

        See :meth:`sign_pdf` for a less granular, more high-level approach.

        .. note::
            This method is useful in remote signing scenarios, where you might
            want to free up resources while waiting for the remote signer to
            respond. The :class:`.PreparedByteRangeDigest` object returned
            allows you to keep track of the required state to fill the
            signature container at some later point in time.

        :param pdf_out:
            A PDF file writer (usually an :class:`.IncrementalPdfFileWriter`)
            containing the data to sign.
        :param existing_fields_only:
            If ``True``, never create a new empty signature field to contain
            the signature.
            If ``False``, a new field may be created if no field matching
            :attr:`~.PdfSignatureMetadata.field_name` exists.
        :param bytes_reserved:
            Bytes to reserve for the CMS object in the PDF file.
            If not specified, make an estimate based on a dummy signature.

            .. warning::
                Since the CMS object is written to the output file as a
                hexadecimal string, you should request **twice** the (estimated)
                number of bytes in the DER-encoded version of the CMS object.
        :param appearance_text_params:
            Dictionary with text parameters that will be passed to the
            signature appearance constructor (if applicable).
        :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:
            Size of the internal buffer (in bytes) used to feed data to the
            message digest function if the input stream does not support
            ``memoryview``.
        :return:
            A tuple containing a :class:`.PreparedByteRangeDigest` object,
            a :class:`.PdfTBSDocument` object and an output handle to which the
            document in its current state has been written.
        zR'digest_doc_for_signing' is deprecated, use 'async_digest_doc_for_signing' insteadr   r   r)  r   r   r   )warningswarnDeprecationWarningr   r   async_digest_doc_for_signing	rh   r   r   r   r)  r   r   r   r   r^   r^   r_   digest_doc_for_signing  s     ?z PdfSigner.digest_doc_for_signingc                   sx   | j ||d}||I dH }	|dkrB|j|	| jjd}
|
I dH }|j|	||d}|j|||d\}}||t||fS )a	  
        .. versionadded:: 0.9.0

        Set up all stages of the signing process up to and including the point
        where the signature placeholder is allocated, and the document's
        ``/ByteRange`` digest is computed.

        See :meth:`sign_pdf` for a less granular, more high-level approach.

        .. note::
            This method is useful in remote signing scenarios, where you might
            want to free up resources while waiting for the remote signer to
            respond. The :class:`.PreparedByteRangeDigest` object returned
            allows you to keep track of the required state to fill the
            signature container at some later point in time.

        :param pdf_out:
            A PDF file writer (usually an :class:`.IncrementalPdfFileWriter`)
            containing the data to sign.
        :param existing_fields_only:
            If ``True``, never create a new empty signature field to contain
            the signature.
            If ``False``, a new field may be created if no field matching
            :attr:`~.PdfSignatureMetadata.field_name` exists.
        :param bytes_reserved:
            Bytes to reserve for the CMS object in the PDF file.
            If not specified, make an estimate based on a dummy signature.

            .. warning::
                Since the CMS object is written to the output file as a
                hexadecimal string, you should request **twice** the (estimated)
                number of bytes in the DER-encoded version of the CMS object.
        :param appearance_text_params:
            Dictionary with text parameters that will be passed to the
            signature appearance constructor (if applicable).
        :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:
            Size of the internal buffer (in bytes) used to feed data to the
            message digest function if the input stream does not support
            ``memoryview``.
        :return:
            A tuple containing a :class:`.PreparedByteRangeDigest` object,
            a :class:`.PdfTBSDocument` object and an output handle to which the
            document in its current state has been written.
        r   N)validation_infotightr2  r   r)  r   r   r   )	r(  perform_presign_validation!estimate_signature_container_sizer  r   prepare_tbs_documentdigest_tbs_documentr   r   )rh   r   r   r   r)  r   r   r   signing_sessionr2  
estimationtbs_documentprepared_br_digestr   r^   r^   r_   r.  m  s6    >

  

z&PdfSigner.async_digest_doc_for_signing)r   c          	      C   s"   t | j|||||||d}|S )a  
        .. versionchanged:: 0.9.0
            Wrapper around :meth:`async_sign_pdf`.

        Sign a PDF file using the provided output writer.

        :param pdf_out:
            A PDF file writer (usually an :class:`.IncrementalPdfFileWriter`)
            containing the data to sign.
        :param existing_fields_only:
            If ``True``, never create a new empty signature field to contain
            the signature.
            If ``False``, a new field may be created if no field matching
            :attr:`~.PdfSignatureMetadata.field_name` exists.
        :param bytes_reserved:
            Bytes to reserve for the CMS object in the PDF file.
            If not specified, make an estimate based on a dummy signature.
        :param appearance_text_params:
            Dictionary with text parameters that will be passed to the
            signature appearance constructor (if applicable).
        :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:
            Size of the internal buffer (in bytes) used to feed data to the
            message digest function if the input stream does not support
            ``memoryview``.
        :return:
            The output stream containing the signed data.
        r*  )r   r   async_sign_pdfr/  r^   r^   r_   sign_pdf  s    -zPdfSigner.sign_pdfc                   s   | j ||d}||I dH }	|dkrB|j|	| jjd}
|
I dH }|j|	||d}|j|||d\}}|j|jt	|j
|	dkrdn|	j| jjddI dH }|j||dI dH  t||S )	a  
        .. versionadded:: 0.9.0

        Sign a PDF file using the provided output writer.

        :param pdf_out:
            A PDF file writer (usually an :class:`.IncrementalPdfFileWriter`)
            containing the data to sign.
        :param existing_fields_only:
            If ``True``, never create a new empty signature field to contain
            the signature.
            If ``False``, a new field may be created if no field matching
            :attr:`~.PdfSignatureMetadata.field_name` exists.
        :param bytes_reserved:
            Bytes to reserve for the CMS object in the PDF file.
            If not specified, make an estimate based on a dummy signature.
        :param appearance_text_params:
            Dictionary with text parameters that will be passed to the
            signature appearance constructor (if applicable).
        :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:
            Size of the internal buffer (in bytes) used to feed data to the
            message digest function if the input stream does not support
            ``memoryview``.
        :return:
            The output stream containing the signed data.
        r1  N)r3  r4  r5  Zsigning_timeadobe_revinfo_attrZcades_signed_attrs)r   pdf_cms_signed_attrsr   )r(  r6  r7  r  r   r8  r9  perform_signaturer   rB   system_timerA  r   post_signature_processingr   r   )rh   r   r   r   r)  r   r   r   r:  r2  r;  r<  r=  r   Zpost_signing_docr^   r^   r_   r>    sL    -
 
  
 zPdfSigner.async_sign_pdf)F)FN)FN)FN)FN) rX   rY   rZ   r[   r  rE   rC   r
   r5   r6   r+   r   r   r   r  r"   r  r.   r  r  r#   r   r(  r   r   r   r@   r   r0  r.  r?  r>  r^   r^   r^   r_   rK     s   !/ ( _  T  ]  =  c                   @   s   e Zd ZU dZeed< ee ed< dZeee  ed< dZ	ee
j ed< eedZeej ed< eedZeej ed	< eedZee ed
< dS )rO   z
    .. versionadded:: 0.7.0

    Container for validation data collected prior to creating a signature, e.g.
    for later inclusion in a document's DSS, or as a signed attribute on
    the signature.
    signer_pathr   Nts_validation_pathsrA  r   ocsps_to_embedcrls_to_embedac_validation_paths)rX   rY   rZ   r[   r   r]   r	   rH  r
   rA  asn1_pdfZRevocationInfoArchivalr   listrI  r   ZOCSPResponserJ  r   ZCertificateListrK  r^   r^   r^   r_   rO   X  s   
r   r   c              	   C   s.   |  tdttdtdtd|i d S )Nz	/AuthCodez/MACLocationz/AttachedToSigz
/SigObjRef)Zset_custom_trailer_entryr    r   DictionaryObjectrN  r^   r^   r_   r     s      r   c                	   @   s   e Zd ZdZdeeeee e	ee
 ee dddZdee ee dddZed	d
dZdd Zdd ZedddZee dddZd ee dddZd!ee ddddZdS )"rL   z
    .. versionadded:: 0.7.0

    Class modelling a PDF signing session in its initial state.

    The ``__init__`` method is internal API, get an instance using
    :meth:`.PdfSigner.init_signing_session`.
    N)
pdf_signerr   rp   r   ry   rE  r  c
           
      C   sV   || _ || _|| _|| _|| _|| _|| _|tjk| _	|pHt
jt d| _|	| _d S )N)tz)rP  r   r  r   rp   r   ry   r,   r  	use_padesr   r  tzlocalZget_localzonerE  r  )
rh   rP  r   r   r  rp   r   ry   rE  r  r^   r^   r_   r     s    zPdfSigningSession.__init__r!  c              	      s  | j }g }|j}|j}|jrV| j jjdkr4tdn"|dkrFtdn|jsVt	d |j}|dkrhdS | 
||jI dH }|| |jrt|tr| ||jI dH }|dk	r|| | j}|dk	r||}	g }
|	2 z 3 dH W }|| |
| q6 nd}
|jdk	rP| |j}g }|2 z"3 dH W }|| || q(6 ng }|jr| js|dk	srttj|j|jd}nd}t|||
||j|j|dS )a  
        Perform certificate validation checks for the signer's certificate,
        including any necessary revocation checks.

        This function will also attempt to validate & collect revocation
        information for the relevant TSA (by requesting a dummy timestamp).

        :param pdf_out:
            Current PDF writer. Technically optional; only used to look for
            the end of the timestamp chain in the previous revision when
            producing a PAdES-LTA signature in a document that is already
            signed (to ensure that the timestamp chain is uninterrupted).
        :return:
            A :class:`PreSignValidationStatus` object, or ``None`` if there
            is no validation context available.
        NzkA signer's certificate must be provided if validation/revocation info is to be embedded into the signature.ziA validation context must be provided if validation/revocation info is to be embedded into the signature.zsValidation/revocation info will be embedded, but fetching is not allowed. This may give rise to unexpected results.)Zocsp_responsescrls)r   rG  rH  rA  rI  rJ  rK  )rP  r  r}   rz   r  r  r0   Zfetching_allowedr   r   "_perform_presign_signer_validationr   r   r{   r"  r!   _perform_prev_ts_validationr#  r   r   r   _perform_presign_ac_validationrR  r   rC   Zformat_revinfoocspsrT  rO   )rh   r   rP  r   r  r}   rG  Zprev_tsa_pathr   Zasync_ts_pathsZts_pathsZts_pathZasync_aa_pathsZaa_pathsaa_pathZrevinfor^   r^   r_   r6    s     

  





z,PdfSigningSession.perform_presign_validation)r}   c                   sv   | j j t j}| j jj}|d k	r<|jd k	r<||jj  fdd|D }t	
|D ]}|I d H }|jV  qZd S )Nc                    s   g | ]}t | jd qS ))Zholder_cert)r   r  ).0acr  r}   r^   r_   
<listcomp>6  s     zDPdfSigningSession._perform_presign_ac_validation.<locals>.<listcomp>)rP  r  rM  Zattribute_certsr  r   Zsigner_attributesextendZcertified_attrsr   Zas_completedrY  )rh   r}   Z
attr_certsZcades_attr_specZac_jobsZac_jobr   r^   r\  r_   rW  (  s    


z0PdfSigningSession._perform_presign_ac_validationc              
      sd   | j j}t|j|j|d}z||I d H }W n0 ttfk
r^ } ztd|W 5 d }~X Y nX |S )NZintermediate_certsr}   z/The signer's certificate could not be validated)	rP  r  r   r  cert_registryasync_validate_usager   r   r0   )rh   r}   Z	key_usager  Z	validatorZsigner_cert_validation_pathr  r^   r^   r_   rU  @  s"    z4PdfSigningSession._perform_presign_signer_validationc           
   
      s   | j j}ddlm} d }zt||}W n tk
r<   Y nX d }|d k	rt|j|j|d}z |j	t
 dhd}|I d H }W n0 ttfk
r }	 ztd|	W 5 d }	~	X Y nX |S )Nr   )r   r_  Ztime_stamping)Zextended_key_usageznRequested a PAdES-LTA signature on an existing document, but the most recent timestamp could not be validated.)rP  r  r
  r   r   r   r   Zsigner_certr`  ra  setr   r   r0   )
rh   r}   Zprev_readerr  r   Zlast_tsZlast_ts_validation_pathZts_validatorZvalidate_coror  r^   r^   r_   rV  U  s4     z-PdfSigningSession._perform_prev_ts_validationrl   c              
   C   s  | j }| j}| jj}|d k	r`tjtjgtjtj	tj
gi}||jg }|d k	o\t|jtj@ }ng }d}d  }}|r||d nd }	zB|d }t|}|d }
t|
}	|r|	|krtd|	 dW n@ tk
r   Y n. tk
r } ztd|W 5 d }~X Y nX |j}|j}|d k	r~|s*|	d k	r~|rD||krD|d }	n|	d krR|nt|	|}	|	|kr~td| d	|	 d
 |s|	d k	r|d krttdtdtdt i |d< }t|	j |d< t!|||	| j"dS )NFr   z/Lockz/PzWInconsistency in form field data. The field lock dictionary imposes the DocMDP policy 'zE', but the seed value dictionary's /LockDocument does not allow that.zFailed to read /Lock dictionaryzDocMDP policy 'zO', was requested, but the signature field settings do not allow that. Setting 'z
' instead.z/Actionz/Includez/Fields)rx   Z
field_lockdocmdp_permsrp   )#r  r  rP  r  r)   ZLOCKr(   r  ZDO_NOT_LOCKr   ZANNOTATEr  Zlock_documentr\   flagsr-   ZLOCK_DOCUMENTr&   r  r0   KeyErrorr  r~   rx   minr   r   r   rO  r    ZArrayObjectZNumberObjectvaluer<   rp   )rh   r  r  r  Zsv_lock_lutZsv_lock_valuesZsv_lock_value_reqlockZ	lock_dictrc  Zdocmdp_valuer  Z
meta_permsZmeta_certifyr^   r^   r_   _apply_locking_rulesv  s    
  







  z&PdfSigningSession._apply_locking_rules)r   c                 C   s  | j }| j}|j}|d k	st|j}|jd k	rT|jjd krBtd|j	|jj| |j
d k	r|j
 }||jkrdd }td|| d||j d|j
j}|r||jkrtd| d|j d	|s|S |j}	|tj@ r.|jd k	r.|jstd
|jd }
|	d k	r.|
|	kr.td|
j|	jf |	d krN|jd k	rN|jd }	|tj@ rx|jd k	rxtd|j d|tj@ r|jd k	r|j|jkrtd|jrdnd |jr|	tjkrtdtjj |tj@ r.|jd k	r.|j}|d k	r.| }||jkr.td|d |jf |tj!@ r|j"}| pP|dgk}|j#}|rp|d k	rptd|s|r||krtd|d dd |D f d S )NzZCannot verify seed value constraints on the signer's certificate since it is not availablec                 S   s   | rdS dS )Nza certificationzan approvalr^   )rx   r^   r^   r_   _type  s    z@PdfSigningSession._enforce_seed_value_constraints.<locals>._typezPThe seed value dictionary's /MDP entry specifies that this field should contain z signature, but z was requested.zaThe seed value dictionary specified that this certification signature should use the MDP policy 'z', but 'z' was requested.zPThe signature encodings mandated by the seed value dictionary are not supported.r   zJThe seed value dictionary mandates subfilter '%s', but '%s' was requested.zqpyHanko does not define any named appearances, but the seed value dictionary requires that the named appearance 'z
' be used.zoThe seed value dict mandates that revocation info %sbe added; adjust PdfSignatureMetadata settings accordingly.r   znot zdThe seed value dict mandates that Adobe-style revocation info be added; this requires subfilter '%s'zdThe selected message digest %s is not allowed by the seed value dictionary. Please select one of %s.z, .z@The seed value dictionary prohibits giving a reason for signing.zVReason "%s" is not a valid reason for signing, please choose one of the following: %s.c                 s   s   | ]}d | V  qdS )z"%s"Nr^   )rZ  sr^   r^   r_   	<genexpr>Z  s     zDPdfSigningSession._enforce_seed_value_constraints.<locals>.<genexpr>)$r  rP  r  r   rd  r  r  r  r0   satisfied_byZseed_signature_typeZcertification_signaturerx   Zmdp_permr~   ry   r-   Z	SUBFILTERr%  NotImplementedErrorrg  ZAPPEARANCE_FILTERZ
appearanceZADD_REV_INFOZadd_rev_inforz   r,   r&  ZDIGEST_METHODr  r  lowerjoinZREASONSreasonsrr   )rh   r   r  rP  r  rd  Z
sv_certifyrj  Zsv_mdp_permZselected_sfZmandated_sfZselected_mdrr  Z	must_omitZreason_givenr^   r^   r_   _enforce_seed_value_constraints  s    
 






z1PdfSigningSession._enforce_seed_value_constraintsF)r2  c                    s   | j }| jj}| jj}|jd kr(tdt|}t|	 }t
| j|d krPd n|j|jd}|j||| jd| j|dI d H }	t|	 d }
|r|
}n|
d|
d   }|S )NzAutomatic signature size estimation is not available without a signer's certificate. Space must be allocated manually using bytes_reserved=...r@  T)rR  r   r   signed_attr_settingsrS   r   )rp   rP  r  r  r  r0   r3   r   r   r   rB   rE  rA  r   
async_signrR  r   r   r   )rh   r2  r3  rp   r  r  Zmd_specZtest_mdsigned_attrsZtest_signature_cmsr   r   r^   r^   r_   r7  ^  s:    
	z3PdfSigningSession.estimate_signature_container_sizerM   )r2  rm   c                 C   s  | j }| j j}| jdk	r0| |dkr(dn|j |j}|j}|j}| jr|dk	r|	  |j
tjkrddlm}	 | j}
|	jj|
d|j|j|j|d | j}|  }| j}|j}t|j|p|j||d}t|| j||r|nd|j|j|j |j!|j"|j#d
}| j$%t&|||d}|j}| jj'}|dk	rN|j(rNt)| j| t*| j+|| j, |j}|j-}d }}| jr|j.r|dkrt/d|j0r| j,}d}|dk	r|1 }|dk	r|2 }t3||||j4|j|j5||d	}t6| j$||| j,| j||d
S )aM  
        Set up the signature appearance (if necessary) and signature dictionary
        in the PDF file, to put the document in its final pre-signing state.

        :param validation_info:
            Validation information collected prior to signing.
        :param bytes_reserved:
            Bytes to reserve for the signature container.
        :param appearance_text_params:
            Optional text parameters for the signature appearance content.
        :return:
            A :class:`.PdfTBSDocument` describing the document in its final
            pre-signing state.
        Nr   r   )r   r   rX  rT  r   )stylert   	timestampZtext_params)
r   ry   rx  rt   rq   rr   rs   rv   rw   ru   )r   Z	mdp_setupZappearance_setupz>Requested embedding of validation info, but none was collected)r2  timestamp_md_algorithmr   r|   r   r   r   r   r   r  rp   r   rR  post_sign_instructionsr}   )7rP  r  r  rs  rG  r  r   r   rR  ri   rj   rI   rb   r   r   r   r   r   r   rI  rJ  rp   ri  rE  rt   r:   r  Zsubject_namerA   ry   rq   rr   rs   rv   rw   ru   r   r   r=   r   r   r   PdfMacAttrProviderSpecinstallr   r}   rz   r0   r{   r   r   rP   r|   r   rM   )rh   r2  r   r)  rP  r  r  r   r   r   r   rp   Zsig_mdp_setuprE  Zname_specifiedZsig_appearanceZsig_objr   r   r}   Zpost_signing_instrZdoc_timestamperr   r   r^   r^   r_   r8    s    
	

 


z&PdfSigningSession.prepare_tbs_document)NN)N)F)N)rX   rY   rZ   r[   rK   r#   r   r
   r5   r,   r   r.   r   rO   r6  r   rW  rU  rV  r<   ri  r   rs  r7  r8  r^   r^   r^   r_   rL     sD      q!e  4 c                   @   s   e Zd ZU dZeed< dZee ed< dZ	ee
 ed< dZee
 ed< e Zeed< dZeed	< d
Zeed< dZee ed< dS )rP   z
    .. versionadded:: 0.7.0

    Container class housing instructions for incremental updates
    to the document after the signature has been put in place.
    Necessary for PAdES-LT and PAdES-LTA workflows.
    r2  Nr   ry  r|   r   Fr   Tr   r   )rX   rY   rZ   r[   rO   r]   r   r
   r5   ry  r   r|   rF   r   r   r\   r   r   rR   r^   r^   r^   r_   rP   !	  s   
c                   @   s,   e Zd ZdZeeddddZd
ddZd	S )PdfMacAttrProviderr   zpdfmac.PdfMacTokenHandlerr   r   r   c                C   s   || _ || _|| _d S r   r  )rh   r   r   r   r^   r^   r_   r   t	  s    zPdfMacAttrProvider.__init__Fc                    s   | j j| j| j|dS )Nr   )r   r   r   r   )rh   r   r^   r^   r_   build_attr_value	  s
    z#PdfMacAttrProvider.build_attr_valueN)F)rX   rY   rZ   Zattribute_typebytesr   r  r^   r^   r^   r_   r~  q	  s   r~  c                   @   s\   e Zd ZdZdeee dddZeee	 dddZ
d	d
 Zeejeee dddZdS )r|  zF
    Internal handler to deal with signatures under ISO/TS 32004.
    N)r   r   c                 C   s"   || _ || _d | _d | _d | _d S r   )r   r   wrapped_orig_target)rh   r   r   r^   r^   r_   r   	  s
    zPdfMacAttrProviderSpec.__init__)r  r   c                 C   s2   | j dkst|| _|j| _ ||| _| |_dS )a  
        Install the provider on a signer.

        NOTE: this is a stateful operation and won't work
        if the signer is shared, but we have a safeguard in place
        for that (will fail during size estimation under normal
        circumstances).
        N)r  r   r  unsigned_attr_prov_specZ_unsigned_attr_provider_specr  )rh   r  r   r^   r^   r_   r}  	  s
    zPdfMacAttrProviderSpec.installc                 C   s   | j | j_dS )zE
        Remove the provider from its target (internal API).
        N)r  r  r  rg   r^   r^   r_   	uninstall	  s    z PdfMacAttrProviderSpec.uninstall)r   rv  digest_algorithmrm   c           	      c   s   | j d k	std| j |||}|D ]}t|tr<td|V  q&tt|}|	| |
 }| j}|szt|dj}|d k	stt||| j|dV  d S )Nz$Unsigned attr provider not installeda  Other PDF MAC attribute provider found. This may be the result of signer instances being shared across multiple documents. This workflow is not supported for encrypted documents. Either turn off MAC generation, or use separate signer instances for different documents.Zmessage_digestr  )r  r   unsigned_attr_providersr"  r~  r0   r   r   r3   r   r   r   r1   r   r   r   )	rh   r   rv  r  Zother_provsZprovr   r   r   r^   r^   r_   r  	  s6      

 
z.PdfMacAttrProviderSpec.unsigned_attr_providers)N)rX   rY   rZ   r[   r#   r
   r  r   rC   r5   r}  r  r   r   r   r   rT   r  r^   r^   r^   r_   r|  	  s    r|  c                	   @   s  e Zd ZdZdeeeee ee	 ee
 dddZddejdee eeeef dd	d
ZeeddddZedeeeeejf ee	 ee
 ddddZeddejfeeeeejf ee	 ee
 dddZeddejfeeeeejf ee	 ee
 dddZdS )rM   a  
    .. versionadded:: 0.7.0

    A PDF document in its final pre-signing state.

    The ``__init__`` method is internal API, get an instance using
    :meth:`.PdfSigningSession.prepare_tbs_document`. Alternatively, use
    :meth:`resume_signing` or :meth:`finish_signing` to continue a previously
    interrupted signing process without instantiating a new
    :class:`.PdfTBSDocument` object.
    N)r  rp   rR  r   r{  r}   c                 C   s.   || _ || _|| _|| _|| _|| _|| _d S r   rz  )rh   r   r  rp   rR  r   r{  r}   r^   r^   r_   r   	  s    
zPdfTBSDocument.__init__F)r   r   r   )r   r   rm   c                C   s   | j t| j|||dS )a  
        Write the document to an output stream and compute the digest, while
        keeping track of the (future) location of the signature contents in the
        output stream.

        The digest can then be passed to the next part of the signing pipeline.

        .. warning::
            This method can only be called once.

        :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:
            Size of the internal buffer (in bytes) used to feed data to the
            message digest function if the input stream does not support
            ``memoryview``.
        :return:
            A tuple containing a :class:`.PreparedByteRangeDigest` and the
            output stream to which the output was written.
        )rp   r   r   r   )r   r   r;   rp   )rh   r   r   r   r^   r^   r_   r9  	  s    "z"PdfTBSDocument.digest_tbs_documentrN   )r   rB  rm   c                    sZ   | j }|j|| j| j| j|dI dH }| j|}t|jt	rH|j
  t|| j| jdS )ay  
        Perform the relevant cryptographic signing operations on the document
        digest, and write the resulting CMS object to the appropriate location
        in the output stream.

        .. warning::
            This method can only be called once, and must be invoked after
            :meth:`digest_tbs_document`.

        :param document_digest:
            Digest of the document, as computed over the relevant
            ``/ByteRange``.
        :param pdf_cms_signed_attrs:
            Description of the signed attributes to include.
        :return:
            A :class:`.PdfPostSignatureDocument` object.
        )rR  r   rt  Npost_sign_instrr}   )r  ru  rp   rR  r   r   r   r"  r  r|  r  rN   r{  r}   )rh   r   rB  r  signature_cmsr   r^   r^   r_   rD  %
  s     
z PdfTBSDocument.perform_signature)r   prepared_digestr  r  r}   rm   c                 C   s   | ||}t|||dS )av  
        Resume signing after obtaining a CMS object from an external source.

        This is a class method; it doesn't require a :class:`.PdfTBSDocument`
        instance. Contrast with :meth:`perform_signature`.

        :param output:
            Output stream housing the document in its final pre-signing state.
            This stream must at least be writable and seekable, and also
            readable if post-signature processing is required.
        :param prepared_digest:
            The prepared digest returned by a prior call to
            :meth:`digest_tbs_document`.
        :param signature_cms:
            CMS object to embed in the signature dictionary.
        :param post_sign_instr:
            Instructions for post-signing processing (DSS updates and document
            timestamps).
        :param validation_context:
            Validation context to use in post-signing operations.
            This is mainly intended for TSA certificate validation, but it can
            also contain additional validation data to embed in the DSS.
        :return:
            A :class:`PdfPostSignatureDocument`.
        r  )Zfill_with_cmsrN   )clsr   r  r  r  r}   r   r^   r^   r_   resume_signingO
  s    #zPdfTBSDocument.resume_signing)r   r  r  r  r}   c              
   C   s    t | j||||||d dS )  
        Finish signing after obtaining a CMS object from an external source, and
        perform any required post-signature processing.

        This is a class method; it doesn't require a :class:`.PdfTBSDocument`
        instance. Contrast with :meth:`perform_signature`.

        :param output:
            Output stream housing the document in its final pre-signing state.
        :param prepared_digest:
            The prepared digest returned by a prior call to
            :meth:`digest_tbs_document`.
        :param signature_cms:
            CMS object to embed in the signature dictionary.
        :param post_sign_instr:
            Instructions for post-signing processing (DSS updates and document
            timestamps).
        :param validation_context:
            Validation context to use in post-signing operations.
            This is mainly intended for TSA certificate validation, but it can
            also contain additional validation data to embed in the DSS.
        :param chunk_size:
            Size of the internal buffer (in bytes) used to feed data to the
            message digest function if the input stream does not support
            ``memoryview``.
        )r  r}   r   N)r   r   async_finish_signing)r  r   r  r  r  r}   r   r^   r^   r_   finish_signingy
  s    $zPdfTBSDocument.finish_signingc           	         s6   t |}| j|||||d}|j||dI dH  dS )r  )r  r  r  r}   rC  N)r   r   r  rF  )	r  r   r  r  r  r}   r   Z	rw_outputZ	post_signr^   r^   r_   r  
  s    '
 z#PdfTBSDocument.async_finish_signing)NNN)NN)rX   rY   rZ   r[   rC   r   r\   r
   r5   rP   r   r   r   r   r   r   r@   r9  r  rB   rD  classmethodr   r   ZContentInfor  r  r  r^   r^   r^   r_   rM   	  sr      
-*  ).c                   @   s@   e Zd ZdZd	eee ee dddZe	j
fedddZdS )
rN   z\
    .. versionadded:: 0.7.0

    Represents the final phase of the PDF signing process
    N)r   r  r}   c                 C   s   || _ || _|| _d S r   )r   r{  r}   )rh   r   r  r}   r^   r^   r_   r   
  s    z!PdfPostSignatureDocument.__init__)r   c                    s`  | j }|dkrdS | j}|j}|j}ddlm} t|j||j|j	|j
d}|jr\| j|d< nd|d< |j}	|j}
d}|
tjkrd}n|
tjkr|	dk}|r|jsd|d< |jjf d	|i|d
|ji |	dk	r\t|}|jdk	r|jdk	r|j|j t|	|jd}|
tjkr$|jj|f| |j||jp6tj||jd|	||  |j!|j
d
I dH  dS )aN  
        Handle DSS updates and LTA timestamps, if applicable.

        :param output:
            I/O buffer containing the signed document. Must support
            reading, writing and seeking.
        :param chunk_size:
            Chunk size to use for I/O operations that do not support the buffer
            protocol.
        Nr   r   )r   r}   rX  rT  r   r   FTr   r   r   )ro   )r   r   r   r   r   r   r   )"r{  r}   r2  r   r   r   dictr   rI  rJ  r   rV   r   r   rj   rI   rc   rd   rW   r   r   r   r!   r   ZauthenticaterJ   r|   r   r   ry  r8   r   rn   r   )rh   r   r   instrr}   r2  r   r   Zdss_op_kwargsr   Zdss_placementZseparate_dss_revisionwZpdf_timestamperr^   r^   r_   rF  
  s~    



 z2PdfPostSignatureDocument.post_signature_processing)NN)rX   rY   rZ   r[   r  r
   rP   r   r   r   r   r   rF  r^   r^   r^   r_   rN   
  s   	  )F)r[   r   r`   loggingr   r+  Zdataclassesr   r   r   typingr   r   r   r   r	   r
   r   r   r   rS  Z
asn1cryptor   r   r   r   r   r   rL  Zasn1crypto.corer   Zcryptography.hazmat.primitivesr   Zpyhanko_certvalidatorr   r   Zpyhanko_certvalidator.errorsr   r   Zpyhanko_certvalidator.pathr   Zpyhanko_certvalidator.validater   r   Zpyhanko.pdf_utilsr   r   Zpyhanko.pdf_utils.cryptr   Zpyhanko.pdf_utils.genericr    Z$pyhanko.pdf_utils.incremental_writerr!   Zpyhanko.pdf_utils.readerr"   Zpyhanko.pdf_utils.writerr#   r   r$   Zpyhanko.sign.ades.apir%   Zpyhanko.sign.fieldsr&   r'   r(   r)   r*   r+   r,   r-   r.   r/   Zpyhanko.sign.generalr0   r1   r2   r3   r4   Zpyhanko.sign.timestampsr5   Zpyhanko.stampr6   r   r8   Zcms_embedderr9   r:   r;   r<   r=   Zpdf_byteranger>   r?   r@   rA   Zpdf_cmsrB   rC   rD   __all__Zpdf_utils.cryptrR   rT   	getLoggerrX   r   rH   EnumrI   rG   rF   rE   r   r   Z
SignedDatar  r   r   r   ZPublicKeyInfor   rJ   r  rK   rO   ZIndirectObjectr   rL   rP   r~  ZUnsignedAttributeProviderSpecr|  rM   rN   r^   r^   r^   r_   <module>   s   ,0
"0!@ I ,   \    [/      OT  