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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mZmZmZ d d
lmZmZmZmZmZm Z  d dl!m"Z"m#Z#m$Z$m%Z% d dl&m'Z' d dl(m)Z) ddl*m+Z+m,Z,m-Z- ddl.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6 ddl7m8Z8 ddl9m:Z:m;Z;m<Z< ddl=m>Z> g dZ?e @eAZBdeejC fddZDdee fddZEdejCdeFfddZGG dd dZHedd d!gZI	 d"edeeI fd#d$ZJd%eHfd&d'ZKd(eHd)e)d*eLfd+d,ZMd-d. ZN						/	d<d(eHd0ee' d1ee' d2ee' d3ee d4ee8 d5eLd6ee> de;fd7d8ZO			/d=d(eHd9ee' d3ee d5eLde:f
d:d;ZPdS )>    N)
namedtuple)datetime)ListOptionalUnion)cmsx509)genericmisc)pdf_name)PdfFileReaderprocess_data_at_eof)DEFAULT_DIFF_POLICY
DiffPolicy
DiffResultModificationLevelSuspiciousModification)FieldMDPSpecMDPPermSeedLockDocumentSigSeedSubFilterSigSeedValFlagsSigSeedValueSpec)SignedDataCertsUnacceptableSignerErrorbyte_range_digestextract_signer_info)ValidationContext)ValidationPath   )SignatureValidationErrorSigSeedValueValidationErrorValidationInfoReadingError)cms_basic_validationcollect_signer_attr_statuscollect_timing_infocompute_signature_tst_digestextract_certs_for_validationextract_self_reported_tsextract_tst_datavalidate_tst_signed_data)KeyUsageConstraints)DocumentTimestampStatusPdfSignatureStatusSignatureCoverageLevel)CMSAlgorithmUsagePolicy)EmbeddedPdfSignature
DocMDPInforead_certification_dataasync_validate_pdf_signatureasync_validate_pdf_timestampreport_seed_value_validationextract_contentsreturnc                 C   sL   z| d }W n
 t y   Y d S w |D ]}| }|d |kr#|  S qd S )Nz
/Referencez/TransformMethod)KeyError
get_object)signature_objmethodsig_refsref r>   b/var/www/html/hyperkenya/venv/lib/python3.10/site-packages/pyhanko/sign/validation/pdf_embedded.py_extract_reference_dictI   s   r@   c              
   C   sV   t | d}|d u rd S z|d d}t|W S  ttfy* } ztd|d }~ww )N/DocMDP/TransformParams/Pz#Failed to read document permissions)r@   raw_getr   
ValueErrorr8   r    )r:   r=   	raw_permser>   r>   r?   _extract_docmdp_for_sigW   s   

rH   
sig_objectc                 C   sR   z| j dtjjd}W n ty   tdw t|tjtj	fs&td|j
S )z
    Internal function to extract the (DER-encoded) signature bytes from a PDF
    signature dictionary.

    :param sig_object:
        A signature dictionary.
    :return:
        The extracted contents as a byte string.
    z	/Contents)decryptz+Could not read /Contents entry in signaturez/Contents must be string-like)rD   r	   EncryptedObjAccessRAWr8   r
   PdfReadError
isinstanceTextStringObjectByteStringObjectoriginal_bytes)rI   cms_contentr>   r>   r?   r6   d   s   


r6   c                   @   s  e Zd ZU dZejed< 	 ejed< 	 ejed< 	 de	dejde
fddZd	efd
dZed	eej fddZed	eej fddZed	ejfddZed	ejfddZedd Zed	ee fddZed	eej fddZd1ddZd	efddZed	ee  fd d!Z!ed	ee" fd"d#Z#ed	ee$ fd$d%Z%d	e&fd&d'Z'd	ee& fd(d)Z(d	e)fd*d+Z*d,d- Z+d.e,d	e-e.e/f fd/d0Z0dS )2r0   zA
    Class modelling a signature embedded in a PDF document.
    	sig_fieldrI   signed_datareaderfq_namec                 C   sf  || _ t|tjr| }|| _|d}|  | _}t|tjs$J z|d| _	W n t
