U
    c\                  	   @   s  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
 d dl	mZ d dlmZ d dl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 ddlmZmZm Z  ddl!m"Z"m#Z#m$Z$m%Z% ddl&m'Z'm(Z( ddl)m*Z* ddl+m,Z,m-Z-m.Z. ddddddgZ/e 0e1Z2ede-dZ3G dd deZ4eej5ej5dZ6dd Z7eej8ej8dZ9d d! Z:d"d# Z;e
j<ee=d$d%dZ>eee' d&d'dZ?eG d(d) d)Z@e'd*d+d,ZAd-d. ZBd6e'e4ee ee ee* eCe,d0d1dZDe
jEd2d3dZFd7e
jEed4d5dZGdS )8    N)	dataclass)Enum)IteratorOptionalTypeVar)cms)pdf)ValidationContext)CertRevTrustPolicyRevocationCheckingPolicyRevocationCheckingRule)PdfFileReader   )
DiffPolicy)MultivaluedAttributeErrorNonexistentAttributeErrorfind_unique_cms_attribute   )DocumentSecurityStore)NoDSSFoundErrorSignatureValidationErrorValidationInfoReadingError)async_validate_cms_signaturecms_basic_validationcollect_signer_attr_statusvalidate_tst_signed_data)EmbeddedPdfSignaturereport_seed_value_validation)KeyUsageConstraints)PdfSignatureStatusSignatureStatusTimestampSignatureStatusRevocationInfoValidationTypeapply_adobe_revocation_inforetrieve_adobe_revocation_infoget_timestamp_chain async_validate_pdf_ltv_signatureestablish_timestamp_trust
StatusType)boundc                   @   s(   e Zd ZdZdZdZdZedd ZdS )r"   zP
    Indicates a validation profile to use when validating revocation info.
    adobeZpadesz	pades-ltac                 C   s   t dd | D S )Nc                 s   s   | ]}|j V  qd S )N)value).0m r.   ?/tmp/pip-unpacked-wheel-0kb_yl26/pyhanko/sign/validation/ltv.py	<genexpr>R   s     z8RevocationInfoValidationType.as_tuple.<locals>.<genexpr>)tuple)clsr.   r.   r/   as_tupleP   s    z%RevocationInfoValidationType.as_tupleN)	__name__
__module____qualname____doc__ADOBE_STYLEPADES_LT	PADES_LTAclassmethodr3   r.   r.   r.   r/   r"   8   s   )Zee_certificate_ruleZintermediate_ca_cert_rulec                  K   s   t f dti| S Nrevocation_checking_policy)r
   &DEFAULT_LTV_INTERNAL_REVO_CHECK_POLICYkwargsr.   r.   r/   !_default_ltv_internal_revo_policy[   s
    rA   c                  K   s   t f dti| S r<   )r
   %STRICT_LTV_INTERNAL_REVO_CHECK_POLICYr?   r.   r.   r/    _strict_ltv_internal_revo_policyh   s
    rC   c                 C   s   d|d< | |d< | dd }| dd}|d krl|dd }|rX|dkrXtt|}q~|dkr~t|d}n|jjs~t|d}||d< d S )	NFallow_fetchingmomentrevinfo_policyretroactive_revinforevocation_modez	soft-failrG   )	getpopr
   r   Zfrom_legacyrA   r=   Z	essentialrC   )	timestampvalidation_context_kwargsrF   retroactiveZ	legacy_rmr.   r.   r/   _strict_vc_context_kwargso   s(    
rO   )tst_signed_datavalidation_contextexpected_tst_imprintc                    sD   t | ||I dH }tf |}|jr(|js@td|  td|S )a  
    Wrapper around :func:`validate_tst_signed_data` for use when analysing
    timestamps for the purpose of establishing a timestamp chain.
    Its main purpose is throwing/logging an error if validation fails, since
    that amounts to lack of trust in the purported validation time.

    This is internal API.

    :param tst_signed_data:
        The ``SignedData`` value to validate; must encapsulate a ``TSTInfo``
        value.
    :param validation_context:
        The validation context to apply to the timestamp.
    :param expected_tst_imprint:
        The expected message imprint for the ``TSTInfo`` value.
    :return:
        A :class:`.TimestampSignatureStatus` if validation is successful.
    :raises:
        :class:`SignatureValidationError` if validation fails.
    Nz0Could not validate embedded timestamp token: %s.z\Could not establish time of signing, timestamp token did not validate with current settings.)r   r!   ZvalidZtrustedloggerwarningsummaryr   )rP   rQ   rR   Ztimestamp_status_kwargstimestamp_statusr.   r.   r/   r'      s      

)readerreturnc                 C   s   t dd t| jS )a:  
    Get the document timestamp chain of the associated reader, ordered
    from new to old.

    :param reader:
        A :class:`.PdfFileReader`.
    :return:
        An iterable of
        :class:`~pyhanko.sign.validation.pdf_embedded.EmbeddedPdfSignature`
        objects representing document timestamps.
    c                 S   s   | j dd dkS )Nz/Typez/DocTimeStamp)Z