y8   tdw t| | _}tj|}|d }|| _t|| _d | _| jd }	|	d j | _|d }
|
d j}|d	krt| j| _n|d
kr|
d jd }|d d j| _| j j|j| _d | _d | _ d | _!d | _"d | _#d | _$| _%d | _&d | _'d| _(|| _)d S )Nz/Vz
/ByteRangez,Could not read /ByteRange entry in signaturecontentdigest_algorithm	algorithmencap_content_infocontent_typedatatst_infomessage_imprinthash_algorithmF)*rU   rN   r	   IndirectObjectr9   rS   rD   rI   DictionaryObject
byte_ranger8   r
   rM   r6   pkcs7_contentr   ContentInfoloadrT   r   signer_info_sd_cert_infonativelowermd_algorithmexternal_md_algorithmparsedxrefsget_last_change	referencesigned_revisioncoverageexternal_digest	total_len_docmdp	_fieldmdp_docmdp_queried_fieldmdp_queriedtst_signature_digestdiff_result_integrity_checkedrV   )selfrU   rS   rV   sig_object_refrI   rR   messagerT   digest_algoecir[   mir>   r>   r?   __init__   s\   





zEmbeddedPdfSignature.__init__r7   c                 C   s   | j d u rt| j| _ | j S )N)rg   r'   rT   r{   r>   r>   r?   _init_cert_info   s   
z$EmbeddedPdfSignature._init_cert_infoc                 C      t |  jS )z2
        Embedded attribute certificates.
        )listr   attribute_certsr   r>   r>   r?   embedded_attr_certs      z(EmbeddedPdfSignature.embedded_attr_certsc                 C   r   )zQ
        Embedded X.509 certificates, excluding than that of the signer.
        )r   r   other_certsr   r>   r>   r?   other_embedded_certs   r   z)EmbeddedPdfSignature.other_embedded_certsc                 C   s
   |   jS )z,
        Certificate of the signer.
        )r   signer_certr   r>   r>   r?   r      s   
z EmbeddedPdfSignature.signer_certc                 C   s   | j dtdS )a  
        Returns the type of the embedded signature object.
        For ordinary signatures, this will be ``/Sig``.
        In the case of a document timestamp, ``/DocTimeStamp`` is returned.

        :return:
            A PDF name object describing the type of signature.
        z/Type/Sig)rI   getr   r   r>   r>   r?   sig_object_type   s   
z$EmbeddedPdfSignature.sig_object_typec                 C   s   | j S )zC
        :return:
            Name of the signature field.
        )rV   r   r>   r>   r?   
field_name  s   zEmbeddedPdfSignature.field_namec                 C   sJ   t | j}|dur|S z| jd }tj|| jjdW S  ty$   Y dS w )z
        :return:
            The signing time as reported by the signer, if embedded in the
            signature's signed attributes or provided as part of the signature
            object in the PDF document.
        Nz/M)strict)r(   rf   rI   r	   parse_pdf_daterU   r   r8   )r{   tsst_as_pdf_dater>   r>   r?   self_reported_timestamp  s   

z,EmbeddedPdfSignature.self_reported_timestampc                 C   s
   t | jS )z
        :return:
            The signed data component of the timestamp token embedded in this
            signature, if present.
        )r)   rf   r   r>   r>   r?   attached_timestamp_data"  s   
z,EmbeddedPdfSignature.attached_timestamp_dataNFc                 C   sD   |    |   |   |  | _|pt}|s| || _d| _dS )a  
        Compute the various integrity indicators of this signature.

        :param diff_policy:
            Policy to evaluate potential incremental updates that were appended
            to the signed revision of the document.
            Defaults to
            :const:`~pyhanko.sign.diff_analysis.DEFAULT_DIFF_POLICY`.
        :param skip_diff:
            If ``True``, skip the difference analysis step entirely.
        TN)	_enforce_hybrid_xref_policycompute_digestcompute_tst_digestevaluate_signature_coveragerq   r   evaluate_modificationsry   rz   )r{   diff_policy	skip_diffr>   r>   r?   compute_integrity_info+  s   

z+EmbeddedPdfSignature.compute_integrity_infoc                 C   s   | j std| j}| j}| j}d}|dur2t|tr|jntj	}|tj	kp/|duo/|j
|j
k }n
|tjkr<|tjk}|||d}|S )a  
        Compile the integrity information for this signature into a dictionary
        that can later be passed to :class:`.PdfSignatureStatus` as kwargs.

        This method is only available after calling
        :meth:`.EmbeddedPdfSignature.compute_integrity_info`.
        zGCall compute_integrity_info() before invokingsummarise_integrity_info()N)rq   	docmdp_okry   )rz   r    docmdp_levelry   rq   rN   r   modification_levelr   OTHERvaluer.   ENTIRE_REVISIONENTIRE_FILE)r{   docmdpry   rq   r   	mod_levelstatus_kwargsr>   r>   r?   summarise_integrity_infoD  s.   	


z-EmbeddedPdfSignature.summarise_integrity_infoc                 C   s.   z| j d }W n
 ty   Y d S w t|S )Nz/SV)rS   r8   r   from_pdf_object)r{   sig_sv_dictr>   r>   r?   seed_value_specq  s   
z$EmbeddedPdfSignature.seed_value_specc                 C   s^   | j r| jS t| jd}|du r'z| jd }t|d }W n	 ty&   Y nw || _d| _ |S )av  
        :return:
            The document modification policy required by this signature or
            its Lock dictionary.

            .. warning::
                This does not take into account the DocMDP requirements of
                earlier signatures (if present).

                The specification forbids signing with a more lenient DocMDP
                than the one currently in force, so this should not happen
                in a compliant document.
                That being said, any potential violations will still invalidate
                the earlier signature with the stricter DocMDP policy.

        )r:   Nz/LockrC   T)rv   rt   rH   rI   rS   r   r8   )r{   r   	lock_dictr>   r>   r?   r   y  s   
z!EmbeddedPdfSignature.docmdp_levelc              
   C   sn   | j r| jS t| jd}d| _ |du rdS z	t|d }W n ttfy1 } ztd|d}~ww || _|S )z
        :return:
            Read the field locking policy of this signature, if applicable.
            See also :class:`~.pyhanko.sign.fields.FieldMDPSpec`.
        z	/FieldMDPTNrB   z!Failed to read /FieldMDP settings)	rw   ru   r@   rI   r   r   rE   r8   r    )r{   ref_dictsprG   r>   r>   r?   fieldmdp  s$   zEmbeddedPdfSignature.fieldmdpc                 C   s6   | j dur| j S t| jj| j| jd\| _}|| _ |S )z
        Compute the ``/ByteRange`` digest of this signature.
        The result will be cached.

        :return:
            The digest value.
        N)rb   rj   )rr   r   rU   streamrb   rk   rs   r{   digestr>   r>   r?   r     s   
z#EmbeddedPdfSignature.compute_digestc                 C   s$   | j dur| j S t| j | _ }|S )a  
        Compute the digest of the signature needed to validate its timestamp
        token (if present).

        .. warning::
            This computation is only relevant for timestamp tokens embedded
            inside a regular signature.
            If the signature in question is a document timestamp (where the
            entire signature object is a timestamp token), this method
            does not apply.

        :return:
            The digest value, or ``None`` if there is no timestamp token.
        N)rx   r&   rf   r   r>   r>   r?   r     s   