sig_objectrJ   )sigr.   r.   r/   <lambda>       z%get_timestamp_chain.<locals>.<lambda>)filterreversedZembedded_signatures)rW   r.   r.   r/   r%      s    c                   @   s.   e Zd ZU eed< eed< eed< eed< dS )_TimestampTrustData
latest_dtsearliest_ts_statusts_chain_lengthcurrent_signature_vc_kwargsN)r4   r5   r6   r   __annotations__r!   intdictr.   r.   r.   r/   r^      s   
r^   )emb_timestampc                 C   s`   z$| j | j}t|}||W S  tk
rZ   |dd |dd tf | Y S X d S )Ncrlsr.   ocsps)	rW   Zget_historical_resolversigned_revisionr   read_dssas_validation_contextr   
setdefaultr	   )rf   rM   Zhist_resolverdssr.   r.   r/   _instantiate_ltv_vc   s    rn   c           	         s   t | }t|}|}d }d}d }t|D ]J\}}|j|k r> qt|  t|j||jI d H }t|j	| t
||}q(t|||d |dS )Nr   )r_   r`   ra   rb   )r%   re   	enumerateri   compute_digestr'   signed_dataexternal_digestrO   rL   rn   r^   )	rW   bootstrap_validation_contextrM   until_revisionZ
timestamps
current_vcZ	ts_statusZts_countrf   r.   r.   r/   _establish_timestamp_trust_lta   s:    
  
  rw   F)embedded_sigvalidation_typert   diff_policykey_usage_settings	skip_diffrX   c	                    s  t |pi }|dd |dd |d }	|rVt|	d|d< |dk	rt|	d|d< n4d|kr|dt|	d |dk	r|dt|	d | j}
|tjkrd}|ptf |}n6t	|
}|dkr|j
|dd	}n|}|j|  |   |   d}d}|tjkr|t|
||| jd
I dH }|j}|jr:t|j|}|jdkrZ|tjkrZtd|tjksv|jdksvt|j}| j}|dk	rt||| jI dH }|j}||d< |dk	r||d< n |tjkr|jdkrtd|dkrtdt|j| d}|tjkr^t | j!\}}||d< ||d< tf |}|dk	r||d< ||d< tf |}nN|tjkr|
|}|dk	r|
|}n"t|j|}|dk	rt|j|}|dk	s|tjkr|dk	r|}n|jj"}t#|t$|d|jid}|I dH }n|}| j%||d | & }|'|j|d t()|}t*| j"| j+|||dI dH }t,| |d dd |dk	rx|j| j- |'t.| j/| j0|| j!d dI dH  t(f |S )a   
    .. versionadded:: 0.9.0

    Validate a PDF LTV signature according to a particular profile.

    :param embedded_sig:
        Embedded signature to evaluate.
    :param validation_type:
        Validation profile to use.
    :param validation_context_kwargs:
        Keyword args to instantiate
        :class:`.pyhanko_certvalidator.ValidationContext` objects needed over
        the course of the validation.
    :param ac_validation_context_kwargs:
        Keyword arguments for the 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 bootstrap_validation_context:
        Validation context used to validate the current timestamp.
    :param force_revinfo:
        Require all certificates encountered to have some form of live
        revocation checking provisions.
    :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.
    :return:
        The status of the signature.
    rD   TrG   FrI   rF   NrH   )Zinclude_revinfo)rM   ru   z>Purported PAdES-LTA signature does not have a timestamp chain.r   rE   zlPAdES-LTA signature requires separate timestamps protecting the signature & the rest of the revocation info.z+LTV signatures require a trusted timestamp.rh   rg   rL   )Z