z'EmbeddedPdfSignature.compute_tst_digestc                 C   s   | j j}| j j}t| jdks| jd dkrtjS | j\}}}}|dtj	 t| j
d d }|| | }| |k}	|	rAtjS ||| k}
|
sLtjS || | j}zt|}||}||krftjW S W n tjyt   tj Y S w t|d D ]}||}|j|krtj  S q{tjS )z
        Internal method used to evaluate the coverage level of a signature.

        :return:
            The coverage level of the signature.
           r      r   )rU   rm   r   lenrb   r.   UNCLEARseekosSEEK_ENDrc   tellr   rp   r   get_startxref_for_revisionCONTIGUOUS_BLOCK_FROM_STARTr
   rM   rangeget_xref_container_infoend_locationr   )r{   
xref_cacher   _len1start2len2embedded_sig_contentsigned_zone_lenfile_covered
contiguous
signed_rev	startxrefexpectedrevision	xref_metar>   r>   r?   r     s>   







z0EmbeddedPdfSignature.evaluate_signature_coveragec                 C   s$   | j }|jr|jjrtdd S d S )NzJSettings do not permit validation of signatures in hybrid-reference files.)rU   r   rm   hybrid_xrefs_presentr    )r{   rU   r>   r>   r?   r   "  s   z0EmbeddedPdfSignature._enforce_hybrid_xref_policyr   c                 C   sH   | j tjk r
tdS | j tjkrttjt S |j	| j
| j| j| jdS )zY
        Internal method used to evaluate the modification level of a signature.
        z$Nonstandard signature coverage level)field_mdp_specdoc_mdp)rq   r.   r   r   r   r   r   NONEsetreview_filerU   rp   r   r   )r{   r   r>   r>   r?   r   *  s   z+EmbeddedPdfSignature.evaluate_modifications)NF)1__name__
__module____qualname____doc__r	   ra   __annotations__r   
SignedDatar   strr   r   r   propertyr   AttributeCertificateV2r   r   Certificater   r   
NameObjectr   r   r   r   r   r   r   dictr   r   r   r   r   r   r   bytesr   r   r.   r   r   r   r   r   r   r   r>   r>   r>   r?   r0      s^   
 



L

-H
r0   r1   
permission
author_sigrU   c                 C   s:   z	| j d d }W n
 ty   Y dS w t|}t||S )z
    Read the certification information for a PDF document, if present.

    :param reader:
        Reader representing the input document.
    :return:
        A :class:`.DocMDPInfo` object containing the relevant data, or ``None``.
    /PermsrA   N)rootr8   rH   r1   )rU   certification_sigpermr>   r>   r?   r2   G  s   	
r2   emb_sigc              
   C   s  | j }|d u r	d S | j}|jd ur,z	|j|| W n ty+ } zt||d }~ww |s5|jr5td| j}|jd ur|j	 }z| j
jd }|d}	|	|jk}
W n ttjtfyc   d}
Y nw ||
kr{dd }td|| d||
 d	|r|jj}| j}||krtd
| d| d|j}|sd S |d }t|}|tj@ r|jd ur|jstd|jd }|d ur||krtd|j|jf |tj@ r|jd urtd |tj@ r|j d urtd|tj!@ r|j"d ur| j}|j"t#j$kr|t%j&krtd|j"t#j'kr|t%j&krtd| j(}|tj)@ rp|j*d urpddl+m,} z|| d}W n t-yA   d}Y nw |j*|kr^td|j*rPdnd|rYdf df |j*rp|tj.krptdtj.j |tj/@ r|j0d ur| j12 }||j0vrtd| |tj3@ r|j4pg }| p|dgk}|5d}|r|d urtd|s||vrtd|f d S d S d S ) NznThe seed value dictionary requires a trusted timestamp, but none was found, or the timestamp did not validate.r   rA   Fc                 S   s   | rdS dS )Nza certificationzan approvalr>   )certifyr>   r>   r?   _typex  s   z'_validate_sv_constraints.<locals>._typezPThe seed value dictionary's /MDP entry specifies that this field should contain z signature, but z appears to have been used.zaThe seed value dictionary specified that this certification signature should use the MDP policy 'z', but 'z' was used in the signature.
/SubFilterzPThe signature encodings mandated by the seed value dictionary are not supported.r   zVThe seed value dictionary mandates subfilter '%s', but '%s' was used in the signature.zThe signature's seed value dictionary specifies the /AppearanceFilter entry as mandatory, but this constraint is impossible to validate.zpyHanko does not support legal attestations, but the seed value dictionary mandates that they be restricted to a specific subset.z<Document must be locked, but some changes are still allowed.zGDocument must not be locked, but the DocMDP level is set to NO_CHANGES.)retrieve_adobe_revocation_infoTzbThe seed value dict mandates that revocation info %sbe added, but it was %sfound in the signature. znot zdThe seed value dict mandates that Adobe-style revocation info be added; this requires subfilter '%s'zKThe selected message digest %s is not allowed by the seed value dictionary..z/Reasonz@The seed value dictionary prohibits giving a reason for signing.zIThe reason for signing "%s" is not accepted by the seed value dictionary.)6r   r   certsatisfied_byr   r!   timestamp_requiredrI   seed_signature_typecertification_signaturerU   r   get_value_as_referencecontainer_refr8   r	   IndirectObjectExpectedAttributeErrormdp_permr   flagsr   r   	SUBFILTER
subfiltersNotImplementedErrorr   APPEARANCE_FILTER
appearanceloggerwarningLEGAL_ATTESTATIONlegal_attestationsLOCK_DOCUMENTlock_documentr   LOCKr   
NO_CHANGESDO_NOT_LOCKrf   ADD_REV_INFOadd_rev_infopyhanko.sign.validation.ltvr   r"   ADOBE_PKCS7_DETACHEDDIGEST_METHODdigest_methodsrj   ri   REASONSreasonsr   )r   validation_pathtimestamp_foundsv_specsigning_certrG   sig_obj
sv_certifypermscert_sig_refwas_certifiedr   sv_mdp_permr   r   selected_sf_strselected_sfmandated_sfrf   r   revinfo_foundselected_mdr  	must_omitreason_givenr>   r>   r?   _validate_sv_constraintsY  s"  









	

r   embedded_sigr  r  c              
   C   s^   zt | ||d d}W n ty& } ztjd|d |}W Y d}~nd}~ww | jdu|dS )a  
    Internal API function to enforce seed value constraints (if present)
    and report on the result(s).

    :param embedded_sig:
        The embedded signature.
    :param validation_path:
        The validation path for the signer's certificate.
    :param timestamp_found:
        Flag indicating whether a valid timestamp was found or not.
    :return:
        A ``status_kwargs`` dict.
    )r  NzError in seed value validation.)exc_info)has_seed_valuesseed_value_constraint_error)r   r!   r   r   r   )r!  r  r  sv_errrG   r>   r>   r?   r5     s   r5   c                 C   sH   zddl m} || |v }W n ty   d}Y nw |s"t||  d S )Nr   )r   F)pyhanko.sign.fieldsr   rE   r    )subfilter_strpermitted_subfilterserr_msgr   subfilter_okr>   r>   r?   _validate_subfilter$  s   r+  Fsigner_validation_contextts_validation_contextac_validation_contextr   key_usage_settingsr   algorithm_policyc                    sJ  | j }| jdkrtd|dd}	t|	tjtjfd |du r#|}| j||d | 	 }