status_clsrQ   status_kwargs)rz   r|   )Zsigner_reported_dtZtimestamp_validity)Z
raw_digestrQ   r}   r{   Zvalidation_path)Ztimestamp_foundsigned_attrs)Zsd_attr_certificatessigner_certrQ   Zsd_signed_attrs)1re   rl   rA   rC   rW   r"   r8   r	   r   rj   rk   Zcertificate_registryZregister_multipleZ
load_certsrq   Zcompute_tst_digestrw   ri   rb   r_   rn   r`   r:   r   r9   ra   AssertionErrorZattached_timestamp_datar'   Ztst_signature_digestrL   rO   r$   signer_inforr   r   r!   Zcompute_integrity_infoZsummarise_integrity_infoupdater   Zdefault_usage_constraintsr   rs   r   Zother_embedded_certsr   Zembedded_attr_certsr   )rx   ry   rM   rt   Zac_validation_context_kwargsZforce_revinforz   r{   r|   rN   rW   rm   rv   Zts_trust_dataZearliest_good_timestamp_strP   Zsignature_poeZstored_ac_vcrh   rg   Z	stored_vcZts_to_validateZts_status_cororV   r}   r.   r.   r/   r&     sR   3

 
  
  


	
 



 
 

      

	)r   c              
   C   sl   zt | d d}W n0 ttfk
rB } ztd|W 5 d}~X Y nX t|d pPd}t|d p`d}||fS )a'  
    Retrieve Adobe-style revocation information from a ``SignerInfo`` value,
    if present.

    Internal API.

    :param signer_info:
        A ``SignerInfo`` value.
    :return:
        A tuple of two (potentially empty) lists, containing OCSP
        responses and CRLs, respectively.
    r~   Zadobe_revocation_info_archivalz@No revocation info archival attribute found, or multiple presentNZocspr.   Zcrl)r   r   r   r   list)r   Zrevinfoerh   rg   r.   r.   r/   r$   &  s     )r   rX   c                 C   s(   |pi }t | \}}tf ||d|S )ag  
    Read Adobe-style revocation information from a CMS object, and load it
    into a validation context.

    :param signer_info:
        Signer info CMS object.
    :param validation_context_kwargs:
        Extra kwargs to pass to the ``__init__`` function.
    :return:
        A validation context preloaded with the relevant revocation information.
    )rh   rg   )r$   r	   )r   rM   rh   rg   r.   r.   r/   r#   A  s     )NNNFNNF)N)HloggingZdataclassesr   enumr   typingr   r   r   Z
asn1cryptor   r   Zasn1_pdfZpyhanko_certvalidatorr	   Z!pyhanko_certvalidator.policy_declr
   r   r   Zpyhanko.pdf_utils.readerr   Zdiff_analysisr   Zgeneralr   r   r   rm   r   errorsr   r   r   Zgeneric_cmsr   r   r   r   Zpdf_embeddedr   r   settingsr   statusr   r    r!   __all__	getLoggerr4   rS   r(   r"   ZCHECK_IF_DECLAREDr>   rA   ZCRL_OR_OCSP_REQUIREDrB   rC   rO   Z
SignedDatabytesr'   r%   r^   rn   rw   boolr&   Z
SignerInfor$   r#   r.   r.   r.   r/   <module>   s     
#)-           