t
| j||  dI dH }|
| d|
vrO| j}|durO||
d< t|}t| j| j||
||d	I dH }
|
d
d}|duor|jor|j}t| |
d |}|
| |dur|j| j |
t| j| j|| jd dI dH  tdi |
S )a  
    .. versionadded:: 0.9.0

    .. versionchanged: 0.11.0
        Added ``ac_validation_context`` param.


    Validate a PDF signature.

    :param embedded_sig:
        Embedded signature to evaluate.
    :param signer_validation_context:
        Validation context to use to validate the signature's chain of trust.
    :param ts_validation_context:
        Validation context to use to validate the timestamp's chain of trust
        (defaults to ``signer_validation_context``).
    :param ac_validation_context:
        Validation context to use to validate attribute certificates.
        If not supplied, no AC validation will be performed.

        .. note::
            :rfc:`5755` requires attribute authority trust roots to be specified
            explicitly; hence why there's no default.
    :param diff_policy:
        Policy to evaluate potential incremental updates that were appended
        to the signed revision of the document.
        Defaults to
        :const:`~pyhanko.sign.diff_analysis.DEFAULT_DIFF_POLICY`.
    :param key_usage_settings:
        A :class:`.KeyUsageConstraints` object specifying which key usages
        must or must not be present in the signer's certificate.
    :param skip_diff:
        If ``True``, skip the difference analysis step entirely.
    :param algorithm_policy:
        The algorithm usage policy for the signature validation.

        .. warning::
            This is distinct from the algorithm usage policy used for
            certificate validation, but the latter will be used as a fallback
            if this parameter is not specified.

            It is nonetheless recommended to align both policies unless
            there is a clear reason to do otherwise.
    :return:
        The status of the PDF signature in question.
    r   z"Signature object type must be /Sigr   Nz4%s is not a recognized SubFilter type in signatures.r   r   )
raw_digestsigner_reported_dt)r2  validation_contextr   r/  r0  timestamp_validityr  signed_attrs)sd_attr_certificatesr   r4  sd_signed_attrsr>   )rI   r   r    r   r+  r   r
  PADESr   r   r%   rf   r   updater   r-   default_usage_constraintsr#   rT   rr   validtrustedr5   certificate_registryregister_multipler   r$   r   r   )r!  r,  r-  r.  r   r/  r   r0  rI   r'  r   ts_status_kwargsr3  tst_validityr  	sv_updater>   r>   r?   r3   0  sr   9





r3   r4  c                    sz   | j dkr
td| jdd}t|tjfd | j||d t| j	|| 
 I dH }| j|d< | j|d< td	i |S )
a{  
    .. versionadded:: 0.9.0

    Validate a PDF document timestamp.

    :param embedded_sig:
        Embedded signature to evaluate.
    :param validation_context:
        Validation context to use to validate the timestamp's chain of trust.
    :param diff_policy:
        Policy to evaluate potential incremental updates that were appended
        to the signed revision of the document.
        Defaults to
        :const:`~pyhanko.sign.diff_analysis.DEFAULT_DIFF_POLICY`.
    :param skip_diff:
        If ``True``, skip the difference analysis step entirely.
    :return:
        The status of the PDF timestamp in question.
    z/DocTimeStampz+Signature object type must be /DocTimeStampr   Nz5%s is not a recognized SubFilter type for timestamps.r1  rq   ry   r>   )r   r    rI   r   r+  r   ETSI_RFC3161r   r*   rT   r   rq   ry   r,   )r!  r4  r   r   r'  r   r>   r>   r?   r4     s,   



r4   )NNNNNFN)NNF)Qloggingr   collectionsr   r   typingr   r   r   
asn1cryptor   r   pyhanko.pdf_utilsr	   r
   pyhanko.pdf_utils.genericr   pyhanko.pdf_utils.readerr   r   pyhanko.sign.diff_analysisr   r   r   r   r   r&  r   r   r   r   r   r   pyhanko.sign.generalr   r   r   r   pyhanko_certvalidatorr   pyhanko_certvalidator.pathr   errorsr    r!   r"   generic_cmsr#   r$   r%   r&   r'   r(   r)   r*   settingsr+   statusr,   r-   r.   utilsr/   __all__	getLoggerr   r   ra   r@   rH   r   r6   r0   r1   r2   r   boolr5   r+  r3   r4   r>   r>   r>   r?   <module>   s     (


   C
 +
!	
}